availability: Add optional groups and implement guestfs_available call.
[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 Unix
39 open Printf
40
41 type style = ret * args
42 and ret =
43     (* "RErr" as a return value means an int used as a simple error
44      * indication, ie. 0 or -1.
45      *)
46   | RErr
47
48     (* "RInt" as a return value means an int which is -1 for error
49      * or any value >= 0 on success.  Only use this for smallish
50      * positive ints (0 <= i < 2^30).
51      *)
52   | RInt of string
53
54     (* "RInt64" is the same as RInt, but is guaranteed to be able
55      * to return a full 64 bit value, _except_ that -1 means error
56      * (so -1 cannot be a valid, non-error return value).
57      *)
58   | RInt64 of string
59
60     (* "RBool" is a bool return value which can be true/false or
61      * -1 for error.
62      *)
63   | RBool of string
64
65     (* "RConstString" is a string that refers to a constant value.
66      * The return value must NOT be NULL (since NULL indicates
67      * an error).
68      *
69      * Try to avoid using this.  In particular you cannot use this
70      * for values returned from the daemon, because there is no
71      * thread-safe way to return them in the C API.
72      *)
73   | RConstString of string
74
75     (* "RConstOptString" is an even more broken version of
76      * "RConstString".  The returned string may be NULL and there
77      * is no way to return an error indication.  Avoid using this!
78      *)
79   | RConstOptString of string
80
81     (* "RString" is a returned string.  It must NOT be NULL, since
82      * a NULL return indicates an error.  The caller frees this.
83      *)
84   | RString of string
85
86     (* "RStringList" is a list of strings.  No string in the list
87      * can be NULL.  The caller frees the strings and the array.
88      *)
89   | RStringList of string
90
91     (* "RStruct" is a function which returns a single named structure
92      * or an error indication (in C, a struct, and in other languages
93      * with varying representations, but usually very efficient).  See
94      * after the function list below for the structures.
95      *)
96   | RStruct of string * string          (* name of retval, name of struct *)
97
98     (* "RStructList" is a function which returns either a list/array
99      * of structures (could be zero-length), or an error indication.
100      *)
101   | RStructList of string * string      (* name of retval, name of struct *)
102
103     (* Key-value pairs of untyped strings.  Turns into a hashtable or
104      * dictionary in languages which support it.  DON'T use this as a
105      * general "bucket" for results.  Prefer a stronger typed return
106      * value if one is available, or write a custom struct.  Don't use
107      * this if the list could potentially be very long, since it is
108      * inefficient.  Keys should be unique.  NULLs are not permitted.
109      *)
110   | RHashtable of string
111
112     (* "RBufferOut" is handled almost exactly like RString, but
113      * it allows the string to contain arbitrary 8 bit data including
114      * ASCII NUL.  In the C API this causes an implicit extra parameter
115      * to be added of type <size_t *size_r>.  The extra parameter
116      * returns the actual size of the return buffer in bytes.
117      *
118      * Other programming languages support strings with arbitrary 8 bit
119      * data.
120      *
121      * At the RPC layer we have to use the opaque<> type instead of
122      * string<>.  Returned data is still limited to the max message
123      * size (ie. ~ 2 MB).
124      *)
125   | RBufferOut of string
126
127 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
128
129     (* Note in future we should allow a "variable args" parameter as
130      * the final parameter, to allow commands like
131      *   chmod mode file [file(s)...]
132      * This is not implemented yet, but many commands (such as chmod)
133      * are currently defined with the argument order keeping this future
134      * possibility in mind.
135      *)
136 and argt =
137   | String of string    (* const char *name, cannot be NULL *)
138   | Device of string    (* /dev device name, cannot be NULL *)
139   | Pathname of string  (* file name, cannot be NULL *)
140   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
141   | OptString of string (* const char *name, may be NULL *)
142   | StringList of string(* list of strings (each string cannot be NULL) *)
143   | DeviceList of string(* list of Device names (each cannot be NULL) *)
144   | Bool of string      (* boolean *)
145   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
146   | Int64 of string     (* any 64 bit int *)
147     (* These are treated as filenames (simple string parameters) in
148      * the C API and bindings.  But in the RPC protocol, we transfer
149      * the actual file content up to or down from the daemon.
150      * FileIn: local machine -> daemon (in request)
151      * FileOut: daemon -> local machine (in reply)
152      * In guestfish (only), the special name "-" means read from
153      * stdin or write to stdout.
154      *)
155   | FileIn of string
156   | FileOut of string
157 (* Not implemented:
158     (* Opaque buffer which can contain arbitrary 8 bit data.
159      * In the C API, this is expressed as <char *, int> pair.
160      * Most other languages have a string type which can contain
161      * ASCII NUL.  We use whatever type is appropriate for each
162      * language.
163      * Buffers are limited by the total message size.  To transfer
164      * large blocks of data, use FileIn/FileOut parameters instead.
165      * To return an arbitrary buffer, use RBufferOut.
166      *)
167   | BufferIn of string
168 *)
169
170 type flags =
171   | ProtocolLimitWarning  (* display warning about protocol size limits *)
172   | DangerWillRobinson    (* flags particularly dangerous commands *)
173   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
174   | FishAction of string  (* call this function in guestfish *)
175   | NotInFish             (* do not export via guestfish *)
176   | NotInDocs             (* do not add this function to documentation *)
177   | DeprecatedBy of string (* function is deprecated, use .. instead *)
178   | Optional of string    (* function is part of an optional group *)
179
180 (* You can supply zero or as many tests as you want per API call.
181  *
182  * Note that the test environment has 3 block devices, of size 500MB,
183  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
184  * a fourth ISO block device with some known files on it (/dev/sdd).
185  *
186  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
187  * Number of cylinders was 63 for IDE emulated disks with precisely
188  * the same size.  How exactly this is calculated is a mystery.
189  *
190  * The ISO block device (/dev/sdd) comes from images/test.iso.
191  *
192  * To be able to run the tests in a reasonable amount of time,
193  * the virtual machine and block devices are reused between tests.
194  * So don't try testing kill_subprocess :-x
195  *
196  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
197  *
198  * Don't assume anything about the previous contents of the block
199  * devices.  Use 'Init*' to create some initial scenarios.
200  *
201  * You can add a prerequisite clause to any individual test.  This
202  * is a run-time check, which, if it fails, causes the test to be
203  * skipped.  Useful if testing a command which might not work on
204  * all variations of libguestfs builds.  A test that has prerequisite
205  * of 'Always' is run unconditionally.
206  *
207  * In addition, packagers can skip individual tests by setting the
208  * environment variables:     eg:
209  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
210  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
211  *)
212 type tests = (test_init * test_prereq * test) list
213 and test =
214     (* Run the command sequence and just expect nothing to fail. *)
215   | TestRun of seq
216
217     (* Run the command sequence and expect the output of the final
218      * command to be the string.
219      *)
220   | TestOutput of seq * string
221
222     (* Run the command sequence and expect the output of the final
223      * command to be the list of strings.
224      *)
225   | TestOutputList of seq * string list
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the list of block devices (could be either
229      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
230      * character of each string).
231      *)
232   | TestOutputListOfDevices of seq * string list
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the integer.
236      *)
237   | TestOutputInt of seq * int
238
239     (* Run the command sequence and expect the output of the final
240      * command to be <op> <int>, eg. ">=", "1".
241      *)
242   | TestOutputIntOp of seq * string * int
243
244     (* Run the command sequence and expect the output of the final
245      * command to be a true value (!= 0 or != NULL).
246      *)
247   | TestOutputTrue of seq
248
249     (* Run the command sequence and expect the output of the final
250      * command to be a false value (== 0 or == NULL, but not an error).
251      *)
252   | TestOutputFalse of seq
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a list of the given length (but don't care about
256      * content).
257      *)
258   | TestOutputLength of seq * int
259
260     (* Run the command sequence and expect the output of the final
261      * command to be a buffer (RBufferOut), ie. string + size.
262      *)
263   | TestOutputBuffer of seq * string
264
265     (* Run the command sequence and expect the output of the final
266      * command to be a structure.
267      *)
268   | TestOutputStruct of seq * test_field_compare list
269
270     (* Run the command sequence and expect the final command (only)
271      * to fail.
272      *)
273   | TestLastFail of seq
274
275 and test_field_compare =
276   | CompareWithInt of string * int
277   | CompareWithIntOp of string * string * int
278   | CompareWithString of string * string
279   | CompareFieldsIntEq of string * string
280   | CompareFieldsStrEq of string * string
281
282 (* Test prerequisites. *)
283 and test_prereq =
284     (* Test always runs. *)
285   | Always
286
287     (* Test is currently disabled - eg. it fails, or it tests some
288      * unimplemented feature.
289      *)
290   | Disabled
291
292     (* 'string' is some C code (a function body) that should return
293      * true or false.  The test will run if the code returns true.
294      *)
295   | If of string
296
297     (* As for 'If' but the test runs _unless_ the code returns true. *)
298   | Unless of string
299
300 (* Some initial scenarios for testing. *)
301 and test_init =
302     (* Do nothing, block devices could contain random stuff including
303      * LVM PVs, and some filesystems might be mounted.  This is usually
304      * a bad idea.
305      *)
306   | InitNone
307
308     (* Block devices are empty and no filesystems are mounted. *)
309   | InitEmpty
310
311     (* /dev/sda contains a single partition /dev/sda1, with random
312      * content.  /dev/sdb and /dev/sdc may have random content.
313      * No LVM.
314      *)
315   | InitPartition
316
317     (* /dev/sda contains a single partition /dev/sda1, which is formatted
318      * as ext2, empty [except for lost+found] and mounted on /.
319      * /dev/sdb and /dev/sdc may have random content.
320      * No LVM.
321      *)
322   | InitBasicFS
323
324     (* /dev/sda:
325      *   /dev/sda1 (is a PV):
326      *     /dev/VG/LV (size 8MB):
327      *       formatted as ext2, empty [except for lost+found], mounted on /
328      * /dev/sdb and /dev/sdc may have random content.
329      *)
330   | InitBasicFSonLVM
331
332     (* /dev/sdd (the ISO, see images/ directory in source)
333      * is mounted on /
334      *)
335   | InitISOFS
336
337 (* Sequence of commands for testing. *)
338 and seq = cmd list
339 and cmd = string list
340
341 (* Note about long descriptions: When referring to another
342  * action, use the format C<guestfs_other> (ie. the full name of
343  * the C function).  This will be replaced as appropriate in other
344  * language bindings.
345  *
346  * Apart from that, long descriptions are just perldoc paragraphs.
347  *)
348
349 (* Generate a random UUID (used in tests). *)
350 let uuidgen () =
351   let chan = open_process_in "uuidgen" in
352   let uuid = input_line chan in
353   (match close_process_in chan with
354    | WEXITED 0 -> ()
355    | WEXITED _ ->
356        failwith "uuidgen: process exited with non-zero status"
357    | WSIGNALED _ | WSTOPPED _ ->
358        failwith "uuidgen: process signalled or stopped by signal"
359   );
360   uuid
361
362 (* These test functions are used in the language binding tests. *)
363
364 let test_all_args = [
365   String "str";
366   OptString "optstr";
367   StringList "strlist";
368   Bool "b";
369   Int "integer";
370   Int64 "integer64";
371   FileIn "filein";
372   FileOut "fileout";
373 ]
374
375 let test_all_rets = [
376   (* except for RErr, which is tested thoroughly elsewhere *)
377   "test0rint",         RInt "valout";
378   "test0rint64",       RInt64 "valout";
379   "test0rbool",        RBool "valout";
380   "test0rconststring", RConstString "valout";
381   "test0rconstoptstring", RConstOptString "valout";
382   "test0rstring",      RString "valout";
383   "test0rstringlist",  RStringList "valout";
384   "test0rstruct",      RStruct ("valout", "lvm_pv");
385   "test0rstructlist",  RStructList ("valout", "lvm_pv");
386   "test0rhashtable",   RHashtable "valout";
387 ]
388
389 let test_functions = [
390   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
391    [],
392    "internal test function - do not use",
393    "\
394 This is an internal test function which is used to test whether
395 the automatically generated bindings can handle every possible
396 parameter type correctly.
397
398 It echos the contents of each parameter to stdout.
399
400 You probably don't want to call this function.");
401 ] @ List.flatten (
402   List.map (
403     fun (name, ret) ->
404       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
405         [],
406         "internal test function - do not use",
407         "\
408 This is an internal test function which is used to test whether
409 the automatically generated bindings can handle every possible
410 return type correctly.
411
412 It converts string C<val> to the return type.
413
414 You probably don't want to call this function.");
415        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
416         [],
417         "internal test function - do not use",
418         "\
419 This is an internal test function which is used to test whether
420 the automatically generated bindings can handle every possible
421 return type correctly.
422
423 This function always returns an error.
424
425 You probably don't want to call this function.")]
426   ) test_all_rets
427 )
428
429 (* non_daemon_functions are any functions which don't get processed
430  * in the daemon, eg. functions for setting and getting local
431  * configuration values.
432  *)
433
434 let non_daemon_functions = test_functions @ [
435   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
436    [],
437    "launch the qemu subprocess",
438    "\
439 Internally libguestfs is implemented by running a virtual machine
440 using L<qemu(1)>.
441
442 You should call this after configuring the handle
443 (eg. adding drives) but before performing any actions.");
444
445   ("wait_ready", (RErr, []), -1, [NotInFish],
446    [],
447    "wait until the qemu subprocess launches (no op)",
448    "\
449 This function is a no op.
450
451 In versions of the API E<lt> 1.0.71 you had to call this function
452 just after calling C<guestfs_launch> to wait for the launch
453 to complete.  However this is no longer necessary because
454 C<guestfs_launch> now does the waiting.
455
456 If you see any calls to this function in code then you can just
457 remove them, unless you want to retain compatibility with older
458 versions of the API.");
459
460   ("kill_subprocess", (RErr, []), -1, [],
461    [],
462    "kill the qemu subprocess",
463    "\
464 This kills the qemu subprocess.  You should never need to call this.");
465
466   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
467    [],
468    "add an image to examine or modify",
469    "\
470 This function adds a virtual machine disk image C<filename> to the
471 guest.  The first time you call this function, the disk appears as IDE
472 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
473 so on.
474
475 You don't necessarily need to be root when using libguestfs.  However
476 you obviously do need sufficient permissions to access the filename
477 for whatever operations you want to perform (ie. read access if you
478 just want to read the image or write access if you want to modify the
479 image).
480
481 This is equivalent to the qemu parameter
482 C<-drive file=filename,cache=off,if=...>.
483 C<cache=off> is omitted in cases where it is not supported by
484 the underlying filesystem.
485
486 Note that this call checks for the existence of C<filename>.  This
487 stops you from specifying other types of drive which are supported
488 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
489 the general C<guestfs_config> call instead.");
490
491   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
492    [],
493    "add a CD-ROM disk image to examine",
494    "\
495 This function adds a virtual CD-ROM disk image to the guest.
496
497 This is equivalent to the qemu parameter C<-cdrom filename>.
498
499 Note that this call checks for the existence of C<filename>.  This
500 stops you from specifying other types of drive which are supported
501 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
502 the general C<guestfs_config> call instead.");
503
504   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
505    [],
506    "add a drive in snapshot mode (read-only)",
507    "\
508 This adds a drive in snapshot mode, making it effectively
509 read-only.
510
511 Note that writes to the device are allowed, and will be seen for
512 the duration of the guestfs handle, but they are written
513 to a temporary file which is discarded as soon as the guestfs
514 handle is closed.  We don't currently have any method to enable
515 changes to be committed, although qemu can support this.
516
517 This is equivalent to the qemu parameter
518 C<-drive file=filename,snapshot=on,if=...>.
519
520 Note that this call checks for the existence of C<filename>.  This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
523 the general C<guestfs_config> call instead.");
524
525   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
526    [],
527    "add qemu parameters",
528    "\
529 This can be used to add arbitrary qemu command line parameters
530 of the form C<-param value>.  Actually it's not quite arbitrary - we
531 prevent you from setting some parameters which would interfere with
532 parameters that we use.
533
534 The first character of C<param> string must be a C<-> (dash).
535
536 C<value> can be NULL.");
537
538   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
539    [],
540    "set the qemu binary",
541    "\
542 Set the qemu binary that we will use.
543
544 The default is chosen when the library was compiled by the
545 configure script.
546
547 You can also override this by setting the C<LIBGUESTFS_QEMU>
548 environment variable.
549
550 Setting C<qemu> to C<NULL> restores the default qemu binary.");
551
552   ("get_qemu", (RConstString "qemu", []), -1, [],
553    [InitNone, Always, TestRun (
554       [["get_qemu"]])],
555    "get the qemu binary",
556    "\
557 Return the current qemu binary.
558
559 This is always non-NULL.  If it wasn't set already, then this will
560 return the default qemu binary name.");
561
562   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
563    [],
564    "set the search path",
565    "\
566 Set the path that libguestfs searches for kernel and initrd.img.
567
568 The default is C<$libdir/guestfs> unless overridden by setting
569 C<LIBGUESTFS_PATH> environment variable.
570
571 Setting C<path> to C<NULL> restores the default path.");
572
573   ("get_path", (RConstString "path", []), -1, [],
574    [InitNone, Always, TestRun (
575       [["get_path"]])],
576    "get the search path",
577    "\
578 Return the current search path.
579
580 This is always non-NULL.  If it wasn't set already, then this will
581 return the default path.");
582
583   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
584    [],
585    "add options to kernel command line",
586    "\
587 This function is used to add additional options to the
588 guest kernel command line.
589
590 The default is C<NULL> unless overridden by setting
591 C<LIBGUESTFS_APPEND> environment variable.
592
593 Setting C<append> to C<NULL> means I<no> additional options
594 are passed (libguestfs always adds a few of its own).");
595
596   ("get_append", (RConstOptString "append", []), -1, [],
597    (* This cannot be tested with the current framework.  The
598     * function can return NULL in normal operations, which the
599     * test framework interprets as an error.
600     *)
601    [],
602    "get the additional kernel options",
603    "\
604 Return the additional kernel options which are added to the
605 guest kernel command line.
606
607 If C<NULL> then no options are added.");
608
609   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
610    [],
611    "set autosync mode",
612    "\
613 If C<autosync> is true, this enables autosync.  Libguestfs will make a
614 best effort attempt to run C<guestfs_umount_all> followed by
615 C<guestfs_sync> when the handle is closed
616 (also if the program exits without closing handles).
617
618 This is disabled by default (except in guestfish where it is
619 enabled by default).");
620
621   ("get_autosync", (RBool "autosync", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_autosync"]])],
624    "get autosync mode",
625    "\
626 Get the autosync flag.");
627
628   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
629    [],
630    "set verbose mode",
631    "\
632 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
633
634 Verbose messages are disabled unless the environment variable
635 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
636
637   ("get_verbose", (RBool "verbose", []), -1, [],
638    [],
639    "get verbose mode",
640    "\
641 This returns the verbose messages flag.");
642
643   ("is_ready", (RBool "ready", []), -1, [],
644    [InitNone, Always, TestOutputTrue (
645       [["is_ready"]])],
646    "is ready to accept commands",
647    "\
648 This returns true iff this handle is ready to accept commands
649 (in the C<READY> state).
650
651 For more information on states, see L<guestfs(3)>.");
652
653   ("is_config", (RBool "config", []), -1, [],
654    [InitNone, Always, TestOutputFalse (
655       [["is_config"]])],
656    "is in configuration state",
657    "\
658 This returns true iff this handle is being configured
659 (in the C<CONFIG> state).
660
661 For more information on states, see L<guestfs(3)>.");
662
663   ("is_launching", (RBool "launching", []), -1, [],
664    [InitNone, Always, TestOutputFalse (
665       [["is_launching"]])],
666    "is launching subprocess",
667    "\
668 This returns true iff this handle is launching the subprocess
669 (in the C<LAUNCHING> state).
670
671 For more information on states, see L<guestfs(3)>.");
672
673   ("is_busy", (RBool "busy", []), -1, [],
674    [InitNone, Always, TestOutputFalse (
675       [["is_busy"]])],
676    "is busy processing a command",
677    "\
678 This returns true iff this handle is busy processing a command
679 (in the C<BUSY> state).
680
681 For more information on states, see L<guestfs(3)>.");
682
683   ("get_state", (RInt "state", []), -1, [],
684    [],
685    "get the current state",
686    "\
687 This returns the current state as an opaque integer.  This is
688 only useful for printing debug and internal error messages.
689
690 For more information on states, see L<guestfs(3)>.");
691
692   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
693    [InitNone, Always, TestOutputInt (
694       [["set_memsize"; "500"];
695        ["get_memsize"]], 500)],
696    "set memory allocated to the qemu subprocess",
697    "\
698 This sets the memory size in megabytes allocated to the
699 qemu subprocess.  This only has any effect if called before
700 C<guestfs_launch>.
701
702 You can also change this by setting the environment
703 variable C<LIBGUESTFS_MEMSIZE> before the handle is
704 created.
705
706 For more information on the architecture of libguestfs,
707 see L<guestfs(3)>.");
708
709   ("get_memsize", (RInt "memsize", []), -1, [],
710    [InitNone, Always, TestOutputIntOp (
711       [["get_memsize"]], ">=", 256)],
712    "get memory allocated to the qemu subprocess",
713    "\
714 This gets the memory size in megabytes allocated to the
715 qemu subprocess.
716
717 If C<guestfs_set_memsize> was not called
718 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
719 then this returns the compiled-in default value for memsize.
720
721 For more information on the architecture of libguestfs,
722 see L<guestfs(3)>.");
723
724   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
725    [InitNone, Always, TestOutputIntOp (
726       [["get_pid"]], ">=", 1)],
727    "get PID of qemu subprocess",
728    "\
729 Return the process ID of the qemu subprocess.  If there is no
730 qemu subprocess, then this will return an error.
731
732 This is an internal call used for debugging and testing.");
733
734   ("version", (RStruct ("version", "version"), []), -1, [],
735    [InitNone, Always, TestOutputStruct (
736       [["version"]], [CompareWithInt ("major", 1)])],
737    "get the library version number",
738    "\
739 Return the libguestfs version number that the program is linked
740 against.
741
742 Note that because of dynamic linking this is not necessarily
743 the version of libguestfs that you compiled against.  You can
744 compile the program, and then at runtime dynamically link
745 against a completely different C<libguestfs.so> library.
746
747 This call was added in version C<1.0.58>.  In previous
748 versions of libguestfs there was no way to get the version
749 number.  From C code you can use ELF weak linking tricks to find out if
750 this symbol exists (if it doesn't, then it's an earlier version).
751
752 The call returns a structure with four elements.  The first
753 three (C<major>, C<minor> and C<release>) are numbers and
754 correspond to the usual version triplet.  The fourth element
755 (C<extra>) is a string and is normally empty, but may be
756 used for distro-specific information.
757
758 To construct the original version string:
759 C<$major.$minor.$release$extra>
760
761 I<Note:> Don't use this call to test for availability
762 of features.  Distro backports makes this unreliable.  Use
763 C<guestfs_available> instead.");
764
765   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
766    [InitNone, Always, TestOutputTrue (
767       [["set_selinux"; "true"];
768        ["get_selinux"]])],
769    "set SELinux enabled or disabled at appliance boot",
770    "\
771 This sets the selinux flag that is passed to the appliance
772 at boot time.  The default is C<selinux=0> (disabled).
773
774 Note that if SELinux is enabled, it is always in
775 Permissive mode (C<enforcing=0>).
776
777 For more information on the architecture of libguestfs,
778 see L<guestfs(3)>.");
779
780   ("get_selinux", (RBool "selinux", []), -1, [],
781    [],
782    "get SELinux enabled flag",
783    "\
784 This returns the current setting of the selinux flag which
785 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
786
787 For more information on the architecture of libguestfs,
788 see L<guestfs(3)>.");
789
790   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
791    [InitNone, Always, TestOutputFalse (
792       [["set_trace"; "false"];
793        ["get_trace"]])],
794    "enable or disable command traces",
795    "\
796 If the command trace flag is set to 1, then commands are
797 printed on stdout before they are executed in a format
798 which is very similar to the one used by guestfish.  In
799 other words, you can run a program with this enabled, and
800 you will get out a script which you can feed to guestfish
801 to perform the same set of actions.
802
803 If you want to trace C API calls into libguestfs (and
804 other libraries) then possibly a better way is to use
805 the external ltrace(1) command.
806
807 Command traces are disabled unless the environment variable
808 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
809
810   ("get_trace", (RBool "trace", []), -1, [],
811    [],
812    "get command trace enabled flag",
813    "\
814 Return the command trace flag.");
815
816   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
817    [InitNone, Always, TestOutputFalse (
818       [["set_direct"; "false"];
819        ["get_direct"]])],
820    "enable or disable direct appliance mode",
821    "\
822 If the direct appliance mode flag is enabled, then stdin and
823 stdout are passed directly through to the appliance once it
824 is launched.
825
826 One consequence of this is that log messages aren't caught
827 by the library and handled by C<guestfs_set_log_message_callback>,
828 but go straight to stdout.
829
830 You probably don't want to use this unless you know what you
831 are doing.
832
833 The default is disabled.");
834
835   ("get_direct", (RBool "direct", []), -1, [],
836    [],
837    "get direct appliance mode flag",
838    "\
839 Return the direct appliance mode flag.");
840
841   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
842    [InitNone, Always, TestOutputTrue (
843       [["set_recovery_proc"; "true"];
844        ["get_recovery_proc"]])],
845    "enable or disable the recovery process",
846    "\
847 If this is called with the parameter C<false> then
848 C<guestfs_launch> does not create a recovery process.  The
849 purpose of the recovery process is to stop runaway qemu
850 processes in the case where the main program aborts abruptly.
851
852 This only has any effect if called before C<guestfs_launch>,
853 and the default is true.
854
855 About the only time when you would want to disable this is
856 if the main process will fork itself into the background
857 (\"daemonize\" itself).  In this case the recovery process
858 thinks that the main program has disappeared and so kills
859 qemu, which is not very helpful.");
860
861   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
862    [],
863    "get recovery process enabled flag",
864    "\
865 Return the recovery process enabled flag.");
866
867 ]
868
869 (* daemon_functions are any functions which cause some action
870  * to take place in the daemon.
871  *)
872
873 let daemon_functions = [
874   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
875    [InitEmpty, Always, TestOutput (
876       [["part_disk"; "/dev/sda"; "mbr"];
877        ["mkfs"; "ext2"; "/dev/sda1"];
878        ["mount"; "/dev/sda1"; "/"];
879        ["write_file"; "/new"; "new file contents"; "0"];
880        ["cat"; "/new"]], "new file contents")],
881    "mount a guest disk at a position in the filesystem",
882    "\
883 Mount a guest disk at a position in the filesystem.  Block devices
884 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
885 the guest.  If those block devices contain partitions, they will have
886 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
887 names can be used.
888
889 The rules are the same as for L<mount(2)>:  A filesystem must
890 first be mounted on C</> before others can be mounted.  Other
891 filesystems can only be mounted on directories which already
892 exist.
893
894 The mounted filesystem is writable, if we have sufficient permissions
895 on the underlying device.
896
897 The filesystem options C<sync> and C<noatime> are set with this
898 call, in order to improve reliability.");
899
900   ("sync", (RErr, []), 2, [],
901    [ InitEmpty, Always, TestRun [["sync"]]],
902    "sync disks, writes are flushed through to the disk image",
903    "\
904 This syncs the disk, so that any writes are flushed through to the
905 underlying disk image.
906
907 You should always call this if you have modified a disk image, before
908 closing the handle.");
909
910   ("touch", (RErr, [Pathname "path"]), 3, [],
911    [InitBasicFS, Always, TestOutputTrue (
912       [["touch"; "/new"];
913        ["exists"; "/new"]])],
914    "update file timestamps or create a new file",
915    "\
916 Touch acts like the L<touch(1)> command.  It can be used to
917 update the timestamps on a file, or, if the file does not exist,
918 to create a new zero-length file.");
919
920   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
921    [InitISOFS, Always, TestOutput (
922       [["cat"; "/known-2"]], "abcdef\n")],
923    "list the contents of a file",
924    "\
925 Return the contents of the file named C<path>.
926
927 Note that this function cannot correctly handle binary files
928 (specifically, files containing C<\\0> character which is treated
929 as end of string).  For those you need to use the C<guestfs_read_file>
930 or C<guestfs_download> functions which have a more complex interface.");
931
932   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
933    [], (* XXX Tricky to test because it depends on the exact format
934         * of the 'ls -l' command, which changes between F10 and F11.
935         *)
936    "list the files in a directory (long format)",
937    "\
938 List the files in C<directory> (relative to the root directory,
939 there is no cwd) in the format of 'ls -la'.
940
941 This command is mostly useful for interactive sessions.  It
942 is I<not> intended that you try to parse the output string.");
943
944   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
945    [InitBasicFS, Always, TestOutputList (
946       [["touch"; "/new"];
947        ["touch"; "/newer"];
948        ["touch"; "/newest"];
949        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
950    "list the files in a directory",
951    "\
952 List the files in C<directory> (relative to the root directory,
953 there is no cwd).  The '.' and '..' entries are not returned, but
954 hidden files are shown.
955
956 This command is mostly useful for interactive sessions.  Programs
957 should probably use C<guestfs_readdir> instead.");
958
959   ("list_devices", (RStringList "devices", []), 7, [],
960    [InitEmpty, Always, TestOutputListOfDevices (
961       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
962    "list the block devices",
963    "\
964 List all the block devices.
965
966 The full block device names are returned, eg. C</dev/sda>");
967
968   ("list_partitions", (RStringList "partitions", []), 8, [],
969    [InitBasicFS, Always, TestOutputListOfDevices (
970       [["list_partitions"]], ["/dev/sda1"]);
971     InitEmpty, Always, TestOutputListOfDevices (
972       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
973        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
974    "list the partitions",
975    "\
976 List all the partitions detected on all block devices.
977
978 The full partition device names are returned, eg. C</dev/sda1>
979
980 This does not return logical volumes.  For that you will need to
981 call C<guestfs_lvs>.");
982
983   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
984    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
985       [["pvs"]], ["/dev/sda1"]);
986     InitEmpty, Always, TestOutputListOfDevices (
987       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
988        ["pvcreate"; "/dev/sda1"];
989        ["pvcreate"; "/dev/sda2"];
990        ["pvcreate"; "/dev/sda3"];
991        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
992    "list the LVM physical volumes (PVs)",
993    "\
994 List all the physical volumes detected.  This is the equivalent
995 of the L<pvs(8)> command.
996
997 This returns a list of just the device names that contain
998 PVs (eg. C</dev/sda2>).
999
1000 See also C<guestfs_pvs_full>.");
1001
1002   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1003    [InitBasicFSonLVM, Always, TestOutputList (
1004       [["vgs"]], ["VG"]);
1005     InitEmpty, Always, TestOutputList (
1006       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1007        ["pvcreate"; "/dev/sda1"];
1008        ["pvcreate"; "/dev/sda2"];
1009        ["pvcreate"; "/dev/sda3"];
1010        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1011        ["vgcreate"; "VG2"; "/dev/sda3"];
1012        ["vgs"]], ["VG1"; "VG2"])],
1013    "list the LVM volume groups (VGs)",
1014    "\
1015 List all the volumes groups detected.  This is the equivalent
1016 of the L<vgs(8)> command.
1017
1018 This returns a list of just the volume group names that were
1019 detected (eg. C<VolGroup00>).
1020
1021 See also C<guestfs_vgs_full>.");
1022
1023   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1024    [InitBasicFSonLVM, Always, TestOutputList (
1025       [["lvs"]], ["/dev/VG/LV"]);
1026     InitEmpty, Always, TestOutputList (
1027       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1028        ["pvcreate"; "/dev/sda1"];
1029        ["pvcreate"; "/dev/sda2"];
1030        ["pvcreate"; "/dev/sda3"];
1031        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1032        ["vgcreate"; "VG2"; "/dev/sda3"];
1033        ["lvcreate"; "LV1"; "VG1"; "50"];
1034        ["lvcreate"; "LV2"; "VG1"; "50"];
1035        ["lvcreate"; "LV3"; "VG2"; "50"];
1036        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1037    "list the LVM logical volumes (LVs)",
1038    "\
1039 List all the logical volumes detected.  This is the equivalent
1040 of the L<lvs(8)> command.
1041
1042 This returns a list of the logical volume device names
1043 (eg. C</dev/VolGroup00/LogVol00>).
1044
1045 See also C<guestfs_lvs_full>.");
1046
1047   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1048    [], (* XXX how to test? *)
1049    "list the LVM physical volumes (PVs)",
1050    "\
1051 List all the physical volumes detected.  This is the equivalent
1052 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1053
1054   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1055    [], (* XXX how to test? *)
1056    "list the LVM volume groups (VGs)",
1057    "\
1058 List all the volumes groups detected.  This is the equivalent
1059 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1060
1061   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1062    [], (* XXX how to test? *)
1063    "list the LVM logical volumes (LVs)",
1064    "\
1065 List all the logical volumes detected.  This is the equivalent
1066 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1067
1068   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1069    [InitISOFS, Always, TestOutputList (
1070       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1071     InitISOFS, Always, TestOutputList (
1072       [["read_lines"; "/empty"]], [])],
1073    "read file as lines",
1074    "\
1075 Return the contents of the file named C<path>.
1076
1077 The file contents are returned as a list of lines.  Trailing
1078 C<LF> and C<CRLF> character sequences are I<not> returned.
1079
1080 Note that this function cannot correctly handle binary files
1081 (specifically, files containing C<\\0> character which is treated
1082 as end of line).  For those you need to use the C<guestfs_read_file>
1083 function which has a more complex interface.");
1084
1085   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1086    [], (* XXX Augeas code needs tests. *)
1087    "create a new Augeas handle",
1088    "\
1089 Create a new Augeas handle for editing configuration files.
1090 If there was any previous Augeas handle associated with this
1091 guestfs session, then it is closed.
1092
1093 You must call this before using any other C<guestfs_aug_*>
1094 commands.
1095
1096 C<root> is the filesystem root.  C<root> must not be NULL,
1097 use C</> instead.
1098
1099 The flags are the same as the flags defined in
1100 E<lt>augeas.hE<gt>, the logical I<or> of the following
1101 integers:
1102
1103 =over 4
1104
1105 =item C<AUG_SAVE_BACKUP> = 1
1106
1107 Keep the original file with a C<.augsave> extension.
1108
1109 =item C<AUG_SAVE_NEWFILE> = 2
1110
1111 Save changes into a file with extension C<.augnew>, and
1112 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1113
1114 =item C<AUG_TYPE_CHECK> = 4
1115
1116 Typecheck lenses (can be expensive).
1117
1118 =item C<AUG_NO_STDINC> = 8
1119
1120 Do not use standard load path for modules.
1121
1122 =item C<AUG_SAVE_NOOP> = 16
1123
1124 Make save a no-op, just record what would have been changed.
1125
1126 =item C<AUG_NO_LOAD> = 32
1127
1128 Do not load the tree in C<guestfs_aug_init>.
1129
1130 =back
1131
1132 To close the handle, you can call C<guestfs_aug_close>.
1133
1134 To find out more about Augeas, see L<http://augeas.net/>.");
1135
1136   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1137    [], (* XXX Augeas code needs tests. *)
1138    "close the current Augeas handle",
1139    "\
1140 Close the current Augeas handle and free up any resources
1141 used by it.  After calling this, you have to call
1142 C<guestfs_aug_init> again before you can use any other
1143 Augeas functions.");
1144
1145   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1146    [], (* XXX Augeas code needs tests. *)
1147    "define an Augeas variable",
1148    "\
1149 Defines an Augeas variable C<name> whose value is the result
1150 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1151 undefined.
1152
1153 On success this returns the number of nodes in C<expr>, or
1154 C<0> if C<expr> evaluates to something which is not a nodeset.");
1155
1156   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "define an Augeas node",
1159    "\
1160 Defines a variable C<name> whose value is the result of
1161 evaluating C<expr>.
1162
1163 If C<expr> evaluates to an empty nodeset, a node is created,
1164 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1165 C<name> will be the nodeset containing that single node.
1166
1167 On success this returns a pair containing the
1168 number of nodes in the nodeset, and a boolean flag
1169 if a node was created.");
1170
1171   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1172    [], (* XXX Augeas code needs tests. *)
1173    "look up the value of an Augeas path",
1174    "\
1175 Look up the value associated with C<path>.  If C<path>
1176 matches exactly one node, the C<value> is returned.");
1177
1178   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1179    [], (* XXX Augeas code needs tests. *)
1180    "set Augeas path to value",
1181    "\
1182 Set the value associated with C<path> to C<value>.");
1183
1184   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1185    [], (* XXX Augeas code needs tests. *)
1186    "insert a sibling Augeas node",
1187    "\
1188 Create a new sibling C<label> for C<path>, inserting it into
1189 the tree before or after C<path> (depending on the boolean
1190 flag C<before>).
1191
1192 C<path> must match exactly one existing node in the tree, and
1193 C<label> must be a label, ie. not contain C</>, C<*> or end
1194 with a bracketed index C<[N]>.");
1195
1196   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1197    [], (* XXX Augeas code needs tests. *)
1198    "remove an Augeas path",
1199    "\
1200 Remove C<path> and all of its children.
1201
1202 On success this returns the number of entries which were removed.");
1203
1204   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "move Augeas node",
1207    "\
1208 Move the node C<src> to C<dest>.  C<src> must match exactly
1209 one node.  C<dest> is overwritten if it exists.");
1210
1211   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1212    [], (* XXX Augeas code needs tests. *)
1213    "return Augeas nodes which match augpath",
1214    "\
1215 Returns a list of paths which match the path expression C<path>.
1216 The returned paths are sufficiently qualified so that they match
1217 exactly one node in the current tree.");
1218
1219   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "write all pending Augeas changes to disk",
1222    "\
1223 This writes all pending changes to disk.
1224
1225 The flags which were passed to C<guestfs_aug_init> affect exactly
1226 how files are saved.");
1227
1228   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1229    [], (* XXX Augeas code needs tests. *)
1230    "load files into the tree",
1231    "\
1232 Load files into the tree.
1233
1234 See C<aug_load> in the Augeas documentation for the full gory
1235 details.");
1236
1237   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "list Augeas nodes under augpath",
1240    "\
1241 This is just a shortcut for listing C<guestfs_aug_match>
1242 C<path/*> and sorting the resulting nodes into alphabetical order.");
1243
1244   ("rm", (RErr, [Pathname "path"]), 29, [],
1245    [InitBasicFS, Always, TestRun
1246       [["touch"; "/new"];
1247        ["rm"; "/new"]];
1248     InitBasicFS, Always, TestLastFail
1249       [["rm"; "/new"]];
1250     InitBasicFS, Always, TestLastFail
1251       [["mkdir"; "/new"];
1252        ["rm"; "/new"]]],
1253    "remove a file",
1254    "\
1255 Remove the single file C<path>.");
1256
1257   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1258    [InitBasicFS, Always, TestRun
1259       [["mkdir"; "/new"];
1260        ["rmdir"; "/new"]];
1261     InitBasicFS, Always, TestLastFail
1262       [["rmdir"; "/new"]];
1263     InitBasicFS, Always, TestLastFail
1264       [["touch"; "/new"];
1265        ["rmdir"; "/new"]]],
1266    "remove a directory",
1267    "\
1268 Remove the single directory C<path>.");
1269
1270   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1271    [InitBasicFS, Always, TestOutputFalse
1272       [["mkdir"; "/new"];
1273        ["mkdir"; "/new/foo"];
1274        ["touch"; "/new/foo/bar"];
1275        ["rm_rf"; "/new"];
1276        ["exists"; "/new"]]],
1277    "remove a file or directory recursively",
1278    "\
1279 Remove the file or directory C<path>, recursively removing the
1280 contents if its a directory.  This is like the C<rm -rf> shell
1281 command.");
1282
1283   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1284    [InitBasicFS, Always, TestOutputTrue
1285       [["mkdir"; "/new"];
1286        ["is_dir"; "/new"]];
1287     InitBasicFS, Always, TestLastFail
1288       [["mkdir"; "/new/foo/bar"]]],
1289    "create a directory",
1290    "\
1291 Create a directory named C<path>.");
1292
1293   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1294    [InitBasicFS, Always, TestOutputTrue
1295       [["mkdir_p"; "/new/foo/bar"];
1296        ["is_dir"; "/new/foo/bar"]];
1297     InitBasicFS, Always, TestOutputTrue
1298       [["mkdir_p"; "/new/foo/bar"];
1299        ["is_dir"; "/new/foo"]];
1300     InitBasicFS, Always, TestOutputTrue
1301       [["mkdir_p"; "/new/foo/bar"];
1302        ["is_dir"; "/new"]];
1303     (* Regression tests for RHBZ#503133: *)
1304     InitBasicFS, Always, TestRun
1305       [["mkdir"; "/new"];
1306        ["mkdir_p"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["touch"; "/new"];
1309        ["mkdir_p"; "/new"]]],
1310    "create a directory and parents",
1311    "\
1312 Create a directory named C<path>, creating any parent directories
1313 as necessary.  This is like the C<mkdir -p> shell command.");
1314
1315   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1316    [], (* XXX Need stat command to test *)
1317    "change file mode",
1318    "\
1319 Change the mode (permissions) of C<path> to C<mode>.  Only
1320 numeric modes are supported.");
1321
1322   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1323    [], (* XXX Need stat command to test *)
1324    "change file owner and group",
1325    "\
1326 Change the file owner to C<owner> and group to C<group>.
1327
1328 Only numeric uid and gid are supported.  If you want to use
1329 names, you will need to locate and parse the password file
1330 yourself (Augeas support makes this relatively easy).");
1331
1332   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1333    [InitISOFS, Always, TestOutputTrue (
1334       [["exists"; "/empty"]]);
1335     InitISOFS, Always, TestOutputTrue (
1336       [["exists"; "/directory"]])],
1337    "test if file or directory exists",
1338    "\
1339 This returns C<true> if and only if there is a file, directory
1340 (or anything) with the given C<path> name.
1341
1342 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1343
1344   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1345    [InitISOFS, Always, TestOutputTrue (
1346       [["is_file"; "/known-1"]]);
1347     InitISOFS, Always, TestOutputFalse (
1348       [["is_file"; "/directory"]])],
1349    "test if file exists",
1350    "\
1351 This returns C<true> if and only if there is a file
1352 with the given C<path> name.  Note that it returns false for
1353 other objects like directories.
1354
1355 See also C<guestfs_stat>.");
1356
1357   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1358    [InitISOFS, Always, TestOutputFalse (
1359       [["is_dir"; "/known-3"]]);
1360     InitISOFS, Always, TestOutputTrue (
1361       [["is_dir"; "/directory"]])],
1362    "test if file exists",
1363    "\
1364 This returns C<true> if and only if there is a directory
1365 with the given C<path> name.  Note that it returns false for
1366 other objects like files.
1367
1368 See also C<guestfs_stat>.");
1369
1370   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1371    [InitEmpty, Always, TestOutputListOfDevices (
1372       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1373        ["pvcreate"; "/dev/sda1"];
1374        ["pvcreate"; "/dev/sda2"];
1375        ["pvcreate"; "/dev/sda3"];
1376        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1377    "create an LVM physical volume",
1378    "\
1379 This creates an LVM physical volume on the named C<device>,
1380 where C<device> should usually be a partition name such
1381 as C</dev/sda1>.");
1382
1383   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1384    [InitEmpty, Always, TestOutputList (
1385       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1386        ["pvcreate"; "/dev/sda1"];
1387        ["pvcreate"; "/dev/sda2"];
1388        ["pvcreate"; "/dev/sda3"];
1389        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1390        ["vgcreate"; "VG2"; "/dev/sda3"];
1391        ["vgs"]], ["VG1"; "VG2"])],
1392    "create an LVM volume group",
1393    "\
1394 This creates an LVM volume group called C<volgroup>
1395 from the non-empty list of physical volumes C<physvols>.");
1396
1397   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1398    [InitEmpty, Always, TestOutputList (
1399       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1400        ["pvcreate"; "/dev/sda1"];
1401        ["pvcreate"; "/dev/sda2"];
1402        ["pvcreate"; "/dev/sda3"];
1403        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1404        ["vgcreate"; "VG2"; "/dev/sda3"];
1405        ["lvcreate"; "LV1"; "VG1"; "50"];
1406        ["lvcreate"; "LV2"; "VG1"; "50"];
1407        ["lvcreate"; "LV3"; "VG2"; "50"];
1408        ["lvcreate"; "LV4"; "VG2"; "50"];
1409        ["lvcreate"; "LV5"; "VG2"; "50"];
1410        ["lvs"]],
1411       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1412        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1413    "create an LVM volume group",
1414    "\
1415 This creates an LVM volume group called C<logvol>
1416 on the volume group C<volgroup>, with C<size> megabytes.");
1417
1418   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1419    [InitEmpty, Always, TestOutput (
1420       [["part_disk"; "/dev/sda"; "mbr"];
1421        ["mkfs"; "ext2"; "/dev/sda1"];
1422        ["mount"; "/dev/sda1"; "/"];
1423        ["write_file"; "/new"; "new file contents"; "0"];
1424        ["cat"; "/new"]], "new file contents")],
1425    "make a filesystem",
1426    "\
1427 This creates a filesystem on C<device> (usually a partition
1428 or LVM logical volume).  The filesystem type is C<fstype>, for
1429 example C<ext3>.");
1430
1431   ("sfdisk", (RErr, [Device "device";
1432                      Int "cyls"; Int "heads"; Int "sectors";
1433                      StringList "lines"]), 43, [DangerWillRobinson],
1434    [],
1435    "create partitions on a block device",
1436    "\
1437 This is a direct interface to the L<sfdisk(8)> program for creating
1438 partitions on block devices.
1439
1440 C<device> should be a block device, for example C</dev/sda>.
1441
1442 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1443 and sectors on the device, which are passed directly to sfdisk as
1444 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1445 of these, then the corresponding parameter is omitted.  Usually for
1446 'large' disks, you can just pass C<0> for these, but for small
1447 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1448 out the right geometry and you will need to tell it.
1449
1450 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1451 information refer to the L<sfdisk(8)> manpage.
1452
1453 To create a single partition occupying the whole disk, you would
1454 pass C<lines> as a single element list, when the single element being
1455 the string C<,> (comma).
1456
1457 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1458 C<guestfs_part_init>");
1459
1460   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1461    [InitBasicFS, Always, TestOutput (
1462       [["write_file"; "/new"; "new file contents"; "0"];
1463        ["cat"; "/new"]], "new file contents");
1464     InitBasicFS, Always, TestOutput (
1465       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1466        ["cat"; "/new"]], "\nnew file contents\n");
1467     InitBasicFS, Always, TestOutput (
1468       [["write_file"; "/new"; "\n\n"; "0"];
1469        ["cat"; "/new"]], "\n\n");
1470     InitBasicFS, Always, TestOutput (
1471       [["write_file"; "/new"; ""; "0"];
1472        ["cat"; "/new"]], "");
1473     InitBasicFS, Always, TestOutput (
1474       [["write_file"; "/new"; "\n\n\n"; "0"];
1475        ["cat"; "/new"]], "\n\n\n");
1476     InitBasicFS, Always, TestOutput (
1477       [["write_file"; "/new"; "\n"; "0"];
1478        ["cat"; "/new"]], "\n")],
1479    "create a file",
1480    "\
1481 This call creates a file called C<path>.  The contents of the
1482 file is the string C<content> (which can contain any 8 bit data),
1483 with length C<size>.
1484
1485 As a special case, if C<size> is C<0>
1486 then the length is calculated using C<strlen> (so in this case
1487 the content cannot contain embedded ASCII NULs).
1488
1489 I<NB.> Owing to a bug, writing content containing ASCII NUL
1490 characters does I<not> work, even if the length is specified.
1491 We hope to resolve this bug in a future version.  In the meantime
1492 use C<guestfs_upload>.");
1493
1494   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1495    [InitEmpty, Always, TestOutputListOfDevices (
1496       [["part_disk"; "/dev/sda"; "mbr"];
1497        ["mkfs"; "ext2"; "/dev/sda1"];
1498        ["mount"; "/dev/sda1"; "/"];
1499        ["mounts"]], ["/dev/sda1"]);
1500     InitEmpty, Always, TestOutputList (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount"; "/dev/sda1"; "/"];
1504        ["umount"; "/"];
1505        ["mounts"]], [])],
1506    "unmount a filesystem",
1507    "\
1508 This unmounts the given filesystem.  The filesystem may be
1509 specified either by its mountpoint (path) or the device which
1510 contains the filesystem.");
1511
1512   ("mounts", (RStringList "devices", []), 46, [],
1513    [InitBasicFS, Always, TestOutputListOfDevices (
1514       [["mounts"]], ["/dev/sda1"])],
1515    "show mounted filesystems",
1516    "\
1517 This returns the list of currently mounted filesystems.  It returns
1518 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1519
1520 Some internal mounts are not shown.
1521
1522 See also: C<guestfs_mountpoints>");
1523
1524   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1525    [InitBasicFS, Always, TestOutputList (
1526       [["umount_all"];
1527        ["mounts"]], []);
1528     (* check that umount_all can unmount nested mounts correctly: *)
1529     InitEmpty, Always, TestOutputList (
1530       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1531        ["mkfs"; "ext2"; "/dev/sda1"];
1532        ["mkfs"; "ext2"; "/dev/sda2"];
1533        ["mkfs"; "ext2"; "/dev/sda3"];
1534        ["mount"; "/dev/sda1"; "/"];
1535        ["mkdir"; "/mp1"];
1536        ["mount"; "/dev/sda2"; "/mp1"];
1537        ["mkdir"; "/mp1/mp2"];
1538        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1539        ["mkdir"; "/mp1/mp2/mp3"];
1540        ["umount_all"];
1541        ["mounts"]], [])],
1542    "unmount all filesystems",
1543    "\
1544 This unmounts all mounted filesystems.
1545
1546 Some internal mounts are not unmounted by this call.");
1547
1548   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1549    [],
1550    "remove all LVM LVs, VGs and PVs",
1551    "\
1552 This command removes all LVM logical volumes, volume groups
1553 and physical volumes.");
1554
1555   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1556    [InitISOFS, Always, TestOutput (
1557       [["file"; "/empty"]], "empty");
1558     InitISOFS, Always, TestOutput (
1559       [["file"; "/known-1"]], "ASCII text");
1560     InitISOFS, Always, TestLastFail (
1561       [["file"; "/notexists"]])],
1562    "determine file type",
1563    "\
1564 This call uses the standard L<file(1)> command to determine
1565 the type or contents of the file.  This also works on devices,
1566 for example to find out whether a partition contains a filesystem.
1567
1568 This call will also transparently look inside various types
1569 of compressed file.
1570
1571 The exact command which runs is C<file -zbsL path>.  Note in
1572 particular that the filename is not prepended to the output
1573 (the C<-b> option).");
1574
1575   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1576    [InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 1"]], "Result1");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 2"]], "Result2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 3"]], "\nResult3");
1588     InitBasicFS, Always, TestOutput (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command 4"]], "\nResult4\n");
1592     InitBasicFS, Always, TestOutput (
1593       [["upload"; "test-command"; "/test-command"];
1594        ["chmod"; "0o755"; "/test-command"];
1595        ["command"; "/test-command 5"]], "\nResult5\n\n");
1596     InitBasicFS, Always, TestOutput (
1597       [["upload"; "test-command"; "/test-command"];
1598        ["chmod"; "0o755"; "/test-command"];
1599        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1600     InitBasicFS, Always, TestOutput (
1601       [["upload"; "test-command"; "/test-command"];
1602        ["chmod"; "0o755"; "/test-command"];
1603        ["command"; "/test-command 7"]], "");
1604     InitBasicFS, Always, TestOutput (
1605       [["upload"; "test-command"; "/test-command"];
1606        ["chmod"; "0o755"; "/test-command"];
1607        ["command"; "/test-command 8"]], "\n");
1608     InitBasicFS, Always, TestOutput (
1609       [["upload"; "test-command"; "/test-command"];
1610        ["chmod"; "0o755"; "/test-command"];
1611        ["command"; "/test-command 9"]], "\n\n");
1612     InitBasicFS, Always, TestOutput (
1613       [["upload"; "test-command"; "/test-command"];
1614        ["chmod"; "0o755"; "/test-command"];
1615        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1616     InitBasicFS, Always, TestOutput (
1617       [["upload"; "test-command"; "/test-command"];
1618        ["chmod"; "0o755"; "/test-command"];
1619        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1620     InitBasicFS, Always, TestLastFail (
1621       [["upload"; "test-command"; "/test-command"];
1622        ["chmod"; "0o755"; "/test-command"];
1623        ["command"; "/test-command"]])],
1624    "run a command from the guest filesystem",
1625    "\
1626 This call runs a command from the guest filesystem.  The
1627 filesystem must be mounted, and must contain a compatible
1628 operating system (ie. something Linux, with the same
1629 or compatible processor architecture).
1630
1631 The single parameter is an argv-style list of arguments.
1632 The first element is the name of the program to run.
1633 Subsequent elements are parameters.  The list must be
1634 non-empty (ie. must contain a program name).  Note that
1635 the command runs directly, and is I<not> invoked via
1636 the shell (see C<guestfs_sh>).
1637
1638 The return value is anything printed to I<stdout> by
1639 the command.
1640
1641 If the command returns a non-zero exit status, then
1642 this function returns an error message.  The error message
1643 string is the content of I<stderr> from the command.
1644
1645 The C<$PATH> environment variable will contain at least
1646 C</usr/bin> and C</bin>.  If you require a program from
1647 another location, you should provide the full path in the
1648 first parameter.
1649
1650 Shared libraries and data files required by the program
1651 must be available on filesystems which are mounted in the
1652 correct places.  It is the caller's responsibility to ensure
1653 all filesystems that are needed are mounted at the right
1654 locations.");
1655
1656   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1657    [InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 1"]], ["Result1"]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 2"]], ["Result2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1669     InitBasicFS, Always, TestOutputList (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1673     InitBasicFS, Always, TestOutputList (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1677     InitBasicFS, Always, TestOutputList (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1681     InitBasicFS, Always, TestOutputList (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command_lines"; "/test-command 7"]], []);
1685     InitBasicFS, Always, TestOutputList (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command_lines"; "/test-command 8"]], [""]);
1689     InitBasicFS, Always, TestOutputList (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command_lines"; "/test-command 9"]], ["";""]);
1693     InitBasicFS, Always, TestOutputList (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1697     InitBasicFS, Always, TestOutputList (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1701    "run a command, returning lines",
1702    "\
1703 This is the same as C<guestfs_command>, but splits the
1704 result into a list of lines.
1705
1706 See also: C<guestfs_sh_lines>");
1707
1708   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1709    [InitISOFS, Always, TestOutputStruct (
1710       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1711    "get file information",
1712    "\
1713 Returns file information for the given C<path>.
1714
1715 This is the same as the C<stat(2)> system call.");
1716
1717   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1718    [InitISOFS, Always, TestOutputStruct (
1719       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1720    "get file information for a symbolic link",
1721    "\
1722 Returns file information for the given C<path>.
1723
1724 This is the same as C<guestfs_stat> except that if C<path>
1725 is a symbolic link, then the link is stat-ed, not the file it
1726 refers to.
1727
1728 This is the same as the C<lstat(2)> system call.");
1729
1730   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1731    [InitISOFS, Always, TestOutputStruct (
1732       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1733    "get file system statistics",
1734    "\
1735 Returns file system statistics for any mounted file system.
1736 C<path> should be a file or directory in the mounted file system
1737 (typically it is the mount point itself, but it doesn't need to be).
1738
1739 This is the same as the C<statvfs(2)> system call.");
1740
1741   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1742    [], (* XXX test *)
1743    "get ext2/ext3/ext4 superblock details",
1744    "\
1745 This returns the contents of the ext2, ext3 or ext4 filesystem
1746 superblock on C<device>.
1747
1748 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1749 manpage for more details.  The list of fields returned isn't
1750 clearly defined, and depends on both the version of C<tune2fs>
1751 that libguestfs was built against, and the filesystem itself.");
1752
1753   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1754    [InitEmpty, Always, TestOutputTrue (
1755       [["blockdev_setro"; "/dev/sda"];
1756        ["blockdev_getro"; "/dev/sda"]])],
1757    "set block device to read-only",
1758    "\
1759 Sets the block device named C<device> to read-only.
1760
1761 This uses the L<blockdev(8)> command.");
1762
1763   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1764    [InitEmpty, Always, TestOutputFalse (
1765       [["blockdev_setrw"; "/dev/sda"];
1766        ["blockdev_getro"; "/dev/sda"]])],
1767    "set block device to read-write",
1768    "\
1769 Sets the block device named C<device> to read-write.
1770
1771 This uses the L<blockdev(8)> command.");
1772
1773   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1774    [InitEmpty, Always, TestOutputTrue (
1775       [["blockdev_setro"; "/dev/sda"];
1776        ["blockdev_getro"; "/dev/sda"]])],
1777    "is block device set to read-only",
1778    "\
1779 Returns a boolean indicating if the block device is read-only
1780 (true if read-only, false if not).
1781
1782 This uses the L<blockdev(8)> command.");
1783
1784   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1785    [InitEmpty, Always, TestOutputInt (
1786       [["blockdev_getss"; "/dev/sda"]], 512)],
1787    "get sectorsize of block device",
1788    "\
1789 This returns the size of sectors on a block device.
1790 Usually 512, but can be larger for modern devices.
1791
1792 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1793 for that).
1794
1795 This uses the L<blockdev(8)> command.");
1796
1797   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1798    [InitEmpty, Always, TestOutputInt (
1799       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1800    "get blocksize of block device",
1801    "\
1802 This returns the block size of a device.
1803
1804 (Note this is different from both I<size in blocks> and
1805 I<filesystem block size>).
1806
1807 This uses the L<blockdev(8)> command.");
1808
1809   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1810    [], (* XXX test *)
1811    "set blocksize of block device",
1812    "\
1813 This sets the block size of a device.
1814
1815 (Note this is different from both I<size in blocks> and
1816 I<filesystem block size>).
1817
1818 This uses the L<blockdev(8)> command.");
1819
1820   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1821    [InitEmpty, Always, TestOutputInt (
1822       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1823    "get total size of device in 512-byte sectors",
1824    "\
1825 This returns the size of the device in units of 512-byte sectors
1826 (even if the sectorsize isn't 512 bytes ... weird).
1827
1828 See also C<guestfs_blockdev_getss> for the real sector size of
1829 the device, and C<guestfs_blockdev_getsize64> for the more
1830 useful I<size in bytes>.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1835    [InitEmpty, Always, TestOutputInt (
1836       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1837    "get total size of device in bytes",
1838    "\
1839 This returns the size of the device in bytes.
1840
1841 See also C<guestfs_blockdev_getsz>.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1846    [InitEmpty, Always, TestRun
1847       [["blockdev_flushbufs"; "/dev/sda"]]],
1848    "flush device buffers",
1849    "\
1850 This tells the kernel to flush internal buffers associated
1851 with C<device>.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1856    [InitEmpty, Always, TestRun
1857       [["blockdev_rereadpt"; "/dev/sda"]]],
1858    "reread partition table",
1859    "\
1860 Reread the partition table on C<device>.
1861
1862 This uses the L<blockdev(8)> command.");
1863
1864   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1865    [InitBasicFS, Always, TestOutput (
1866       (* Pick a file from cwd which isn't likely to change. *)
1867       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1868        ["checksum"; "md5"; "/COPYING.LIB"]],
1869         Digest.to_hex (Digest.file "COPYING.LIB"))],
1870    "upload a file from the local machine",
1871    "\
1872 Upload local file C<filename> to C<remotefilename> on the
1873 filesystem.
1874
1875 C<filename> can also be a named pipe.
1876
1877 See also C<guestfs_download>.");
1878
1879   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1880    [InitBasicFS, Always, TestOutput (
1881       (* Pick a file from cwd which isn't likely to change. *)
1882       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1883        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1884        ["upload"; "testdownload.tmp"; "/upload"];
1885        ["checksum"; "md5"; "/upload"]],
1886         Digest.to_hex (Digest.file "COPYING.LIB"))],
1887    "download a file to the local machine",
1888    "\
1889 Download file C<remotefilename> and save it as C<filename>
1890 on the local machine.
1891
1892 C<filename> can also be a named pipe.
1893
1894 See also C<guestfs_upload>, C<guestfs_cat>.");
1895
1896   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1897    [InitISOFS, Always, TestOutput (
1898       [["checksum"; "crc"; "/known-3"]], "2891671662");
1899     InitISOFS, Always, TestLastFail (
1900       [["checksum"; "crc"; "/notexists"]]);
1901     InitISOFS, Always, TestOutput (
1902       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1903     InitISOFS, Always, TestOutput (
1904       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1905     InitISOFS, Always, TestOutput (
1906       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1907     InitISOFS, Always, TestOutput (
1908       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1909     InitISOFS, Always, TestOutput (
1910       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1911     InitISOFS, Always, TestOutput (
1912       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1913    "compute MD5, SHAx or CRC checksum of file",
1914    "\
1915 This call computes the MD5, SHAx or CRC checksum of the
1916 file named C<path>.
1917
1918 The type of checksum to compute is given by the C<csumtype>
1919 parameter which must have one of the following values:
1920
1921 =over 4
1922
1923 =item C<crc>
1924
1925 Compute the cyclic redundancy check (CRC) specified by POSIX
1926 for the C<cksum> command.
1927
1928 =item C<md5>
1929
1930 Compute the MD5 hash (using the C<md5sum> program).
1931
1932 =item C<sha1>
1933
1934 Compute the SHA1 hash (using the C<sha1sum> program).
1935
1936 =item C<sha224>
1937
1938 Compute the SHA224 hash (using the C<sha224sum> program).
1939
1940 =item C<sha256>
1941
1942 Compute the SHA256 hash (using the C<sha256sum> program).
1943
1944 =item C<sha384>
1945
1946 Compute the SHA384 hash (using the C<sha384sum> program).
1947
1948 =item C<sha512>
1949
1950 Compute the SHA512 hash (using the C<sha512sum> program).
1951
1952 =back
1953
1954 The checksum is returned as a printable string.");
1955
1956   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1957    [InitBasicFS, Always, TestOutput (
1958       [["tar_in"; "../images/helloworld.tar"; "/"];
1959        ["cat"; "/hello"]], "hello\n")],
1960    "unpack tarfile to directory",
1961    "\
1962 This command uploads and unpacks local file C<tarfile> (an
1963 I<uncompressed> tar file) into C<directory>.
1964
1965 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1966
1967   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1968    [],
1969    "pack directory into tarfile",
1970    "\
1971 This command packs the contents of C<directory> and downloads
1972 it to local file C<tarfile>.
1973
1974 To download a compressed tarball, use C<guestfs_tgz_out>.");
1975
1976   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1977    [InitBasicFS, Always, TestOutput (
1978       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1979        ["cat"; "/hello"]], "hello\n")],
1980    "unpack compressed tarball to directory",
1981    "\
1982 This command uploads and unpacks local file C<tarball> (a
1983 I<gzip compressed> tar file) into C<directory>.
1984
1985 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1986
1987   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1988    [],
1989    "pack directory into compressed tarball",
1990    "\
1991 This command packs the contents of C<directory> and downloads
1992 it to local file C<tarball>.
1993
1994 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1995
1996   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1997    [InitBasicFS, Always, TestLastFail (
1998       [["umount"; "/"];
1999        ["mount_ro"; "/dev/sda1"; "/"];
2000        ["touch"; "/new"]]);
2001     InitBasicFS, Always, TestOutput (
2002       [["write_file"; "/new"; "data"; "0"];
2003        ["umount"; "/"];
2004        ["mount_ro"; "/dev/sda1"; "/"];
2005        ["cat"; "/new"]], "data")],
2006    "mount a guest disk, read-only",
2007    "\
2008 This is the same as the C<guestfs_mount> command, but it
2009 mounts the filesystem with the read-only (I<-o ro>) flag.");
2010
2011   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2012    [],
2013    "mount a guest disk with mount options",
2014    "\
2015 This is the same as the C<guestfs_mount> command, but it
2016 allows you to set the mount options as for the
2017 L<mount(8)> I<-o> flag.");
2018
2019   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2020    [],
2021    "mount a guest disk with mount options and vfstype",
2022    "\
2023 This is the same as the C<guestfs_mount> command, but it
2024 allows you to set both the mount options and the vfstype
2025 as for the L<mount(8)> I<-o> and I<-t> flags.");
2026
2027   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2028    [],
2029    "debugging and internals",
2030    "\
2031 The C<guestfs_debug> command exposes some internals of
2032 C<guestfsd> (the guestfs daemon) that runs inside the
2033 qemu subprocess.
2034
2035 There is no comprehensive help for this command.  You have
2036 to look at the file C<daemon/debug.c> in the libguestfs source
2037 to find out what you can do.");
2038
2039   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2040    [InitEmpty, Always, TestOutputList (
2041       [["part_disk"; "/dev/sda"; "mbr"];
2042        ["pvcreate"; "/dev/sda1"];
2043        ["vgcreate"; "VG"; "/dev/sda1"];
2044        ["lvcreate"; "LV1"; "VG"; "50"];
2045        ["lvcreate"; "LV2"; "VG"; "50"];
2046        ["lvremove"; "/dev/VG/LV1"];
2047        ["lvs"]], ["/dev/VG/LV2"]);
2048     InitEmpty, Always, TestOutputList (
2049       [["part_disk"; "/dev/sda"; "mbr"];
2050        ["pvcreate"; "/dev/sda1"];
2051        ["vgcreate"; "VG"; "/dev/sda1"];
2052        ["lvcreate"; "LV1"; "VG"; "50"];
2053        ["lvcreate"; "LV2"; "VG"; "50"];
2054        ["lvremove"; "/dev/VG"];
2055        ["lvs"]], []);
2056     InitEmpty, Always, TestOutputList (
2057       [["part_disk"; "/dev/sda"; "mbr"];
2058        ["pvcreate"; "/dev/sda1"];
2059        ["vgcreate"; "VG"; "/dev/sda1"];
2060        ["lvcreate"; "LV1"; "VG"; "50"];
2061        ["lvcreate"; "LV2"; "VG"; "50"];
2062        ["lvremove"; "/dev/VG"];
2063        ["vgs"]], ["VG"])],
2064    "remove an LVM logical volume",
2065    "\
2066 Remove an LVM logical volume C<device>, where C<device> is
2067 the path to the LV, such as C</dev/VG/LV>.
2068
2069 You can also remove all LVs in a volume group by specifying
2070 the VG name, C</dev/VG>.");
2071
2072   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2073    [InitEmpty, Always, TestOutputList (
2074       [["part_disk"; "/dev/sda"; "mbr"];
2075        ["pvcreate"; "/dev/sda1"];
2076        ["vgcreate"; "VG"; "/dev/sda1"];
2077        ["lvcreate"; "LV1"; "VG"; "50"];
2078        ["lvcreate"; "LV2"; "VG"; "50"];
2079        ["vgremove"; "VG"];
2080        ["lvs"]], []);
2081     InitEmpty, Always, TestOutputList (
2082       [["part_disk"; "/dev/sda"; "mbr"];
2083        ["pvcreate"; "/dev/sda1"];
2084        ["vgcreate"; "VG"; "/dev/sda1"];
2085        ["lvcreate"; "LV1"; "VG"; "50"];
2086        ["lvcreate"; "LV2"; "VG"; "50"];
2087        ["vgremove"; "VG"];
2088        ["vgs"]], [])],
2089    "remove an LVM volume group",
2090    "\
2091 Remove an LVM volume group C<vgname>, (for example C<VG>).
2092
2093 This also forcibly removes all logical volumes in the volume
2094 group (if any).");
2095
2096   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2097    [InitEmpty, Always, TestOutputListOfDevices (
2098       [["part_disk"; "/dev/sda"; "mbr"];
2099        ["pvcreate"; "/dev/sda1"];
2100        ["vgcreate"; "VG"; "/dev/sda1"];
2101        ["lvcreate"; "LV1"; "VG"; "50"];
2102        ["lvcreate"; "LV2"; "VG"; "50"];
2103        ["vgremove"; "VG"];
2104        ["pvremove"; "/dev/sda1"];
2105        ["lvs"]], []);
2106     InitEmpty, Always, TestOutputListOfDevices (
2107       [["part_disk"; "/dev/sda"; "mbr"];
2108        ["pvcreate"; "/dev/sda1"];
2109        ["vgcreate"; "VG"; "/dev/sda1"];
2110        ["lvcreate"; "LV1"; "VG"; "50"];
2111        ["lvcreate"; "LV2"; "VG"; "50"];
2112        ["vgremove"; "VG"];
2113        ["pvremove"; "/dev/sda1"];
2114        ["vgs"]], []);
2115     InitEmpty, Always, TestOutputListOfDevices (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["vgremove"; "VG"];
2122        ["pvremove"; "/dev/sda1"];
2123        ["pvs"]], [])],
2124    "remove an LVM physical volume",
2125    "\
2126 This wipes a physical volume C<device> so that LVM will no longer
2127 recognise it.
2128
2129 The implementation uses the C<pvremove> command which refuses to
2130 wipe physical volumes that contain any volume groups, so you have
2131 to remove those first.");
2132
2133   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2134    [InitBasicFS, Always, TestOutput (
2135       [["set_e2label"; "/dev/sda1"; "testlabel"];
2136        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2137    "set the ext2/3/4 filesystem label",
2138    "\
2139 This sets the ext2/3/4 filesystem label of the filesystem on
2140 C<device> to C<label>.  Filesystem labels are limited to
2141 16 characters.
2142
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2144 to return the existing label on a filesystem.");
2145
2146   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2147    [],
2148    "get the ext2/3/4 filesystem label",
2149    "\
2150 This returns the ext2/3/4 filesystem label of the filesystem on
2151 C<device>.");
2152
2153   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2154    (let uuid = uuidgen () in
2155     [InitBasicFS, Always, TestOutput (
2156        [["set_e2uuid"; "/dev/sda1"; uuid];
2157         ["get_e2uuid"; "/dev/sda1"]], uuid);
2158      InitBasicFS, Always, TestOutput (
2159        [["set_e2uuid"; "/dev/sda1"; "clear"];
2160         ["get_e2uuid"; "/dev/sda1"]], "");
2161      (* We can't predict what UUIDs will be, so just check the commands run. *)
2162      InitBasicFS, Always, TestRun (
2163        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2164      InitBasicFS, Always, TestRun (
2165        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2166    "set the ext2/3/4 filesystem UUID",
2167    "\
2168 This sets the ext2/3/4 filesystem UUID of the filesystem on
2169 C<device> to C<uuid>.  The format of the UUID and alternatives
2170 such as C<clear>, C<random> and C<time> are described in the
2171 L<tune2fs(8)> manpage.
2172
2173 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2174 to return the existing UUID of a filesystem.");
2175
2176   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2177    [],
2178    "get the ext2/3/4 filesystem UUID",
2179    "\
2180 This returns the ext2/3/4 filesystem UUID of the filesystem on
2181 C<device>.");
2182
2183   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2184    [InitBasicFS, Always, TestOutputInt (
2185       [["umount"; "/dev/sda1"];
2186        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2187     InitBasicFS, Always, TestOutputInt (
2188       [["umount"; "/dev/sda1"];
2189        ["zero"; "/dev/sda1"];
2190        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2191    "run the filesystem checker",
2192    "\
2193 This runs the filesystem checker (fsck) on C<device> which
2194 should have filesystem type C<fstype>.
2195
2196 The returned integer is the status.  See L<fsck(8)> for the
2197 list of status codes from C<fsck>.
2198
2199 Notes:
2200
2201 =over 4
2202
2203 =item *
2204
2205 Multiple status codes can be summed together.
2206
2207 =item *
2208
2209 A non-zero return code can mean \"success\", for example if
2210 errors have been corrected on the filesystem.
2211
2212 =item *
2213
2214 Checking or repairing NTFS volumes is not supported
2215 (by linux-ntfs).
2216
2217 =back
2218
2219 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2220
2221   ("zero", (RErr, [Device "device"]), 85, [],
2222    [InitBasicFS, Always, TestOutput (
2223       [["umount"; "/dev/sda1"];
2224        ["zero"; "/dev/sda1"];
2225        ["file"; "/dev/sda1"]], "data")],
2226    "write zeroes to the device",
2227    "\
2228 This command writes zeroes over the first few blocks of C<device>.
2229
2230 How many blocks are zeroed isn't specified (but it's I<not> enough
2231 to securely wipe the device).  It should be sufficient to remove
2232 any partition tables, filesystem superblocks and so on.
2233
2234 See also: C<guestfs_scrub_device>.");
2235
2236   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2237    (* Test disabled because grub-install incompatible with virtio-blk driver.
2238     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2239     *)
2240    [InitBasicFS, Disabled, TestOutputTrue (
2241       [["grub_install"; "/"; "/dev/sda1"];
2242        ["is_dir"; "/boot"]])],
2243    "install GRUB",
2244    "\
2245 This command installs GRUB (the Grand Unified Bootloader) on
2246 C<device>, with the root directory being C<root>.");
2247
2248   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2249    [InitBasicFS, Always, TestOutput (
2250       [["write_file"; "/old"; "file content"; "0"];
2251        ["cp"; "/old"; "/new"];
2252        ["cat"; "/new"]], "file content");
2253     InitBasicFS, Always, TestOutputTrue (
2254       [["write_file"; "/old"; "file content"; "0"];
2255        ["cp"; "/old"; "/new"];
2256        ["is_file"; "/old"]]);
2257     InitBasicFS, Always, TestOutput (
2258       [["write_file"; "/old"; "file content"; "0"];
2259        ["mkdir"; "/dir"];
2260        ["cp"; "/old"; "/dir/new"];
2261        ["cat"; "/dir/new"]], "file content")],
2262    "copy a file",
2263    "\
2264 This copies a file from C<src> to C<dest> where C<dest> is
2265 either a destination filename or destination directory.");
2266
2267   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2268    [InitBasicFS, Always, TestOutput (
2269       [["mkdir"; "/olddir"];
2270        ["mkdir"; "/newdir"];
2271        ["write_file"; "/olddir/file"; "file content"; "0"];
2272        ["cp_a"; "/olddir"; "/newdir"];
2273        ["cat"; "/newdir/olddir/file"]], "file content")],
2274    "copy a file or directory recursively",
2275    "\
2276 This copies a file or directory from C<src> to C<dest>
2277 recursively using the C<cp -a> command.");
2278
2279   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2280    [InitBasicFS, Always, TestOutput (
2281       [["write_file"; "/old"; "file content"; "0"];
2282        ["mv"; "/old"; "/new"];
2283        ["cat"; "/new"]], "file content");
2284     InitBasicFS, Always, TestOutputFalse (
2285       [["write_file"; "/old"; "file content"; "0"];
2286        ["mv"; "/old"; "/new"];
2287        ["is_file"; "/old"]])],
2288    "move a file",
2289    "\
2290 This moves a file from C<src> to C<dest> where C<dest> is
2291 either a destination filename or destination directory.");
2292
2293   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2294    [InitEmpty, Always, TestRun (
2295       [["drop_caches"; "3"]])],
2296    "drop kernel page cache, dentries and inodes",
2297    "\
2298 This instructs the guest kernel to drop its page cache,
2299 and/or dentries and inode caches.  The parameter C<whattodrop>
2300 tells the kernel what precisely to drop, see
2301 L<http://linux-mm.org/Drop_Caches>
2302
2303 Setting C<whattodrop> to 3 should drop everything.
2304
2305 This automatically calls L<sync(2)> before the operation,
2306 so that the maximum guest memory is freed.");
2307
2308   ("dmesg", (RString "kmsgs", []), 91, [],
2309    [InitEmpty, Always, TestRun (
2310       [["dmesg"]])],
2311    "return kernel messages",
2312    "\
2313 This returns the kernel messages (C<dmesg> output) from
2314 the guest kernel.  This is sometimes useful for extended
2315 debugging of problems.
2316
2317 Another way to get the same information is to enable
2318 verbose messages with C<guestfs_set_verbose> or by setting
2319 the environment variable C<LIBGUESTFS_DEBUG=1> before
2320 running the program.");
2321
2322   ("ping_daemon", (RErr, []), 92, [],
2323    [InitEmpty, Always, TestRun (
2324       [["ping_daemon"]])],
2325    "ping the guest daemon",
2326    "\
2327 This is a test probe into the guestfs daemon running inside
2328 the qemu subprocess.  Calling this function checks that the
2329 daemon responds to the ping message, without affecting the daemon
2330 or attached block device(s) in any other way.");
2331
2332   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2333    [InitBasicFS, Always, TestOutputTrue (
2334       [["write_file"; "/file1"; "contents of a file"; "0"];
2335        ["cp"; "/file1"; "/file2"];
2336        ["equal"; "/file1"; "/file2"]]);
2337     InitBasicFS, Always, TestOutputFalse (
2338       [["write_file"; "/file1"; "contents of a file"; "0"];
2339        ["write_file"; "/file2"; "contents of another file"; "0"];
2340        ["equal"; "/file1"; "/file2"]]);
2341     InitBasicFS, Always, TestLastFail (
2342       [["equal"; "/file1"; "/file2"]])],
2343    "test if two files have equal contents",
2344    "\
2345 This compares the two files C<file1> and C<file2> and returns
2346 true if their content is exactly equal, or false otherwise.
2347
2348 The external L<cmp(1)> program is used for the comparison.");
2349
2350   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2351    [InitISOFS, Always, TestOutputList (
2352       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2353     InitISOFS, Always, TestOutputList (
2354       [["strings"; "/empty"]], [])],
2355    "print the printable strings in a file",
2356    "\
2357 This runs the L<strings(1)> command on a file and returns
2358 the list of printable strings found.");
2359
2360   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2361    [InitISOFS, Always, TestOutputList (
2362       [["strings_e"; "b"; "/known-5"]], []);
2363     InitBasicFS, Disabled, TestOutputList (
2364       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2365        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2366    "print the printable strings in a file",
2367    "\
2368 This is like the C<guestfs_strings> command, but allows you to
2369 specify the encoding.
2370
2371 See the L<strings(1)> manpage for the full list of encodings.
2372
2373 Commonly useful encodings are C<l> (lower case L) which will
2374 show strings inside Windows/x86 files.
2375
2376 The returned strings are transcoded to UTF-8.");
2377
2378   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2379    [InitISOFS, Always, TestOutput (
2380       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2381     (* Test for RHBZ#501888c2 regression which caused large hexdump
2382      * commands to segfault.
2383      *)
2384     InitISOFS, Always, TestRun (
2385       [["hexdump"; "/100krandom"]])],
2386    "dump a file in hexadecimal",
2387    "\
2388 This runs C<hexdump -C> on the given C<path>.  The result is
2389 the human-readable, canonical hex dump of the file.");
2390
2391   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2392    [InitNone, Always, TestOutput (
2393       [["part_disk"; "/dev/sda"; "mbr"];
2394        ["mkfs"; "ext3"; "/dev/sda1"];
2395        ["mount"; "/dev/sda1"; "/"];
2396        ["write_file"; "/new"; "test file"; "0"];
2397        ["umount"; "/dev/sda1"];
2398        ["zerofree"; "/dev/sda1"];
2399        ["mount"; "/dev/sda1"; "/"];
2400        ["cat"; "/new"]], "test file")],
2401    "zero unused inodes and disk blocks on ext2/3 filesystem",
2402    "\
2403 This runs the I<zerofree> program on C<device>.  This program
2404 claims to zero unused inodes and disk blocks on an ext2/3
2405 filesystem, thus making it possible to compress the filesystem
2406 more effectively.
2407
2408 You should B<not> run this program if the filesystem is
2409 mounted.
2410
2411 It is possible that using this program can damage the filesystem
2412 or data on the filesystem.");
2413
2414   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2415    [],
2416    "resize an LVM physical volume",
2417    "\
2418 This resizes (expands or shrinks) an existing LVM physical
2419 volume to match the new size of the underlying device.");
2420
2421   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2422                        Int "cyls"; Int "heads"; Int "sectors";
2423                        String "line"]), 99, [DangerWillRobinson],
2424    [],
2425    "modify a single partition on a block device",
2426    "\
2427 This runs L<sfdisk(8)> option to modify just the single
2428 partition C<n> (note: C<n> counts from 1).
2429
2430 For other parameters, see C<guestfs_sfdisk>.  You should usually
2431 pass C<0> for the cyls/heads/sectors parameters.
2432
2433 See also: C<guestfs_part_add>");
2434
2435   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2436    [],
2437    "display the partition table",
2438    "\
2439 This displays the partition table on C<device>, in the
2440 human-readable output of the L<sfdisk(8)> command.  It is
2441 not intended to be parsed.
2442
2443 See also: C<guestfs_part_list>");
2444
2445   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2446    [],
2447    "display the kernel geometry",
2448    "\
2449 This displays the kernel's idea of the geometry of C<device>.
2450
2451 The result is in human-readable format, and not designed to
2452 be parsed.");
2453
2454   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2455    [],
2456    "display the disk geometry from the partition table",
2457    "\
2458 This displays the disk geometry of C<device> read from the
2459 partition table.  Especially in the case where the underlying
2460 block device has been resized, this can be different from the
2461 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2462
2463 The result is in human-readable format, and not designed to
2464 be parsed.");
2465
2466   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2467    [],
2468    "activate or deactivate all volume groups",
2469    "\
2470 This command activates or (if C<activate> is false) deactivates
2471 all logical volumes in all volume groups.
2472 If activated, then they are made known to the
2473 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2474 then those devices disappear.
2475
2476 This command is the same as running C<vgchange -a y|n>");
2477
2478   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2479    [],
2480    "activate or deactivate some volume groups",
2481    "\
2482 This command activates or (if C<activate> is false) deactivates
2483 all logical volumes in the listed volume groups C<volgroups>.
2484 If activated, then they are made known to the
2485 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2486 then those devices disappear.
2487
2488 This command is the same as running C<vgchange -a y|n volgroups...>
2489
2490 Note that if C<volgroups> is an empty list then B<all> volume groups
2491 are activated or deactivated.");
2492
2493   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2494    [InitNone, Always, TestOutput (
2495       [["part_disk"; "/dev/sda"; "mbr"];
2496        ["pvcreate"; "/dev/sda1"];
2497        ["vgcreate"; "VG"; "/dev/sda1"];
2498        ["lvcreate"; "LV"; "VG"; "10"];
2499        ["mkfs"; "ext2"; "/dev/VG/LV"];
2500        ["mount"; "/dev/VG/LV"; "/"];
2501        ["write_file"; "/new"; "test content"; "0"];
2502        ["umount"; "/"];
2503        ["lvresize"; "/dev/VG/LV"; "20"];
2504        ["e2fsck_f"; "/dev/VG/LV"];
2505        ["resize2fs"; "/dev/VG/LV"];
2506        ["mount"; "/dev/VG/LV"; "/"];
2507        ["cat"; "/new"]], "test content")],
2508    "resize an LVM logical volume",
2509    "\
2510 This resizes (expands or shrinks) an existing LVM logical
2511 volume to C<mbytes>.  When reducing, data in the reduced part
2512 is lost.");
2513
2514   ("resize2fs", (RErr, [Device "device"]), 106, [],
2515    [], (* lvresize tests this *)
2516    "resize an ext2/ext3 filesystem",
2517    "\
2518 This resizes an ext2 or ext3 filesystem to match the size of
2519 the underlying device.
2520
2521 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2522 on the C<device> before calling this command.  For unknown reasons
2523 C<resize2fs> sometimes gives an error about this and sometimes not.
2524 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2525 calling this function.");
2526
2527   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2528    [InitBasicFS, Always, TestOutputList (
2529       [["find"; "/"]], ["lost+found"]);
2530     InitBasicFS, Always, TestOutputList (
2531       [["touch"; "/a"];
2532        ["mkdir"; "/b"];
2533        ["touch"; "/b/c"];
2534        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2535     InitBasicFS, Always, TestOutputList (
2536       [["mkdir_p"; "/a/b/c"];
2537        ["touch"; "/a/b/c/d"];
2538        ["find"; "/a/b/"]], ["c"; "c/d"])],
2539    "find all files and directories",
2540    "\
2541 This command lists out all files and directories, recursively,
2542 starting at C<directory>.  It is essentially equivalent to
2543 running the shell command C<find directory -print> but some
2544 post-processing happens on the output, described below.
2545
2546 This returns a list of strings I<without any prefix>.  Thus
2547 if the directory structure was:
2548
2549  /tmp/a
2550  /tmp/b
2551  /tmp/c/d
2552
2553 then the returned list from C<guestfs_find> C</tmp> would be
2554 4 elements:
2555
2556  a
2557  b
2558  c
2559  c/d
2560
2561 If C<directory> is not a directory, then this command returns
2562 an error.
2563
2564 The returned list is sorted.
2565
2566 See also C<guestfs_find0>.");
2567
2568   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2569    [], (* lvresize tests this *)
2570    "check an ext2/ext3 filesystem",
2571    "\
2572 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2573 filesystem checker on C<device>, noninteractively (C<-p>),
2574 even if the filesystem appears to be clean (C<-f>).
2575
2576 This command is only needed because of C<guestfs_resize2fs>
2577 (q.v.).  Normally you should use C<guestfs_fsck>.");
2578
2579   ("sleep", (RErr, [Int "secs"]), 109, [],
2580    [InitNone, Always, TestRun (
2581       [["sleep"; "1"]])],
2582    "sleep for some seconds",
2583    "\
2584 Sleep for C<secs> seconds.");
2585
2586   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2587    [InitNone, Always, TestOutputInt (
2588       [["part_disk"; "/dev/sda"; "mbr"];
2589        ["mkfs"; "ntfs"; "/dev/sda1"];
2590        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2591     InitNone, Always, TestOutputInt (
2592       [["part_disk"; "/dev/sda"; "mbr"];
2593        ["mkfs"; "ext2"; "/dev/sda1"];
2594        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2595    "probe NTFS volume",
2596    "\
2597 This command runs the L<ntfs-3g.probe(8)> command which probes
2598 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2599 be mounted read-write, and some cannot be mounted at all).
2600
2601 C<rw> is a boolean flag.  Set it to true if you want to test
2602 if the volume can be mounted read-write.  Set it to false if
2603 you want to test if the volume can be mounted read-only.
2604
2605 The return value is an integer which C<0> if the operation
2606 would succeed, or some non-zero value documented in the
2607 L<ntfs-3g.probe(8)> manual page.");
2608
2609   ("sh", (RString "output", [String "command"]), 111, [],
2610    [], (* XXX needs tests *)
2611    "run a command via the shell",
2612    "\
2613 This call runs a command from the guest filesystem via the
2614 guest's C</bin/sh>.
2615
2616 This is like C<guestfs_command>, but passes the command to:
2617
2618  /bin/sh -c \"command\"
2619
2620 Depending on the guest's shell, this usually results in
2621 wildcards being expanded, shell expressions being interpolated
2622 and so on.
2623
2624 All the provisos about C<guestfs_command> apply to this call.");
2625
2626   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2627    [], (* XXX needs tests *)
2628    "run a command via the shell returning lines",
2629    "\
2630 This is the same as C<guestfs_sh>, but splits the result
2631 into a list of lines.
2632
2633 See also: C<guestfs_command_lines>");
2634
2635   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2636    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2637     * code in stubs.c, since all valid glob patterns must start with "/".
2638     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2639     *)
2640    [InitBasicFS, Always, TestOutputList (
2641       [["mkdir_p"; "/a/b/c"];
2642        ["touch"; "/a/b/c/d"];
2643        ["touch"; "/a/b/c/e"];
2644        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2645     InitBasicFS, Always, TestOutputList (
2646       [["mkdir_p"; "/a/b/c"];
2647        ["touch"; "/a/b/c/d"];
2648        ["touch"; "/a/b/c/e"];
2649        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2650     InitBasicFS, Always, TestOutputList (
2651       [["mkdir_p"; "/a/b/c"];
2652        ["touch"; "/a/b/c/d"];
2653        ["touch"; "/a/b/c/e"];
2654        ["glob_expand"; "/a/*/x/*"]], [])],
2655    "expand a wildcard path",
2656    "\
2657 This command searches for all the pathnames matching
2658 C<pattern> according to the wildcard expansion rules
2659 used by the shell.
2660
2661 If no paths match, then this returns an empty list
2662 (note: not an error).
2663
2664 It is just a wrapper around the C L<glob(3)> function
2665 with flags C<GLOB_MARK|GLOB_BRACE>.
2666 See that manual page for more details.");
2667
2668   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2669    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2670       [["scrub_device"; "/dev/sdc"]])],
2671    "scrub (securely wipe) a device",
2672    "\
2673 This command writes patterns over C<device> to make data retrieval
2674 more difficult.
2675
2676 It is an interface to the L<scrub(1)> program.  See that
2677 manual page for more details.");
2678
2679   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2680    [InitBasicFS, Always, TestRun (
2681       [["write_file"; "/file"; "content"; "0"];
2682        ["scrub_file"; "/file"]])],
2683    "scrub (securely wipe) a file",
2684    "\
2685 This command writes patterns over a file to make data retrieval
2686 more difficult.
2687
2688 The file is I<removed> after scrubbing.
2689
2690 It is an interface to the L<scrub(1)> program.  See that
2691 manual page for more details.");
2692
2693   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2694    [], (* XXX needs testing *)
2695    "scrub (securely wipe) free space",
2696    "\
2697 This command creates the directory C<dir> and then fills it
2698 with files until the filesystem is full, and scrubs the files
2699 as for C<guestfs_scrub_file>, and deletes them.
2700 The intention is to scrub any free space on the partition
2701 containing C<dir>.
2702
2703 It is an interface to the L<scrub(1)> program.  See that
2704 manual page for more details.");
2705
2706   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2707    [InitBasicFS, Always, TestRun (
2708       [["mkdir"; "/tmp"];
2709        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2710    "create a temporary directory",
2711    "\
2712 This command creates a temporary directory.  The
2713 C<template> parameter should be a full pathname for the
2714 temporary directory name with the final six characters being
2715 \"XXXXXX\".
2716
2717 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2718 the second one being suitable for Windows filesystems.
2719
2720 The name of the temporary directory that was created
2721 is returned.
2722
2723 The temporary directory is created with mode 0700
2724 and is owned by root.
2725
2726 The caller is responsible for deleting the temporary
2727 directory and its contents after use.
2728
2729 See also: L<mkdtemp(3)>");
2730
2731   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2732    [InitISOFS, Always, TestOutputInt (
2733       [["wc_l"; "/10klines"]], 10000)],
2734    "count lines in a file",
2735    "\
2736 This command counts the lines in a file, using the
2737 C<wc -l> external command.");
2738
2739   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2740    [InitISOFS, Always, TestOutputInt (
2741       [["wc_w"; "/10klines"]], 10000)],
2742    "count words in a file",
2743    "\
2744 This command counts the words in a file, using the
2745 C<wc -w> external command.");
2746
2747   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2748    [InitISOFS, Always, TestOutputInt (
2749       [["wc_c"; "/100kallspaces"]], 102400)],
2750    "count characters in a file",
2751    "\
2752 This command counts the characters in a file, using the
2753 C<wc -c> external command.");
2754
2755   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2756    [InitISOFS, Always, TestOutputList (
2757       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2758    "return first 10 lines of a file",
2759    "\
2760 This command returns up to the first 10 lines of a file as
2761 a list of strings.");
2762
2763   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2764    [InitISOFS, Always, TestOutputList (
2765       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2766     InitISOFS, Always, TestOutputList (
2767       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2768     InitISOFS, Always, TestOutputList (
2769       [["head_n"; "0"; "/10klines"]], [])],
2770    "return first N lines of a file",
2771    "\
2772 If the parameter C<nrlines> is a positive number, this returns the first
2773 C<nrlines> lines of the file C<path>.
2774
2775 If the parameter C<nrlines> is a negative number, this returns lines
2776 from the file C<path>, excluding the last C<nrlines> lines.
2777
2778 If the parameter C<nrlines> is zero, this returns an empty list.");
2779
2780   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2781    [InitISOFS, Always, TestOutputList (
2782       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2783    "return last 10 lines of a file",
2784    "\
2785 This command returns up to the last 10 lines of a file as
2786 a list of strings.");
2787
2788   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2789    [InitISOFS, Always, TestOutputList (
2790       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2791     InitISOFS, Always, TestOutputList (
2792       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2793     InitISOFS, Always, TestOutputList (
2794       [["tail_n"; "0"; "/10klines"]], [])],
2795    "return last N lines of a file",
2796    "\
2797 If the parameter C<nrlines> is a positive number, this returns the last
2798 C<nrlines> lines of the file C<path>.
2799
2800 If the parameter C<nrlines> is a negative number, this returns lines
2801 from the file C<path>, starting with the C<-nrlines>th line.
2802
2803 If the parameter C<nrlines> is zero, this returns an empty list.");
2804
2805   ("df", (RString "output", []), 125, [],
2806    [], (* XXX Tricky to test because it depends on the exact format
2807         * of the 'df' command and other imponderables.
2808         *)
2809    "report file system disk space usage",
2810    "\
2811 This command runs the C<df> command to report disk space used.
2812
2813 This command is mostly useful for interactive sessions.  It
2814 is I<not> intended that you try to parse the output string.
2815 Use C<statvfs> from programs.");
2816
2817   ("df_h", (RString "output", []), 126, [],
2818    [], (* XXX Tricky to test because it depends on the exact format
2819         * of the 'df' command and other imponderables.
2820         *)
2821    "report file system disk space usage (human readable)",
2822    "\
2823 This command runs the C<df -h> command to report disk space used
2824 in human-readable format.
2825
2826 This command is mostly useful for interactive sessions.  It
2827 is I<not> intended that you try to parse the output string.
2828 Use C<statvfs> from programs.");
2829
2830   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2831    [InitISOFS, Always, TestOutputInt (
2832       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2833    "estimate file space usage",
2834    "\
2835 This command runs the C<du -s> command to estimate file space
2836 usage for C<path>.
2837
2838 C<path> can be a file or a directory.  If C<path> is a directory
2839 then the estimate includes the contents of the directory and all
2840 subdirectories (recursively).
2841
2842 The result is the estimated size in I<kilobytes>
2843 (ie. units of 1024 bytes).");
2844
2845   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2846    [InitISOFS, Always, TestOutputList (
2847       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2848    "list files in an initrd",
2849    "\
2850 This command lists out files contained in an initrd.
2851
2852 The files are listed without any initial C</> character.  The
2853 files are listed in the order they appear (not necessarily
2854 alphabetical).  Directory names are listed as separate items.
2855
2856 Old Linux kernels (2.4 and earlier) used a compressed ext2
2857 filesystem as initrd.  We I<only> support the newer initramfs
2858 format (compressed cpio files).");
2859
2860   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2861    [],
2862    "mount a file using the loop device",
2863    "\
2864 This command lets you mount C<file> (a filesystem image
2865 in a file) on a mount point.  It is entirely equivalent to
2866 the command C<mount -o loop file mountpoint>.");
2867
2868   ("mkswap", (RErr, [Device "device"]), 130, [],
2869    [InitEmpty, Always, TestRun (
2870       [["part_disk"; "/dev/sda"; "mbr"];
2871        ["mkswap"; "/dev/sda1"]])],
2872    "create a swap partition",
2873    "\
2874 Create a swap partition on C<device>.");
2875
2876   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2877    [InitEmpty, Always, TestRun (
2878       [["part_disk"; "/dev/sda"; "mbr"];
2879        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2880    "create a swap partition with a label",
2881    "\
2882 Create a swap partition on C<device> with label C<label>.
2883
2884 Note that you cannot attach a swap label to a block device
2885 (eg. C</dev/sda>), just to a partition.  This appears to be
2886 a limitation of the kernel or swap tools.");
2887
2888   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2889    (let uuid = uuidgen () in
2890     [InitEmpty, Always, TestRun (
2891        [["part_disk"; "/dev/sda"; "mbr"];
2892         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2893    "create a swap partition with an explicit UUID",
2894    "\
2895 Create a swap partition on C<device> with UUID C<uuid>.");
2896
2897   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2898    [InitBasicFS, Always, TestOutputStruct (
2899       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2900        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2901        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2902     InitBasicFS, Always, TestOutputStruct (
2903       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2904        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2905    "make block, character or FIFO devices",
2906    "\
2907 This call creates block or character special devices, or
2908 named pipes (FIFOs).
2909
2910 The C<mode> parameter should be the mode, using the standard
2911 constants.  C<devmajor> and C<devminor> are the
2912 device major and minor numbers, only used when creating block
2913 and character special devices.");
2914
2915   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2916    [InitBasicFS, Always, TestOutputStruct (
2917       [["mkfifo"; "0o777"; "/node"];
2918        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2919    "make FIFO (named pipe)",
2920    "\
2921 This call creates a FIFO (named pipe) called C<path> with
2922 mode C<mode>.  It is just a convenient wrapper around
2923 C<guestfs_mknod>.");
2924
2925   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2926    [InitBasicFS, Always, TestOutputStruct (
2927       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2928        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2929    "make block device node",
2930    "\
2931 This call creates a block device node called C<path> with
2932 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2933 It is just a convenient wrapper around C<guestfs_mknod>.");
2934
2935   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2936    [InitBasicFS, Always, TestOutputStruct (
2937       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2938        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2939    "make char device node",
2940    "\
2941 This call creates a char device node called C<path> with
2942 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2943 It is just a convenient wrapper around C<guestfs_mknod>.");
2944
2945   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2946    [], (* XXX umask is one of those stateful things that we should
2947         * reset between each test.
2948         *)
2949    "set file mode creation mask (umask)",
2950    "\
2951 This function sets the mask used for creating new files and
2952 device nodes to C<mask & 0777>.
2953
2954 Typical umask values would be C<022> which creates new files
2955 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2956 C<002> which creates new files with permissions like
2957 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2958
2959 The default umask is C<022>.  This is important because it
2960 means that directories and device nodes will be created with
2961 C<0644> or C<0755> mode even if you specify C<0777>.
2962
2963 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2964
2965 This call returns the previous umask.");
2966
2967   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2968    [],
2969    "read directories entries",
2970    "\
2971 This returns the list of directory entries in directory C<dir>.
2972
2973 All entries in the directory are returned, including C<.> and
2974 C<..>.  The entries are I<not> sorted, but returned in the same
2975 order as the underlying filesystem.
2976
2977 Also this call returns basic file type information about each
2978 file.  The C<ftyp> field will contain one of the following characters:
2979
2980 =over 4
2981
2982 =item 'b'
2983
2984 Block special
2985
2986 =item 'c'
2987
2988 Char special
2989
2990 =item 'd'
2991
2992 Directory
2993
2994 =item 'f'
2995
2996 FIFO (named pipe)
2997
2998 =item 'l'
2999
3000 Symbolic link
3001
3002 =item 'r'
3003
3004 Regular file
3005
3006 =item 's'
3007
3008 Socket
3009
3010 =item 'u'
3011
3012 Unknown file type
3013
3014 =item '?'
3015
3016 The L<readdir(3)> returned a C<d_type> field with an
3017 unexpected value
3018
3019 =back
3020
3021 This function is primarily intended for use by programs.  To
3022 get a simple list of names, use C<guestfs_ls>.  To get a printable
3023 directory for human consumption, use C<guestfs_ll>.");
3024
3025   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3026    [],
3027    "create partitions on a block device",
3028    "\
3029 This is a simplified interface to the C<guestfs_sfdisk>
3030 command, where partition sizes are specified in megabytes
3031 only (rounded to the nearest cylinder) and you don't need
3032 to specify the cyls, heads and sectors parameters which
3033 were rarely if ever used anyway.
3034
3035 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3036 and C<guestfs_part_disk>");
3037
3038   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3039    [],
3040    "determine file type inside a compressed file",
3041    "\
3042 This command runs C<file> after first decompressing C<path>
3043 using C<method>.
3044
3045 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3046
3047 Since 1.0.63, use C<guestfs_file> instead which can now
3048 process compressed files.");
3049
3050   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3051    [],
3052    "list extended attributes of a file or directory",
3053    "\
3054 This call lists the extended attributes of the file or directory
3055 C<path>.
3056
3057 At the system call level, this is a combination of the
3058 L<listxattr(2)> and L<getxattr(2)> calls.
3059
3060 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3061
3062   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3063    [],
3064    "list extended attributes of a file or directory",
3065    "\
3066 This is the same as C<guestfs_getxattrs>, but if C<path>
3067 is a symbolic link, then it returns the extended attributes
3068 of the link itself.");
3069
3070   ("setxattr", (RErr, [String "xattr";
3071                        String "val"; Int "vallen"; (* will be BufferIn *)
3072                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3073    [],
3074    "set extended attribute of a file or directory",
3075    "\
3076 This call sets the extended attribute named C<xattr>
3077 of the file C<path> to the value C<val> (of length C<vallen>).
3078 The value is arbitrary 8 bit data.
3079
3080 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3081
3082   ("lsetxattr", (RErr, [String "xattr";
3083                         String "val"; Int "vallen"; (* will be BufferIn *)
3084                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3085    [],
3086    "set extended attribute of a file or directory",
3087    "\
3088 This is the same as C<guestfs_setxattr>, but if C<path>
3089 is a symbolic link, then it sets an extended attribute
3090 of the link itself.");
3091
3092   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3093    [],
3094    "remove extended attribute of a file or directory",
3095    "\
3096 This call removes the extended attribute named C<xattr>
3097 of the file C<path>.
3098
3099 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3100
3101   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3102    [],
3103    "remove extended attribute of a file or directory",
3104    "\
3105 This is the same as C<guestfs_removexattr>, but if C<path>
3106 is a symbolic link, then it removes an extended attribute
3107 of the link itself.");
3108
3109   ("mountpoints", (RHashtable "mps", []), 147, [],
3110    [],
3111    "show mountpoints",
3112    "\
3113 This call is similar to C<guestfs_mounts>.  That call returns
3114 a list of devices.  This one returns a hash table (map) of
3115 device name to directory where the device is mounted.");
3116
3117   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3118   (* This is a special case: while you would expect a parameter
3119    * of type "Pathname", that doesn't work, because it implies
3120    * NEED_ROOT in the generated calling code in stubs.c, and
3121    * this function cannot use NEED_ROOT.
3122    *)
3123    [],
3124    "create a mountpoint",
3125    "\
3126 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3127 specialized calls that can be used to create extra mountpoints
3128 before mounting the first filesystem.
3129
3130 These calls are I<only> necessary in some very limited circumstances,
3131 mainly the case where you want to mount a mix of unrelated and/or
3132 read-only filesystems together.
3133
3134 For example, live CDs often contain a \"Russian doll\" nest of
3135 filesystems, an ISO outer layer, with a squashfs image inside, with
3136 an ext2/3 image inside that.  You can unpack this as follows
3137 in guestfish:
3138
3139  add-ro Fedora-11-i686-Live.iso
3140  run
3141  mkmountpoint /cd
3142  mkmountpoint /squash
3143  mkmountpoint /ext3
3144  mount /dev/sda /cd
3145  mount-loop /cd/LiveOS/squashfs.img /squash
3146  mount-loop /squash/LiveOS/ext3fs.img /ext3
3147
3148 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3149
3150   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3151    [],
3152    "remove a mountpoint",
3153    "\
3154 This calls removes a mountpoint that was previously created
3155 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3156 for full details.");
3157
3158   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3159    [InitISOFS, Always, TestOutputBuffer (
3160       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3161    "read a file",
3162    "\
3163 This calls returns the contents of the file C<path> as a
3164 buffer.
3165
3166 Unlike C<guestfs_cat>, this function can correctly
3167 handle files that contain embedded ASCII NUL characters.
3168 However unlike C<guestfs_download>, this function is limited
3169 in the total size of file that can be handled.");
3170
3171   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3172    [InitISOFS, Always, TestOutputList (
3173       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3174     InitISOFS, Always, TestOutputList (
3175       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3176    "return lines matching a pattern",
3177    "\
3178 This calls the external C<grep> program and returns the
3179 matching lines.");
3180
3181   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3182    [InitISOFS, Always, TestOutputList (
3183       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3184    "return lines matching a pattern",
3185    "\
3186 This calls the external C<egrep> program and returns the
3187 matching lines.");
3188
3189   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3190    [InitISOFS, Always, TestOutputList (
3191       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3192    "return lines matching a pattern",
3193    "\
3194 This calls the external C<fgrep> program and returns the
3195 matching lines.");
3196
3197   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3198    [InitISOFS, Always, TestOutputList (
3199       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3200    "return lines matching a pattern",
3201    "\
3202 This calls the external C<grep -i> program and returns the
3203 matching lines.");
3204
3205   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3206    [InitISOFS, Always, TestOutputList (
3207       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3208    "return lines matching a pattern",
3209    "\
3210 This calls the external C<egrep -i> program and returns the
3211 matching lines.");
3212
3213   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3214    [InitISOFS, Always, TestOutputList (
3215       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3216    "return lines matching a pattern",
3217    "\
3218 This calls the external C<fgrep -i> program and returns the
3219 matching lines.");
3220
3221   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputList (
3223       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3224    "return lines matching a pattern",
3225    "\
3226 This calls the external C<zgrep> program and returns the
3227 matching lines.");
3228
3229   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3230    [InitISOFS, Always, TestOutputList (
3231       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3232    "return lines matching a pattern",
3233    "\
3234 This calls the external C<zegrep> program and returns the
3235 matching lines.");
3236
3237   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3238    [InitISOFS, Always, TestOutputList (
3239       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3240    "return lines matching a pattern",
3241    "\
3242 This calls the external C<zfgrep> program and returns the
3243 matching lines.");
3244
3245   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3246    [InitISOFS, Always, TestOutputList (
3247       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3248    "return lines matching a pattern",
3249    "\
3250 This calls the external C<zgrep -i> program and returns the
3251 matching lines.");
3252
3253   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3254    [InitISOFS, Always, TestOutputList (
3255       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3256    "return lines matching a pattern",
3257    "\
3258 This calls the external C<zegrep -i> program and returns the
3259 matching lines.");
3260
3261   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3262    [InitISOFS, Always, TestOutputList (
3263       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3264    "return lines matching a pattern",
3265    "\
3266 This calls the external C<zfgrep -i> program and returns the
3267 matching lines.");
3268
3269   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3270    [InitISOFS, Always, TestOutput (
3271       [["realpath"; "/../directory"]], "/directory")],
3272    "canonicalized absolute pathname",
3273    "\
3274 Return the canonicalized absolute pathname of C<path>.  The
3275 returned path has no C<.>, C<..> or symbolic link path elements.");
3276
3277   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3278    [InitBasicFS, Always, TestOutputStruct (
3279       [["touch"; "/a"];
3280        ["ln"; "/a"; "/b"];
3281        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3282    "create a hard link",
3283    "\
3284 This command creates a hard link using the C<ln> command.");
3285
3286   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["touch"; "/a"];
3289        ["touch"; "/b"];
3290        ["ln_f"; "/a"; "/b"];
3291        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3292    "create a hard link",
3293    "\
3294 This command creates a hard link using the C<ln -f> command.
3295 The C<-f> option removes the link (C<linkname>) if it exists already.");
3296
3297   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3298    [InitBasicFS, Always, TestOutputStruct (
3299       [["touch"; "/a"];
3300        ["ln_s"; "a"; "/b"];
3301        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3302    "create a symbolic link",
3303    "\
3304 This command creates a symbolic link using the C<ln -s> command.");
3305
3306   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3307    [InitBasicFS, Always, TestOutput (
3308       [["mkdir_p"; "/a/b"];
3309        ["touch"; "/a/b/c"];
3310        ["ln_sf"; "../d"; "/a/b/c"];
3311        ["readlink"; "/a/b/c"]], "../d")],
3312    "create a symbolic link",
3313    "\
3314 This command creates a symbolic link using the C<ln -sf> command,
3315 The C<-f> option removes the link (C<linkname>) if it exists already.");
3316
3317   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3318    [] (* XXX tested above *),
3319    "read the target of a symbolic link",
3320    "\
3321 This command reads the target of a symbolic link.");
3322
3323   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3324    [InitBasicFS, Always, TestOutputStruct (
3325       [["fallocate"; "/a"; "1000000"];
3326        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3327    "preallocate a file in the guest filesystem",
3328    "\
3329 This command preallocates a file (containing zero bytes) named
3330 C<path> of size C<len> bytes.  If the file exists already, it
3331 is overwritten.
3332
3333 Do not confuse this with the guestfish-specific
3334 C<alloc> command which allocates a file in the host and
3335 attaches it as a device.");
3336
3337   ("swapon_device", (RErr, [Device "device"]), 170, [],
3338    [InitPartition, Always, TestRun (
3339       [["mkswap"; "/dev/sda1"];
3340        ["swapon_device"; "/dev/sda1"];
3341        ["swapoff_device"; "/dev/sda1"]])],
3342    "enable swap on device",
3343    "\
3344 This command enables the libguestfs appliance to use the
3345 swap device or partition named C<device>.  The increased
3346 memory is made available for all commands, for example
3347 those run using C<guestfs_command> or C<guestfs_sh>.
3348
3349 Note that you should not swap to existing guest swap
3350 partitions unless you know what you are doing.  They may
3351 contain hibernation information, or other information that
3352 the guest doesn't want you to trash.  You also risk leaking
3353 information about the host to the guest this way.  Instead,
3354 attach a new host device to the guest and swap on that.");
3355
3356   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3357    [], (* XXX tested by swapon_device *)
3358    "disable swap on device",
3359    "\
3360 This command disables the libguestfs appliance swap
3361 device or partition named C<device>.
3362 See C<guestfs_swapon_device>.");
3363
3364   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3365    [InitBasicFS, Always, TestRun (
3366       [["fallocate"; "/swap"; "8388608"];
3367        ["mkswap_file"; "/swap"];
3368        ["swapon_file"; "/swap"];
3369        ["swapoff_file"; "/swap"]])],
3370    "enable swap on file",
3371    "\
3372 This command enables swap to a file.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3376    [], (* XXX tested by swapon_file *)
3377    "disable swap on file",
3378    "\
3379 This command disables the libguestfs appliance swap on file.");
3380
3381   ("swapon_label", (RErr, [String "label"]), 174, [],
3382    [InitEmpty, Always, TestRun (
3383       [["part_disk"; "/dev/sdb"; "mbr"];
3384        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3385        ["swapon_label"; "swapit"];
3386        ["swapoff_label"; "swapit"];
3387        ["zero"; "/dev/sdb"];
3388        ["blockdev_rereadpt"; "/dev/sdb"]])],
3389    "enable swap on labeled swap partition",
3390    "\
3391 This command enables swap to a labeled swap partition.
3392 See C<guestfs_swapon_device> for other notes.");
3393
3394   ("swapoff_label", (RErr, [String "label"]), 175, [],
3395    [], (* XXX tested by swapon_label *)
3396    "disable swap on labeled swap partition",
3397    "\
3398 This command disables the libguestfs appliance swap on
3399 labeled swap partition.");
3400
3401   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3402    (let uuid = uuidgen () in
3403     [InitEmpty, Always, TestRun (
3404        [["mkswap_U"; uuid; "/dev/sdb"];
3405         ["swapon_uuid"; uuid];
3406         ["swapoff_uuid"; uuid]])]),
3407    "enable swap on swap partition by UUID",
3408    "\
3409 This command enables swap to a swap partition with the given UUID.
3410 See C<guestfs_swapon_device> for other notes.");
3411
3412   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3413    [], (* XXX tested by swapon_uuid *)
3414    "disable swap on swap partition by UUID",
3415    "\
3416 This command disables the libguestfs appliance swap partition
3417 with the given UUID.");
3418
3419   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3420    [InitBasicFS, Always, TestRun (
3421       [["fallocate"; "/swap"; "8388608"];
3422        ["mkswap_file"; "/swap"]])],
3423    "create a swap file",
3424    "\
3425 Create a swap file.
3426
3427 This command just writes a swap file signature to an existing
3428 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3429
3430   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3431    [InitISOFS, Always, TestRun (
3432       [["inotify_init"; "0"]])],
3433    "create an inotify handle",
3434    "\
3435 This command creates a new inotify handle.
3436 The inotify subsystem can be used to notify events which happen to
3437 objects in the guest filesystem.
3438
3439 C<maxevents> is the maximum number of events which will be
3440 queued up between calls to C<guestfs_inotify_read> or
3441 C<guestfs_inotify_files>.
3442 If this is passed as C<0>, then the kernel (or previously set)
3443 default is used.  For Linux 2.6.29 the default was 16384 events.
3444 Beyond this limit, the kernel throws away events, but records
3445 the fact that it threw them away by setting a flag
3446 C<IN_Q_OVERFLOW> in the returned structure list (see
3447 C<guestfs_inotify_read>).
3448
3449 Before any events are generated, you have to add some
3450 watches to the internal watch list.  See:
3451 C<guestfs_inotify_add_watch>,
3452 C<guestfs_inotify_rm_watch> and
3453 C<guestfs_inotify_watch_all>.
3454
3455 Queued up events should be read periodically by calling
3456 C<guestfs_inotify_read>
3457 (or C<guestfs_inotify_files> which is just a helpful
3458 wrapper around C<guestfs_inotify_read>).  If you don't
3459 read the events out often enough then you risk the internal
3460 queue overflowing.
3461
3462 The handle should be closed after use by calling
3463 C<guestfs_inotify_close>.  This also removes any
3464 watches automatically.
3465
3466 See also L<inotify(7)> for an overview of the inotify interface
3467 as exposed by the Linux kernel, which is roughly what we expose
3468 via libguestfs.  Note that there is one global inotify handle
3469 per libguestfs instance.");
3470
3471   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3472    [InitBasicFS, Always, TestOutputList (
3473       [["inotify_init"; "0"];
3474        ["inotify_add_watch"; "/"; "1073741823"];
3475        ["touch"; "/a"];
3476        ["touch"; "/b"];
3477        ["inotify_files"]], ["a"; "b"])],
3478    "add an inotify watch",
3479    "\
3480 Watch C<path> for the events listed in C<mask>.
3481
3482 Note that if C<path> is a directory then events within that
3483 directory are watched, but this does I<not> happen recursively
3484 (in subdirectories).
3485
3486 Note for non-C or non-Linux callers: the inotify events are
3487 defined by the Linux kernel ABI and are listed in
3488 C</usr/include/sys/inotify.h>.");
3489
3490   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3491    [],
3492    "remove an inotify watch",
3493    "\
3494 Remove a previously defined inotify watch.
3495 See C<guestfs_inotify_add_watch>.");
3496
3497   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3498    [],
3499    "return list of inotify events",
3500    "\
3501 Return the complete queue of events that have happened
3502 since the previous read call.
3503
3504 If no events have happened, this returns an empty list.
3505
3506 I<Note>: In order to make sure that all events have been
3507 read, you must call this function repeatedly until it
3508 returns an empty list.  The reason is that the call will
3509 read events up to the maximum appliance-to-host message
3510 size and leave remaining events in the queue.");
3511
3512   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3513    [],
3514    "return list of watched files that had events",
3515    "\
3516 This function is a helpful wrapper around C<guestfs_inotify_read>
3517 which just returns a list of pathnames of objects that were
3518 touched.  The returned pathnames are sorted and deduplicated.");
3519
3520   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3521    [],
3522    "close the inotify handle",
3523    "\
3524 This closes the inotify handle which was previously
3525 opened by inotify_init.  It removes all watches, throws
3526 away any pending events, and deallocates all resources.");
3527
3528   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3529    [],
3530    "set SELinux security context",
3531    "\
3532 This sets the SELinux security context of the daemon
3533 to the string C<context>.
3534
3535 See the documentation about SELINUX in L<guestfs(3)>.");
3536
3537   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3538    [],
3539    "get SELinux security context",
3540    "\
3541 This gets the SELinux security context of the daemon.
3542
3543 See the documentation about SELINUX in L<guestfs(3)>,
3544 and C<guestfs_setcon>");
3545
3546   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3547    [InitEmpty, Always, TestOutput (
3548       [["part_disk"; "/dev/sda"; "mbr"];
3549        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3550        ["mount"; "/dev/sda1"; "/"];
3551        ["write_file"; "/new"; "new file contents"; "0"];
3552        ["cat"; "/new"]], "new file contents")],
3553    "make a filesystem with block size",
3554    "\
3555 This call is similar to C<guestfs_mkfs>, but it allows you to
3556 control the block size of the resulting filesystem.  Supported
3557 block sizes depend on the filesystem type, but typically they
3558 are C<1024>, C<2048> or C<4096> only.");
3559
3560   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3561    [InitEmpty, Always, TestOutput (
3562       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3563        ["mke2journal"; "4096"; "/dev/sda1"];
3564        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3565        ["mount"; "/dev/sda2"; "/"];
3566        ["write_file"; "/new"; "new file contents"; "0"];
3567        ["cat"; "/new"]], "new file contents")],
3568    "make ext2/3/4 external journal",
3569    "\
3570 This creates an ext2 external journal on C<device>.  It is equivalent
3571 to the command:
3572
3573  mke2fs -O journal_dev -b blocksize device");
3574
3575   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3576    [InitEmpty, Always, TestOutput (
3577       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3578        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3579        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3580        ["mount"; "/dev/sda2"; "/"];
3581        ["write_file"; "/new"; "new file contents"; "0"];
3582        ["cat"; "/new"]], "new file contents")],
3583    "make ext2/3/4 external journal with label",
3584    "\
3585 This creates an ext2 external journal on C<device> with label C<label>.");
3586
3587   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3588    (let uuid = uuidgen () in
3589     [InitEmpty, Always, TestOutput (
3590        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3591         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3592         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3593         ["mount"; "/dev/sda2"; "/"];
3594         ["write_file"; "/new"; "new file contents"; "0"];
3595         ["cat"; "/new"]], "new file contents")]),
3596    "make ext2/3/4 external journal with UUID",
3597    "\
3598 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3599
3600   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3601    [],
3602    "make ext2/3/4 filesystem with external journal",
3603    "\
3604 This creates an ext2/3/4 filesystem on C<device> with
3605 an external journal on C<journal>.  It is equivalent
3606 to the command:
3607
3608  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3609
3610 See also C<guestfs_mke2journal>.");
3611
3612   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3613    [],
3614    "make ext2/3/4 filesystem with external journal",
3615    "\
3616 This creates an ext2/3/4 filesystem on C<device> with
3617 an external journal on the journal labeled C<label>.
3618
3619 See also C<guestfs_mke2journal_L>.");
3620
3621   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3622    [],
3623    "make ext2/3/4 filesystem with external journal",
3624    "\
3625 This creates an ext2/3/4 filesystem on C<device> with
3626 an external journal on the journal with UUID C<uuid>.
3627
3628 See also C<guestfs_mke2journal_U>.");
3629
3630   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3631    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3632    "load a kernel module",
3633    "\
3634 This loads a kernel module in the appliance.
3635
3636 The kernel module must have been whitelisted when libguestfs
3637 was built (see C<appliance/kmod.whitelist.in> in the source).");
3638
3639   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3640    [InitNone, Always, TestOutput (
3641      [["echo_daemon"; "This is a test"]], "This is a test"
3642    )],
3643    "echo arguments back to the client",
3644    "\
3645 This command concatenate the list of C<words> passed with single spaces between
3646 them and returns the resulting string.
3647
3648 You can use this command to test the connection through to the daemon.
3649
3650 See also C<guestfs_ping_daemon>.");
3651
3652   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3653    [], (* There is a regression test for this. *)
3654    "find all files and directories, returning NUL-separated list",
3655    "\
3656 This command lists out all files and directories, recursively,
3657 starting at C<directory>, placing the resulting list in the
3658 external file called C<files>.
3659
3660 This command works the same way as C<guestfs_find> with the
3661 following exceptions:
3662
3663 =over 4
3664
3665 =item *
3666
3667 The resulting list is written to an external file.
3668
3669 =item *
3670
3671 Items (filenames) in the result are separated
3672 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3673
3674 =item *
3675
3676 This command is not limited in the number of names that it
3677 can return.
3678
3679 =item *
3680
3681 The result list is not sorted.
3682
3683 =back");
3684
3685   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3686    [InitISOFS, Always, TestOutput (
3687       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3688     InitISOFS, Always, TestOutput (
3689       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3690     InitISOFS, Always, TestOutput (
3691       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3692     InitISOFS, Always, TestLastFail (
3693       [["case_sensitive_path"; "/Known-1/"]]);
3694     InitBasicFS, Always, TestOutput (
3695       [["mkdir"; "/a"];
3696        ["mkdir"; "/a/bbb"];
3697        ["touch"; "/a/bbb/c"];
3698        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3699     InitBasicFS, Always, TestOutput (
3700       [["mkdir"; "/a"];
3701        ["mkdir"; "/a/bbb"];
3702        ["touch"; "/a/bbb/c"];
3703        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3704     InitBasicFS, Always, TestLastFail (
3705       [["mkdir"; "/a"];
3706        ["mkdir"; "/a/bbb"];
3707        ["touch"; "/a/bbb/c"];
3708        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3709    "return true path on case-insensitive filesystem",
3710    "\
3711 This can be used to resolve case insensitive paths on
3712 a filesystem which is case sensitive.  The use case is
3713 to resolve paths which you have read from Windows configuration
3714 files or the Windows Registry, to the true path.
3715
3716 The command handles a peculiarity of the Linux ntfs-3g
3717 filesystem driver (and probably others), which is that although
3718 the underlying filesystem is case-insensitive, the driver
3719 exports the filesystem to Linux as case-sensitive.
3720
3721 One consequence of this is that special directories such
3722 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3723 (or other things) depending on the precise details of how
3724 they were created.  In Windows itself this would not be
3725 a problem.
3726
3727 Bug or feature?  You decide:
3728 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3729
3730 This function resolves the true case of each element in the
3731 path and returns the case-sensitive path.
3732
3733 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3734 might return C<\"/WINDOWS/system32\"> (the exact return value
3735 would depend on details of how the directories were originally
3736 created under Windows).
3737
3738 I<Note>:
3739 This function does not handle drive names, backslashes etc.
3740
3741 See also C<guestfs_realpath>.");
3742
3743   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3744    [InitBasicFS, Always, TestOutput (
3745       [["vfs_type"; "/dev/sda1"]], "ext2")],
3746    "get the Linux VFS type corresponding to a mounted device",
3747    "\
3748 This command gets the block device type corresponding to
3749 a mounted device called C<device>.
3750
3751 Usually the result is the name of the Linux VFS module that
3752 is used to mount this device (probably determined automatically
3753 if you used the C<guestfs_mount> call).");
3754
3755   ("truncate", (RErr, [Pathname "path"]), 199, [],
3756    [InitBasicFS, Always, TestOutputStruct (
3757       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3758        ["truncate"; "/test"];
3759        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3760    "truncate a file to zero size",
3761    "\
3762 This command truncates C<path> to a zero-length file.  The
3763 file must exist already.");
3764
3765   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3766    [InitBasicFS, Always, TestOutputStruct (
3767       [["touch"; "/test"];
3768        ["truncate_size"; "/test"; "1000"];
3769        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3770    "truncate a file to a particular size",
3771    "\
3772 This command truncates C<path> to size C<size> bytes.  The file
3773 must exist already.  If the file is smaller than C<size> then
3774 the file is extended to the required size with null bytes.");
3775
3776   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3777    [InitBasicFS, Always, TestOutputStruct (
3778       [["touch"; "/test"];
3779        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3780        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3781    "set timestamp of a file with nanosecond precision",
3782    "\
3783 This command sets the timestamps of a file with nanosecond
3784 precision.
3785
3786 C<atsecs, atnsecs> are the last access time (atime) in secs and
3787 nanoseconds from the epoch.
3788
3789 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3790 secs and nanoseconds from the epoch.
3791
3792 If the C<*nsecs> field contains the special value C<-1> then
3793 the corresponding timestamp is set to the current time.  (The
3794 C<*secs> field is ignored in this case).
3795
3796 If the C<*nsecs> field contains the special value C<-2> then
3797 the corresponding timestamp is left unchanged.  (The
3798 C<*secs> field is ignored in this case).");
3799
3800   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3801    [InitBasicFS, Always, TestOutputStruct (
3802       [["mkdir_mode"; "/test"; "0o111"];
3803        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3804    "create a directory with a particular mode",
3805    "\
3806 This command creates a directory, setting the initial permissions
3807 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3808
3809   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3810    [], (* XXX *)
3811    "change file owner and group",
3812    "\
3813 Change the file owner to C<owner> and group to C<group>.
3814 This is like C<guestfs_chown> but if C<path> is a symlink then
3815 the link itself is changed, not the target.
3816
3817 Only numeric uid and gid are supported.  If you want to use
3818 names, you will need to locate and parse the password file
3819 yourself (Augeas support makes this relatively easy).");
3820
3821   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3822    [], (* XXX *)
3823    "lstat on multiple files",
3824    "\
3825 This call allows you to perform the C<guestfs_lstat> operation
3826 on multiple files, where all files are in the directory C<path>.
3827 C<names> is the list of files from this directory.
3828
3829 On return you get a list of stat structs, with a one-to-one
3830 correspondence to the C<names> list.  If any name did not exist
3831 or could not be lstat'd, then the C<ino> field of that structure
3832 is set to C<-1>.
3833
3834 This call is intended for programs that want to efficiently
3835 list a directory contents without making many round-trips.
3836 See also C<guestfs_lxattrlist> for a similarly efficient call
3837 for getting extended attributes.  Very long directory listings
3838 might cause the protocol message size to be exceeded, causing
3839 this call to fail.  The caller must split up such requests
3840 into smaller groups of names.");
3841
3842   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3843    [], (* XXX *)
3844    "lgetxattr on multiple files",
3845    "\
3846 This call allows you to get the extended attributes
3847 of multiple files, where all files are in the directory C<path>.
3848 C<names> is the list of files from this directory.
3849
3850 On return you get a flat list of xattr structs which must be
3851 interpreted sequentially.  The first xattr struct always has a zero-length
3852 C<attrname>.  C<attrval> in this struct is zero-length
3853 to indicate there was an error doing C<lgetxattr> for this
3854 file, I<or> is a C string which is a decimal number
3855 (the number of following attributes for this file, which could
3856 be C<\"0\">).  Then after the first xattr struct are the
3857 zero or more attributes for the first named file.
3858 This repeats for the second and subsequent files.
3859
3860 This call is intended for programs that want to efficiently
3861 list a directory contents without making many round-trips.
3862 See also C<guestfs_lstatlist> for a similarly efficient call
3863 for getting standard stats.  Very long directory listings
3864 might cause the protocol message size to be exceeded, causing
3865 this call to fail.  The caller must split up such requests
3866 into smaller groups of names.");
3867
3868   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3869    [], (* XXX *)
3870    "readlink on multiple files",
3871    "\
3872 This call allows you to do a C<readlink> operation
3873 on multiple files, where all files are in the directory C<path>.
3874 C<names> is the list of files from this directory.
3875
3876 On return you get a list of strings, with a one-to-one
3877 correspondence to the C<names> list.  Each string is the
3878 value of the symbol link.
3879
3880 If the C<readlink(2)> operation fails on any name, then
3881 the corresponding result string is the empty string C<\"\">.
3882 However the whole operation is completed even if there
3883 were C<readlink(2)> errors, and so you can call this
3884 function with names where you don't know if they are
3885 symbolic links already (albeit slightly less efficient).
3886
3887 This call is intended for programs that want to efficiently
3888 list a directory contents without making many round-trips.
3889 Very long directory listings might cause the protocol
3890 message size to be exceeded, causing
3891 this call to fail.  The caller must split up such requests
3892 into smaller groups of names.");
3893
3894   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3895    [InitISOFS, Always, TestOutputBuffer (
3896       [["pread"; "/known-4"; "1"; "3"]], "\n");
3897     InitISOFS, Always, TestOutputBuffer (
3898       [["pread"; "/empty"; "0"; "100"]], "")],
3899    "read part of a file",
3900    "\
3901 This command lets you read part of a file.  It reads C<count>
3902 bytes of the file, starting at C<offset>, from file C<path>.
3903
3904 This may read fewer bytes than requested.  For further details
3905 see the L<pread(2)> system call.");
3906
3907   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3908    [InitEmpty, Always, TestRun (
3909       [["part_init"; "/dev/sda"; "gpt"]])],
3910    "create an empty partition table",
3911    "\
3912 This creates an empty partition table on C<device> of one of the
3913 partition types listed below.  Usually C<parttype> should be
3914 either C<msdos> or C<gpt> (for large disks).
3915
3916 Initially there are no partitions.  Following this, you should
3917 call C<guestfs_part_add> for each partition required.
3918
3919 Possible values for C<parttype> are:
3920
3921 =over 4
3922
3923 =item B<efi> | B<gpt>
3924
3925 Intel EFI / GPT partition table.
3926
3927 This is recommended for >= 2 TB partitions that will be accessed
3928 from Linux and Intel-based Mac OS X.  It also has limited backwards
3929 compatibility with the C<mbr> format.
3930
3931 =item B<mbr> | B<msdos>
3932
3933 The standard PC \"Master Boot Record\" (MBR) format used
3934 by MS-DOS and Windows.  This partition type will B<only> work
3935 for device sizes up to 2 TB.  For large disks we recommend
3936 using C<gpt>.
3937
3938 =back
3939
3940 Other partition table types that may work but are not
3941 supported include:
3942
3943 =over 4
3944
3945 =item B<aix>
3946
3947 AIX disk labels.
3948
3949 =item B<amiga> | B<rdb>
3950
3951 Amiga \"Rigid Disk Block\" format.
3952
3953 =item B<bsd>
3954
3955 BSD disk labels.
3956
3957 =item B<dasd>
3958
3959 DASD, used on IBM mainframes.
3960
3961 =item B<dvh>
3962
3963 MIPS/SGI volumes.
3964
3965 =item B<mac>
3966
3967 Old Mac partition format.  Modern Macs use C<gpt>.
3968
3969 =item B<pc98>
3970
3971 NEC PC-98 format, common in Japan apparently.
3972
3973 =item B<sun>
3974
3975 Sun disk labels.
3976
3977 =back");
3978
3979   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3980    [InitEmpty, Always, TestRun (
3981       [["part_init"; "/dev/sda"; "mbr"];
3982        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3983     InitEmpty, Always, TestRun (
3984       [["part_init"; "/dev/sda"; "gpt"];
3985        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3986        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3987     InitEmpty, Always, TestRun (
3988       [["part_init"; "/dev/sda"; "mbr"];
3989        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3990        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3991        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3992        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3993    "add a partition to the device",
3994    "\
3995 This command adds a partition to C<device>.  If there is no partition
3996 table on the device, call C<guestfs_part_init> first.
3997
3998 The C<prlogex> parameter is the type of partition.  Normally you
3999 should pass C<p> or C<primary> here, but MBR partition tables also
4000 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4001 types.
4002
4003 C<startsect> and C<endsect> are the start and end of the partition
4004 in I<sectors>.  C<endsect> may be negative, which means it counts
4005 backwards from the end of the disk (C<-1> is the last sector).
4006
4007 Creating a partition which covers the whole disk is not so easy.
4008 Use C<guestfs_part_disk> to do that.");
4009
4010   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4011    [InitEmpty, Always, TestRun (
4012       [["part_disk"; "/dev/sda"; "mbr"]]);
4013     InitEmpty, Always, TestRun (
4014       [["part_disk"; "/dev/sda"; "gpt"]])],
4015    "partition whole disk with a single primary partition",
4016    "\
4017 This command is simply a combination of C<guestfs_part_init>
4018 followed by C<guestfs_part_add> to create a single primary partition
4019 covering the whole disk.
4020
4021 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4022 but other possible values are described in C<guestfs_part_init>.");
4023
4024   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4025    [InitEmpty, Always, TestRun (
4026       [["part_disk"; "/dev/sda"; "mbr"];
4027        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4028    "make a partition bootable",
4029    "\
4030 This sets the bootable flag on partition numbered C<partnum> on
4031 device C<device>.  Note that partitions are numbered from 1.
4032
4033 The bootable flag is used by some PC BIOSes to determine which
4034 partition to boot from.  It is by no means universally recognized,
4035 and in any case if your operating system installed a boot
4036 sector on the device itself, then that takes precedence.");
4037
4038   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4039    [InitEmpty, Always, TestRun (
4040       [["part_disk"; "/dev/sda"; "gpt"];
4041        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4042    "set partition name",
4043    "\
4044 This sets the partition name on partition numbered C<partnum> on
4045 device C<device>.  Note that partitions are numbered from 1.
4046
4047 The partition name can only be set on certain types of partition
4048 table.  This works on C<gpt> but not on C<mbr> partitions.");
4049
4050   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4051    [], (* XXX Add a regression test for this. *)
4052    "list partitions on a device",
4053    "\
4054 This command parses the partition table on C<device> and
4055 returns the list of partitions found.
4056
4057 The fields in the returned structure are:
4058
4059 =over 4
4060
4061 =item B<part_num>
4062
4063 Partition number, counting from 1.
4064
4065 =item B<part_start>
4066
4067 Start of the partition I<in bytes>.  To get sectors you have to
4068 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4069
4070 =item B<part_end>
4071
4072 End of the partition in bytes.
4073
4074 =item B<part_size>
4075
4076 Size of the partition in bytes.
4077
4078 =back");
4079
4080   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4081    [InitEmpty, Always, TestOutput (
4082       [["part_disk"; "/dev/sda"; "gpt"];
4083        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4084    "get the partition table type",
4085    "\
4086 This command examines the partition table on C<device> and
4087 returns the partition table type (format) being used.
4088
4089 Common return values include: C<msdos> (a DOS/Windows style MBR
4090 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4091 values are possible, although unusual.  See C<guestfs_part_init>
4092 for a full list.");
4093
4094   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4095    [InitBasicFS, Always, TestOutputBuffer (
4096       [["fill"; "0x63"; "10"; "/test"];
4097        ["read_file"; "/test"]], "cccccccccc")],
4098    "fill a file with octets",
4099    "\
4100 This command creates a new file called C<path>.  The initial
4101 content of the file is C<len> octets of C<c>, where C<c>
4102 must be a number in the range C<[0..255]>.
4103
4104 To fill a file with zero bytes (sparsely), it is
4105 much more efficient to use C<guestfs_truncate_size>.");
4106
4107   ("available", (RErr, [StringList "groups"]), 216, [],
4108    [],
4109    "test availability of some parts of the API",
4110    "\
4111 This command is used to check the availability of some
4112 groups of libguestfs functions which not all builds of
4113 libguestfs will be able to provide.
4114
4115 The precise libguestfs function groups that may be checked by this
4116 command are listed in L<guestfs(3)/AVAILABILITY>.
4117
4118 The argument C<groups> is a list of API group names, eg:
4119 C<[\"inotify\", \"augeas\"]> would check for the availability of
4120 the C<guestfs_inotify_*> functions and C<guestfs_aug_*>
4121 (partition editing) functions.
4122
4123 The command returns no error if I<all> requested groups are available.
4124
4125 It returns an error if one or more of the requested
4126 groups is unavailable.
4127
4128 If an unknown group name is included in the
4129 list of C<groups> then an error is always returned.
4130
4131 I<Notes:>
4132
4133 =over 4
4134
4135 =item *
4136
4137 You must call C<guestfs_launch> before calling this function.
4138 The reason is because we don't know what function groups are
4139 supported by the appliance/daemon until it is running and can
4140 be queried.
4141
4142 =item *
4143
4144 If a group of functions is available, this does not necessarily
4145 mean that they will work.  You still have to check for errors
4146 when calling individual API functions even if they are
4147 available.
4148
4149 =item *
4150
4151 It is usually the job of distro packagers to build
4152 complete functionality into the libguestfs appliance.
4153 Upstream libguestfs, if built from source with all
4154 requirements satisfied, will support everything.
4155
4156 =item *
4157
4158 This call was added in version C<1.0.80>.  In previous
4159 versions of libguestfs all you could do would be to speculatively
4160 execute a command to find out if the daemon implemented it.
4161 See also C<guestfs_version>.
4162
4163 =back");
4164
4165 ]
4166
4167 let all_functions = non_daemon_functions @ daemon_functions
4168
4169 (* In some places we want the functions to be displayed sorted
4170  * alphabetically, so this is useful:
4171  *)
4172 let all_functions_sorted =
4173   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4174                compare n1 n2) all_functions
4175
4176 (* Field types for structures. *)
4177 type field =
4178   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4179   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4180   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4181   | FUInt32
4182   | FInt32
4183   | FUInt64
4184   | FInt64
4185   | FBytes                      (* Any int measure that counts bytes. *)
4186   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4187   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4188
4189 (* Because we generate extra parsing code for LVM command line tools,
4190  * we have to pull out the LVM columns separately here.
4191  *)
4192 let lvm_pv_cols = [
4193   "pv_name", FString;
4194   "pv_uuid", FUUID;
4195   "pv_fmt", FString;
4196   "pv_size", FBytes;
4197   "dev_size", FBytes;
4198   "pv_free", FBytes;
4199   "pv_used", FBytes;
4200   "pv_attr", FString (* XXX *);
4201   "pv_pe_count", FInt64;
4202   "pv_pe_alloc_count", FInt64;
4203   "pv_tags", FString;
4204   "pe_start", FBytes;
4205   "pv_mda_count", FInt64;
4206   "pv_mda_free", FBytes;
4207   (* Not in Fedora 10:
4208      "pv_mda_size", FBytes;
4209   *)
4210 ]
4211 let lvm_vg_cols = [
4212   "vg_name", FString;
4213   "vg_uuid", FUUID;
4214   "vg_fmt", FString;
4215   "vg_attr", FString (* XXX *);
4216   "vg_size", FBytes;
4217   "vg_free", FBytes;
4218   "vg_sysid", FString;
4219   "vg_extent_size", FBytes;
4220   "vg_extent_count", FInt64;
4221   "vg_free_count", FInt64;
4222   "max_lv", FInt64;
4223   "max_pv", FInt64;
4224   "pv_count", FInt64;
4225   "lv_count", FInt64;
4226   "snap_count", FInt64;
4227   "vg_seqno", FInt64;
4228   "vg_tags", FString;
4229   "vg_mda_count", FInt64;
4230   "vg_mda_free", FBytes;
4231   (* Not in Fedora 10:
4232      "vg_mda_size", FBytes;
4233   *)
4234 ]
4235 let lvm_lv_cols = [
4236   "lv_name", FString;
4237   "lv_uuid", FUUID;
4238   "lv_attr", FString (* XXX *);
4239   "lv_major", FInt64;
4240   "lv_minor", FInt64;
4241   "lv_kernel_major", FInt64;
4242   "lv_kernel_minor", FInt64;
4243   "lv_size", FBytes;
4244   "seg_count", FInt64;
4245   "origin", FString;
4246   "snap_percent", FOptPercent;
4247   "copy_percent", FOptPercent;
4248   "move_pv", FString;
4249   "lv_tags", FString;
4250   "mirror_log", FString;
4251   "modules", FString;
4252 ]
4253
4254 (* Names and fields in all structures (in RStruct and RStructList)
4255  * that we support.
4256  *)
4257 let structs = [
4258   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4259    * not use this struct in any new code.
4260    *)
4261   "int_bool", [
4262     "i", FInt32;                (* for historical compatibility *)
4263     "b", FInt32;                (* for historical compatibility *)
4264   ];
4265
4266   (* LVM PVs, VGs, LVs. *)
4267   "lvm_pv", lvm_pv_cols;
4268   "lvm_vg", lvm_vg_cols;
4269   "lvm_lv", lvm_lv_cols;
4270
4271   (* Column names and types from stat structures.
4272    * NB. Can't use things like 'st_atime' because glibc header files
4273    * define some of these as macros.  Ugh.
4274    *)
4275   "stat", [
4276     "dev", FInt64;
4277     "ino", FInt64;
4278     "mode", FInt64;
4279     "nlink", FInt64;
4280     "uid", FInt64;
4281     "gid", FInt64;
4282     "rdev", FInt64;
4283     "size", FInt64;
4284     "blksize", FInt64;
4285     "blocks", FInt64;
4286     "atime", FInt64;
4287     "mtime", FInt64;
4288     "ctime", FInt64;
4289   ];
4290   "statvfs", [
4291     "bsize", FInt64;
4292     "frsize", FInt64;
4293     "blocks", FInt64;
4294     "bfree", FInt64;
4295     "bavail", FInt64;
4296     "files", FInt64;
4297     "ffree", FInt64;
4298     "favail", FInt64;
4299     "fsid", FInt64;
4300     "flag", FInt64;
4301     "namemax", FInt64;
4302   ];
4303
4304   (* Column names in dirent structure. *)
4305   "dirent", [
4306     "ino", FInt64;
4307     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4308     "ftyp", FChar;
4309     "name", FString;
4310   ];
4311
4312   (* Version numbers. *)
4313   "version", [
4314     "major", FInt64;
4315     "minor", FInt64;
4316     "release", FInt64;
4317     "extra", FString;
4318   ];
4319
4320   (* Extended attribute. *)
4321   "xattr", [
4322     "attrname", FString;
4323     "attrval", FBuffer;
4324   ];
4325
4326   (* Inotify events. *)
4327   "inotify_event", [
4328     "in_wd", FInt64;
4329     "in_mask", FUInt32;
4330     "in_cookie", FUInt32;
4331     "in_name", FString;
4332   ];
4333
4334   (* Partition table entry. *)
4335   "partition", [
4336     "part_num", FInt32;
4337     "part_start", FBytes;
4338     "part_end", FBytes;
4339     "part_size", FBytes;
4340   ];
4341 ] (* end of structs *)
4342
4343 (* Ugh, Java has to be different ..
4344  * These names are also used by the Haskell bindings.
4345  *)
4346 let java_structs = [
4347   "int_bool", "IntBool";
4348   "lvm_pv", "PV";
4349   "lvm_vg", "VG";
4350   "lvm_lv", "LV";
4351   "stat", "Stat";
4352   "statvfs", "StatVFS";
4353   "dirent", "Dirent";
4354   "version", "Version";
4355   "xattr", "XAttr";
4356   "inotify_event", "INotifyEvent";
4357   "partition", "Partition";
4358 ]
4359
4360 (* What structs are actually returned. *)
4361 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4362
4363 (* Returns a list of RStruct/RStructList structs that are returned
4364  * by any function.  Each element of returned list is a pair:
4365  *
4366  * (structname, RStructOnly)
4367  *    == there exists function which returns RStruct (_, structname)
4368  * (structname, RStructListOnly)
4369  *    == there exists function which returns RStructList (_, structname)
4370  * (structname, RStructAndList)
4371  *    == there are functions returning both RStruct (_, structname)
4372  *                                      and RStructList (_, structname)
4373  *)
4374 let rstructs_used_by functions =
4375   (* ||| is a "logical OR" for rstructs_used_t *)
4376   let (|||) a b =
4377     match a, b with
4378     | RStructAndList, _
4379     | _, RStructAndList -> RStructAndList
4380     | RStructOnly, RStructListOnly
4381     | RStructListOnly, RStructOnly -> RStructAndList
4382     | RStructOnly, RStructOnly -> RStructOnly
4383     | RStructListOnly, RStructListOnly -> RStructListOnly
4384   in
4385
4386   let h = Hashtbl.create 13 in
4387
4388   (* if elem->oldv exists, update entry using ||| operator,
4389    * else just add elem->newv to the hash
4390    *)
4391   let update elem newv =
4392     try  let oldv = Hashtbl.find h elem in
4393          Hashtbl.replace h elem (newv ||| oldv)
4394     with Not_found -> Hashtbl.add h elem newv
4395   in
4396
4397   List.iter (
4398     fun (_, style, _, _, _, _, _) ->
4399       match fst style with
4400       | RStruct (_, structname) -> update structname RStructOnly
4401       | RStructList (_, structname) -> update structname RStructListOnly
4402       | _ -> ()
4403   ) functions;
4404
4405   (* return key->values as a list of (key,value) *)
4406   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4407
4408 (* Used for testing language bindings. *)
4409 type callt =
4410   | CallString of string
4411   | CallOptString of string option
4412   | CallStringList of string list
4413   | CallInt of int
4414   | CallInt64 of int64
4415   | CallBool of bool
4416
4417 (* Used to memoize the result of pod2text. *)
4418 let pod2text_memo_filename = "src/.pod2text.data"
4419 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4420   try
4421     let chan = open_in pod2text_memo_filename in
4422     let v = input_value chan in
4423     close_in chan;
4424     v
4425   with
4426     _ -> Hashtbl.create 13
4427 let pod2text_memo_updated () =
4428   let chan = open_out pod2text_memo_filename in
4429   output_value chan pod2text_memo;
4430   close_out chan
4431
4432 (* Useful functions.
4433  * Note we don't want to use any external OCaml libraries which
4434  * makes this a bit harder than it should be.
4435  *)
4436 let failwithf fs = ksprintf failwith fs
4437
4438 let replace_char s c1 c2 =
4439   let s2 = String.copy s in
4440   let r = ref false in
4441   for i = 0 to String.length s2 - 1 do
4442     if String.unsafe_get s2 i = c1 then (
4443       String.unsafe_set s2 i c2;
4444       r := true
4445     )
4446   done;
4447   if not !r then s else s2
4448
4449 let isspace c =
4450   c = ' '
4451   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4452
4453 let triml ?(test = isspace) str =
4454   let i = ref 0 in
4455   let n = ref (String.length str) in
4456   while !n > 0 && test str.[!i]; do
4457     decr n;
4458     incr i
4459   done;
4460   if !i = 0 then str
4461   else String.sub str !i !n
4462
4463 let trimr ?(test = isspace) str =
4464   let n = ref (String.length str) in
4465   while !n > 0 && test str.[!n-1]; do
4466     decr n
4467   done;
4468   if !n = String.length str then str
4469   else String.sub str 0 !n
4470
4471 let trim ?(test = isspace) str =
4472   trimr ~test (triml ~test str)
4473
4474 let rec find s sub =
4475   let len = String.length s in
4476   let sublen = String.length sub in
4477   let rec loop i =
4478     if i <= len-sublen then (
4479       let rec loop2 j =
4480         if j < sublen then (
4481           if s.[i+j] = sub.[j] then loop2 (j+1)
4482           else -1
4483         ) else
4484           i (* found *)
4485       in
4486       let r = loop2 0 in
4487       if r = -1 then loop (i+1) else r
4488     ) else
4489       -1 (* not found *)
4490   in
4491   loop 0
4492
4493 let rec replace_str s s1 s2 =
4494   let len = String.length s in
4495   let sublen = String.length s1 in
4496   let i = find s s1 in
4497   if i = -1 then s
4498   else (
4499     let s' = String.sub s 0 i in
4500     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4501     s' ^ s2 ^ replace_str s'' s1 s2
4502   )
4503
4504 let rec string_split sep str =
4505   let len = String.length str in
4506   let seplen = String.length sep in
4507   let i = find str sep in
4508   if i = -1 then [str]
4509   else (
4510     let s' = String.sub str 0 i in
4511     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4512     s' :: string_split sep s''
4513   )
4514
4515 let files_equal n1 n2 =
4516   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4517   match Sys.command cmd with
4518   | 0 -> true
4519   | 1 -> false
4520   | i -> failwithf "%s: failed with error code %d" cmd i
4521
4522 let rec filter_map f = function
4523   | [] -> []
4524   | x :: xs ->
4525       match f x with
4526       | Some y -> y :: filter_map f xs
4527       | None -> filter_map f xs
4528
4529 let rec find_map f = function
4530   | [] -> raise Not_found
4531   | x :: xs ->
4532       match f x with
4533       | Some y -> y
4534       | None -> find_map f xs
4535
4536 let iteri f xs =
4537   let rec loop i = function
4538     | [] -> ()
4539     | x :: xs -> f i x; loop (i+1) xs
4540   in
4541   loop 0 xs
4542
4543 let mapi f xs =
4544   let rec loop i = function
4545     | [] -> []
4546     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4547   in
4548   loop 0 xs
4549
4550 let name_of_argt = function
4551   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4552   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4553   | FileIn n | FileOut n -> n
4554
4555 let java_name_of_struct typ =
4556   try List.assoc typ java_structs
4557   with Not_found ->
4558     failwithf
4559       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4560
4561 let cols_of_struct typ =
4562   try List.assoc typ structs
4563   with Not_found ->
4564     failwithf "cols_of_struct: unknown struct %s" typ
4565
4566 let seq_of_test = function
4567   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4568   | TestOutputListOfDevices (s, _)
4569   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4570   | TestOutputTrue s | TestOutputFalse s
4571   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4572   | TestOutputStruct (s, _)
4573   | TestLastFail s -> s
4574
4575 (* Handling for function flags. *)
4576 let protocol_limit_warning =
4577   "Because of the message protocol, there is a transfer limit
4578 of somewhere between 2MB and 4MB.  To transfer large files you should use
4579 FTP."
4580
4581 let danger_will_robinson =
4582   "B<This command is dangerous.  Without careful use you
4583 can easily destroy all your data>."
4584
4585 let deprecation_notice flags =
4586   try
4587     let alt =
4588       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4589     let txt =
4590       sprintf "This function is deprecated.
4591 In new code, use the C<%s> call instead.
4592
4593 Deprecated functions will not be removed from the API, but the
4594 fact that they are deprecated indicates that there are problems
4595 with correct use of these functions." alt in
4596     Some txt
4597   with
4598     Not_found -> None
4599
4600 (* Create list of optional groups. *)
4601 let optgroups =
4602   let h = Hashtbl.create 13 in
4603   List.iter (
4604     fun (name, _, _, flags, _, _, _) ->
4605       List.iter (
4606         function
4607         | Optional group ->
4608             let names = try Hashtbl.find h group with Not_found -> [] in
4609             Hashtbl.replace h group (name :: names)
4610         | _ -> ()
4611       ) flags
4612   ) daemon_functions;
4613   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4614   let groups =
4615     List.map (
4616       fun group -> group, List.sort compare (Hashtbl.find h group)
4617     ) groups in
4618   List.sort (fun x y -> compare (fst x) (fst y)) groups
4619
4620 (* Check function names etc. for consistency. *)
4621 let check_functions () =
4622   let contains_uppercase str =
4623     let len = String.length str in
4624     let rec loop i =
4625       if i >= len then false
4626       else (
4627         let c = str.[i] in
4628         if c >= 'A' && c <= 'Z' then true
4629         else loop (i+1)
4630       )
4631     in
4632     loop 0
4633   in
4634
4635   (* Check function names. *)
4636   List.iter (
4637     fun (name, _, _, _, _, _, _) ->
4638       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4639         failwithf "function name %s does not need 'guestfs' prefix" name;
4640       if name = "" then
4641         failwithf "function name is empty";
4642       if name.[0] < 'a' || name.[0] > 'z' then
4643         failwithf "function name %s must start with lowercase a-z" name;
4644       if String.contains name '-' then
4645         failwithf "function name %s should not contain '-', use '_' instead."
4646           name
4647   ) all_functions;
4648
4649   (* Check function parameter/return names. *)
4650   List.iter (
4651     fun (name, style, _, _, _, _, _) ->
4652       let check_arg_ret_name n =
4653         if contains_uppercase n then
4654           failwithf "%s param/ret %s should not contain uppercase chars"
4655             name n;
4656         if String.contains n '-' || String.contains n '_' then
4657           failwithf "%s param/ret %s should not contain '-' or '_'"
4658             name n;
4659         if n = "value" then
4660           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;
4661         if n = "int" || n = "char" || n = "short" || n = "long" then
4662           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4663         if n = "i" || n = "n" then
4664           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4665         if n = "argv" || n = "args" then
4666           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4667
4668         (* List Haskell, OCaml and C keywords here.
4669          * http://www.haskell.org/haskellwiki/Keywords
4670          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4671          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4672          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4673          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4674          * Omitting _-containing words, since they're handled above.
4675          * Omitting the OCaml reserved word, "val", is ok,
4676          * and saves us from renaming several parameters.
4677          *)
4678         let reserved = [
4679           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4680           "char"; "class"; "const"; "constraint"; "continue"; "data";
4681           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4682           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4683           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4684           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4685           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4686           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4687           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4688           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4689           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4690           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4691           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4692           "volatile"; "when"; "where"; "while";
4693           ] in
4694         if List.mem n reserved then
4695           failwithf "%s has param/ret using reserved word %s" name n;
4696       in
4697
4698       (match fst style with
4699        | RErr -> ()
4700        | RInt n | RInt64 n | RBool n
4701        | RConstString n | RConstOptString n | RString n
4702        | RStringList n | RStruct (n, _) | RStructList (n, _)
4703        | RHashtable n | RBufferOut n ->
4704            check_arg_ret_name n
4705       );
4706       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4707   ) all_functions;
4708
4709   (* Check short descriptions. *)
4710   List.iter (
4711     fun (name, _, _, _, _, shortdesc, _) ->
4712       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4713         failwithf "short description of %s should begin with lowercase." name;
4714       let c = shortdesc.[String.length shortdesc-1] in
4715       if c = '\n' || c = '.' then
4716         failwithf "short description of %s should not end with . or \\n." name
4717   ) all_functions;
4718
4719   (* Check long dscriptions. *)
4720   List.iter (
4721     fun (name, _, _, _, _, _, longdesc) ->
4722       if longdesc.[String.length longdesc-1] = '\n' then
4723         failwithf "long description of %s should not end with \\n." name
4724   ) all_functions;
4725
4726   (* Check proc_nrs. *)
4727   List.iter (
4728     fun (name, _, proc_nr, _, _, _, _) ->
4729       if proc_nr <= 0 then
4730         failwithf "daemon function %s should have proc_nr > 0" name
4731   ) daemon_functions;
4732
4733   List.iter (
4734     fun (name, _, proc_nr, _, _, _, _) ->
4735       if proc_nr <> -1 then
4736         failwithf "non-daemon function %s should have proc_nr -1" name
4737   ) non_daemon_functions;
4738
4739   let proc_nrs =
4740     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4741       daemon_functions in
4742   let proc_nrs =
4743     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4744   let rec loop = function
4745     | [] -> ()
4746     | [_] -> ()
4747     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4748         loop rest
4749     | (name1,nr1) :: (name2,nr2) :: _ ->
4750         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4751           name1 name2 nr1 nr2
4752   in
4753   loop proc_nrs;
4754
4755   (* Check tests. *)
4756   List.iter (
4757     function
4758       (* Ignore functions that have no tests.  We generate a
4759        * warning when the user does 'make check' instead.
4760        *)
4761     | name, _, _, _, [], _, _ -> ()
4762     | name, _, _, _, tests, _, _ ->
4763         let funcs =
4764           List.map (
4765             fun (_, _, test) ->
4766               match seq_of_test test with
4767               | [] ->
4768                   failwithf "%s has a test containing an empty sequence" name
4769               | cmds -> List.map List.hd cmds
4770           ) tests in
4771         let funcs = List.flatten funcs in
4772
4773         let tested = List.mem name funcs in
4774
4775         if not tested then
4776           failwithf "function %s has tests but does not test itself" name
4777   ) all_functions
4778
4779 (* 'pr' prints to the current output file. *)
4780 let chan = ref Pervasives.stdout
4781 let pr fs = ksprintf (output_string !chan) fs
4782
4783 (* Generate a header block in a number of standard styles. *)
4784 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4785 type license = GPLv2 | LGPLv2
4786
4787 let generate_header comment license =
4788   let c = match comment with
4789     | CStyle ->     pr "/* "; " *"
4790     | HashStyle ->  pr "# ";  "#"
4791     | OCamlStyle -> pr "(* "; " *"
4792     | HaskellStyle -> pr "{- "; "  " in
4793   pr "libguestfs generated file\n";
4794   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4795   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4796   pr "%s\n" c;
4797   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4798   pr "%s\n" c;
4799   (match license with
4800    | GPLv2 ->
4801        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4802        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4803        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4804        pr "%s (at your option) any later version.\n" c;
4805        pr "%s\n" c;
4806        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4807        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4808        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4809        pr "%s GNU General Public License for more details.\n" c;
4810        pr "%s\n" c;
4811        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4812        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4813        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4814
4815    | LGPLv2 ->
4816        pr "%s This library is free software; you can redistribute it and/or\n" c;
4817        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4818        pr "%s License as published by the Free Software Foundation; either\n" c;
4819        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4820        pr "%s\n" c;
4821        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4822        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4823        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4824        pr "%s Lesser General Public License for more details.\n" c;
4825        pr "%s\n" c;
4826        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4827        pr "%s License along with this library; if not, write to the Free Software\n" c;
4828        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4829   );
4830   (match comment with
4831    | CStyle -> pr " */\n"
4832    | HashStyle -> ()
4833    | OCamlStyle -> pr " *)\n"
4834    | HaskellStyle -> pr "-}\n"
4835   );
4836   pr "\n"
4837
4838 (* Start of main code generation functions below this line. *)
4839
4840 (* Generate the pod documentation for the C API. *)
4841 let rec generate_actions_pod () =
4842   List.iter (
4843     fun (shortname, style, _, flags, _, _, longdesc) ->
4844       if not (List.mem NotInDocs flags) then (
4845         let name = "guestfs_" ^ shortname in
4846         pr "=head2 %s\n\n" name;
4847         pr " ";
4848         generate_prototype ~extern:false ~handle:"handle" name style;
4849         pr "\n\n";
4850         pr "%s\n\n" longdesc;
4851         (match fst style with
4852          | RErr ->
4853              pr "This function returns 0 on success or -1 on error.\n\n"
4854          | RInt _ ->
4855              pr "On error this function returns -1.\n\n"
4856          | RInt64 _ ->
4857              pr "On error this function returns -1.\n\n"
4858          | RBool _ ->
4859              pr "This function returns a C truth value on success or -1 on error.\n\n"
4860          | RConstString _ ->
4861              pr "This function returns a string, or NULL on error.
4862 The string is owned by the guest handle and must I<not> be freed.\n\n"
4863          | RConstOptString _ ->
4864              pr "This function returns a string which may be NULL.
4865 There is way to return an error from this function.
4866 The string is owned by the guest handle and must I<not> be freed.\n\n"
4867          | RString _ ->
4868              pr "This function returns a string, or NULL on error.
4869 I<The caller must free the returned string after use>.\n\n"
4870          | RStringList _ ->
4871              pr "This function returns a NULL-terminated array of strings
4872 (like L<environ(3)>), or NULL if there was an error.
4873 I<The caller must free the strings and the array after use>.\n\n"
4874          | RStruct (_, typ) ->
4875              pr "This function returns a C<struct guestfs_%s *>,
4876 or NULL if there was an error.
4877 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4878          | RStructList (_, typ) ->
4879              pr "This function returns a C<struct guestfs_%s_list *>
4880 (see E<lt>guestfs-structs.hE<gt>),
4881 or NULL if there was an error.
4882 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4883          | RHashtable _ ->
4884              pr "This function returns a NULL-terminated array of
4885 strings, or NULL if there was an error.
4886 The array of strings will always have length C<2n+1>, where
4887 C<n> keys and values alternate, followed by the trailing NULL entry.
4888 I<The caller must free the strings and the array after use>.\n\n"
4889          | RBufferOut _ ->
4890              pr "This function returns a buffer, or NULL on error.
4891 The size of the returned buffer is written to C<*size_r>.
4892 I<The caller must free the returned buffer after use>.\n\n"
4893         );
4894         if List.mem ProtocolLimitWarning flags then
4895           pr "%s\n\n" protocol_limit_warning;
4896         if List.mem DangerWillRobinson flags then
4897           pr "%s\n\n" danger_will_robinson;
4898         match deprecation_notice flags with
4899         | None -> ()
4900         | Some txt -> pr "%s\n\n" txt
4901       )
4902   ) all_functions_sorted
4903
4904 and generate_structs_pod () =
4905   (* Structs documentation. *)
4906   List.iter (
4907     fun (typ, cols) ->
4908       pr "=head2 guestfs_%s\n" typ;
4909       pr "\n";
4910       pr " struct guestfs_%s {\n" typ;
4911       List.iter (
4912         function
4913         | name, FChar -> pr "   char %s;\n" name
4914         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4915         | name, FInt32 -> pr "   int32_t %s;\n" name
4916         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4917         | name, FInt64 -> pr "   int64_t %s;\n" name
4918         | name, FString -> pr "   char *%s;\n" name
4919         | name, FBuffer ->
4920             pr "   /* The next two fields describe a byte array. */\n";
4921             pr "   uint32_t %s_len;\n" name;
4922             pr "   char *%s;\n" name
4923         | name, FUUID ->
4924             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4925             pr "   char %s[32];\n" name
4926         | name, FOptPercent ->
4927             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4928             pr "   float %s;\n" name
4929       ) cols;
4930       pr " };\n";
4931       pr " \n";
4932       pr " struct guestfs_%s_list {\n" typ;
4933       pr "   uint32_t len; /* Number of elements in list. */\n";
4934       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4935       pr " };\n";
4936       pr " \n";
4937       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4938       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4939         typ typ;
4940       pr "\n"
4941   ) structs
4942
4943 and generate_availability_pod () =
4944   (* Availability documentation. *)
4945   pr "=over 4\n";
4946   pr "\n";
4947   List.iter (
4948     fun (group, functions) ->
4949       pr "=item B<%s>\n" group;
4950       pr "\n";
4951       pr "The following functions:\n";
4952       List.iter (pr "L</guestfs_%s>\n") functions;
4953       pr "\n"
4954   ) optgroups;
4955   pr "=back\n";
4956   pr "\n"
4957
4958 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4959  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4960  *
4961  * We have to use an underscore instead of a dash because otherwise
4962  * rpcgen generates incorrect code.
4963  *
4964  * This header is NOT exported to clients, but see also generate_structs_h.
4965  *)
4966 and generate_xdr () =
4967   generate_header CStyle LGPLv2;
4968
4969   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4970   pr "typedef string str<>;\n";
4971   pr "\n";
4972
4973   (* Internal structures. *)
4974   List.iter (
4975     function
4976     | typ, cols ->
4977         pr "struct guestfs_int_%s {\n" typ;
4978         List.iter (function
4979                    | name, FChar -> pr "  char %s;\n" name
4980                    | name, FString -> pr "  string %s<>;\n" name
4981                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4982                    | name, FUUID -> pr "  opaque %s[32];\n" name
4983                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4984                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4985                    | name, FOptPercent -> pr "  float %s;\n" name
4986                   ) cols;
4987         pr "};\n";
4988         pr "\n";
4989         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4990         pr "\n";
4991   ) structs;
4992
4993   List.iter (
4994     fun (shortname, style, _, _, _, _, _) ->
4995       let name = "guestfs_" ^ shortname in
4996
4997       (match snd style with
4998        | [] -> ()
4999        | args ->
5000            pr "struct %s_args {\n" name;
5001            List.iter (
5002              function
5003              | Pathname n | Device n | Dev_or_Path n | String n ->
5004                  pr "  string %s<>;\n" n
5005              | OptString n -> pr "  str *%s;\n" n
5006              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5007              | Bool n -> pr "  bool %s;\n" n
5008              | Int n -> pr "  int %s;\n" n
5009              | Int64 n -> pr "  hyper %s;\n" n
5010              | FileIn _ | FileOut _ -> ()
5011            ) args;
5012            pr "};\n\n"
5013       );
5014       (match fst style with
5015        | RErr -> ()
5016        | RInt n ->
5017            pr "struct %s_ret {\n" name;
5018            pr "  int %s;\n" n;
5019            pr "};\n\n"
5020        | RInt64 n ->
5021            pr "struct %s_ret {\n" name;
5022            pr "  hyper %s;\n" n;
5023            pr "};\n\n"
5024        | RBool n ->
5025            pr "struct %s_ret {\n" name;
5026            pr "  bool %s;\n" n;
5027            pr "};\n\n"
5028        | RConstString _ | RConstOptString _ ->
5029            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5030        | RString n ->
5031            pr "struct %s_ret {\n" name;
5032            pr "  string %s<>;\n" n;
5033            pr "};\n\n"
5034        | RStringList n ->
5035            pr "struct %s_ret {\n" name;
5036            pr "  str %s<>;\n" n;
5037            pr "};\n\n"
5038        | RStruct (n, typ) ->
5039            pr "struct %s_ret {\n" name;
5040            pr "  guestfs_int_%s %s;\n" typ n;
5041            pr "};\n\n"
5042        | RStructList (n, typ) ->
5043            pr "struct %s_ret {\n" name;
5044            pr "  guestfs_int_%s_list %s;\n" typ n;
5045            pr "};\n\n"
5046        | RHashtable n ->
5047            pr "struct %s_ret {\n" name;
5048            pr "  str %s<>;\n" n;
5049            pr "};\n\n"
5050        | RBufferOut n ->
5051            pr "struct %s_ret {\n" name;
5052            pr "  opaque %s<>;\n" n;
5053            pr "};\n\n"
5054       );
5055   ) daemon_functions;
5056
5057   (* Table of procedure numbers. *)
5058   pr "enum guestfs_procedure {\n";
5059   List.iter (
5060     fun (shortname, _, proc_nr, _, _, _, _) ->
5061       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5062   ) daemon_functions;
5063   pr "  GUESTFS_PROC_NR_PROCS\n";
5064   pr "};\n";
5065   pr "\n";
5066
5067   (* Having to choose a maximum message size is annoying for several
5068    * reasons (it limits what we can do in the API), but it (a) makes
5069    * the protocol a lot simpler, and (b) provides a bound on the size
5070    * of the daemon which operates in limited memory space.  For large
5071    * file transfers you should use FTP.
5072    *)
5073   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5074   pr "\n";
5075
5076   (* Message header, etc. *)
5077   pr "\
5078 /* The communication protocol is now documented in the guestfs(3)
5079  * manpage.
5080  */
5081
5082 const GUESTFS_PROGRAM = 0x2000F5F5;
5083 const GUESTFS_PROTOCOL_VERSION = 1;
5084
5085 /* These constants must be larger than any possible message length. */
5086 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5087 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5088
5089 enum guestfs_message_direction {
5090   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5091   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5092 };
5093
5094 enum guestfs_message_status {
5095   GUESTFS_STATUS_OK = 0,
5096   GUESTFS_STATUS_ERROR = 1
5097 };
5098
5099 const GUESTFS_ERROR_LEN = 256;
5100
5101 struct guestfs_message_error {
5102   string error_message<GUESTFS_ERROR_LEN>;
5103 };
5104
5105 struct guestfs_message_header {
5106   unsigned prog;                     /* GUESTFS_PROGRAM */
5107   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5108   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5109   guestfs_message_direction direction;
5110   unsigned serial;                   /* message serial number */
5111   guestfs_message_status status;
5112 };
5113
5114 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5115
5116 struct guestfs_chunk {
5117   int cancel;                        /* if non-zero, transfer is cancelled */
5118   /* data size is 0 bytes if the transfer has finished successfully */
5119   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5120 };
5121 "
5122
5123 (* Generate the guestfs-structs.h file. *)
5124 and generate_structs_h () =
5125   generate_header CStyle LGPLv2;
5126
5127   (* This is a public exported header file containing various
5128    * structures.  The structures are carefully written to have
5129    * exactly the same in-memory format as the XDR structures that
5130    * we use on the wire to the daemon.  The reason for creating
5131    * copies of these structures here is just so we don't have to
5132    * export the whole of guestfs_protocol.h (which includes much
5133    * unrelated and XDR-dependent stuff that we don't want to be
5134    * public, or required by clients).
5135    *
5136    * To reiterate, we will pass these structures to and from the
5137    * client with a simple assignment or memcpy, so the format
5138    * must be identical to what rpcgen / the RFC defines.
5139    *)
5140
5141   (* Public structures. *)
5142   List.iter (
5143     fun (typ, cols) ->
5144       pr "struct guestfs_%s {\n" typ;
5145       List.iter (
5146         function
5147         | name, FChar -> pr "  char %s;\n" name
5148         | name, FString -> pr "  char *%s;\n" name
5149         | name, FBuffer ->
5150             pr "  uint32_t %s_len;\n" name;
5151             pr "  char *%s;\n" name
5152         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5153         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5154         | name, FInt32 -> pr "  int32_t %s;\n" name
5155         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5156         | name, FInt64 -> pr "  int64_t %s;\n" name
5157         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5158       ) cols;
5159       pr "};\n";
5160       pr "\n";
5161       pr "struct guestfs_%s_list {\n" typ;
5162       pr "  uint32_t len;\n";
5163       pr "  struct guestfs_%s *val;\n" typ;
5164       pr "};\n";
5165       pr "\n";
5166       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5167       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5168       pr "\n"
5169   ) structs
5170
5171 (* Generate the guestfs-actions.h file. *)
5172 and generate_actions_h () =
5173   generate_header CStyle LGPLv2;
5174   List.iter (
5175     fun (shortname, style, _, _, _, _, _) ->
5176       let name = "guestfs_" ^ shortname in
5177       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5178         name style
5179   ) all_functions
5180
5181 (* Generate the guestfs-internal-actions.h file. *)
5182 and generate_internal_actions_h () =
5183   generate_header CStyle LGPLv2;
5184   List.iter (
5185     fun (shortname, style, _, _, _, _, _) ->
5186       let name = "guestfs__" ^ shortname in
5187       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5188         name style
5189   ) non_daemon_functions
5190
5191 (* Generate the client-side dispatch stubs. *)
5192 and generate_client_actions () =
5193   generate_header CStyle LGPLv2;
5194
5195   pr "\
5196 #include <stdio.h>
5197 #include <stdlib.h>
5198 #include <stdint.h>
5199 #include <inttypes.h>
5200
5201 #include \"guestfs.h\"
5202 #include \"guestfs-internal.h\"
5203 #include \"guestfs-internal-actions.h\"
5204 #include \"guestfs_protocol.h\"
5205
5206 #define error guestfs_error
5207 //#define perrorf guestfs_perrorf
5208 #define safe_malloc guestfs_safe_malloc
5209 #define safe_realloc guestfs_safe_realloc
5210 //#define safe_strdup guestfs_safe_strdup
5211 #define safe_memdup guestfs_safe_memdup
5212
5213 /* Check the return message from a call for validity. */
5214 static int
5215 check_reply_header (guestfs_h *g,
5216                     const struct guestfs_message_header *hdr,
5217                     unsigned int proc_nr, unsigned int serial)
5218 {
5219   if (hdr->prog != GUESTFS_PROGRAM) {
5220     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5221     return -1;
5222   }
5223   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5224     error (g, \"wrong protocol version (%%d/%%d)\",
5225            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5226     return -1;
5227   }
5228   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5229     error (g, \"unexpected message direction (%%d/%%d)\",
5230            hdr->direction, GUESTFS_DIRECTION_REPLY);
5231     return -1;
5232   }
5233   if (hdr->proc != proc_nr) {
5234     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5235     return -1;
5236   }
5237   if (hdr->serial != serial) {
5238     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5239     return -1;
5240   }
5241
5242   return 0;
5243 }
5244
5245 /* Check we are in the right state to run a high-level action. */
5246 static int
5247 check_state (guestfs_h *g, const char *caller)
5248 {
5249   if (!guestfs__is_ready (g)) {
5250     if (guestfs__is_config (g) || guestfs__is_launching (g))
5251       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5252         caller);
5253     else
5254       error (g, \"%%s called from the wrong state, %%d != READY\",
5255         caller, guestfs__get_state (g));
5256     return -1;
5257   }
5258   return 0;
5259 }
5260
5261 ";
5262
5263   (* Generate code to generate guestfish call traces. *)
5264   let trace_call shortname style =
5265     pr "  if (guestfs__get_trace (g)) {\n";
5266
5267     let needs_i =
5268       List.exists (function
5269                    | StringList _ | DeviceList _ -> true
5270                    | _ -> false) (snd style) in
5271     if needs_i then (
5272       pr "    int i;\n";
5273       pr "\n"
5274     );
5275
5276     pr "    printf (\"%s\");\n" shortname;
5277     List.iter (
5278       function
5279       | String n                        (* strings *)
5280       | Device n
5281       | Pathname n
5282       | Dev_or_Path n
5283       | FileIn n
5284       | FileOut n ->
5285           (* guestfish doesn't support string escaping, so neither do we *)
5286           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5287       | OptString n ->                  (* string option *)
5288           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5289           pr "    else printf (\" null\");\n"
5290       | StringList n
5291       | DeviceList n ->                 (* string list *)
5292           pr "    putchar (' ');\n";
5293           pr "    putchar ('\"');\n";
5294           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5295           pr "      if (i > 0) putchar (' ');\n";
5296           pr "      fputs (%s[i], stdout);\n" n;
5297           pr "    }\n";
5298           pr "    putchar ('\"');\n";
5299       | Bool n ->                       (* boolean *)
5300           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5301       | Int n ->                        (* int *)
5302           pr "    printf (\" %%d\", %s);\n" n
5303       | Int64 n ->
5304           pr "    printf (\" %%\" PRIi64, %s);\n" n
5305     ) (snd style);
5306     pr "    putchar ('\\n');\n";
5307     pr "  }\n";
5308     pr "\n";
5309   in
5310
5311   (* For non-daemon functions, generate a wrapper around each function. *)
5312   List.iter (
5313     fun (shortname, style, _, _, _, _, _) ->
5314       let name = "guestfs_" ^ shortname in
5315
5316       generate_prototype ~extern:false ~semicolon:false ~newline:true
5317         ~handle:"g" name style;
5318       pr "{\n";
5319       trace_call shortname style;
5320       pr "  return guestfs__%s " shortname;
5321       generate_c_call_args ~handle:"g" style;
5322       pr ";\n";
5323       pr "}\n";
5324       pr "\n"
5325   ) non_daemon_functions;
5326
5327   (* Client-side stubs for each function. *)
5328   List.iter (
5329     fun (shortname, style, _, _, _, _, _) ->
5330       let name = "guestfs_" ^ shortname in
5331
5332       (* Generate the action stub. *)
5333       generate_prototype ~extern:false ~semicolon:false ~newline:true
5334         ~handle:"g" name style;
5335
5336       let error_code =
5337         match fst style with
5338         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5339         | RConstString _ | RConstOptString _ ->
5340             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5341         | RString _ | RStringList _
5342         | RStruct _ | RStructList _
5343         | RHashtable _ | RBufferOut _ ->
5344             "NULL" in
5345
5346       pr "{\n";
5347
5348       (match snd style with
5349        | [] -> ()
5350        | _ -> pr "  struct %s_args args;\n" name
5351       );
5352
5353       pr "  guestfs_message_header hdr;\n";
5354       pr "  guestfs_message_error err;\n";
5355       let has_ret =
5356         match fst style with
5357         | RErr -> false
5358         | RConstString _ | RConstOptString _ ->
5359             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5360         | RInt _ | RInt64 _
5361         | RBool _ | RString _ | RStringList _
5362         | RStruct _ | RStructList _
5363         | RHashtable _ | RBufferOut _ ->
5364             pr "  struct %s_ret ret;\n" name;
5365             true in
5366
5367       pr "  int serial;\n";
5368       pr "  int r;\n";
5369       pr "\n";
5370       trace_call shortname style;
5371       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5372       pr "  guestfs___set_busy (g);\n";
5373       pr "\n";
5374
5375       (* Send the main header and arguments. *)
5376       (match snd style with
5377        | [] ->
5378            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5379              (String.uppercase shortname)
5380        | args ->
5381            List.iter (
5382              function
5383              | Pathname n | Device n | Dev_or_Path n | String n ->
5384                  pr "  args.%s = (char *) %s;\n" n n
5385              | OptString n ->
5386                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5387              | StringList n | DeviceList n ->
5388                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5389                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5390              | Bool n ->
5391                  pr "  args.%s = %s;\n" n n
5392              | Int n ->
5393                  pr "  args.%s = %s;\n" n n
5394              | Int64 n ->
5395                  pr "  args.%s = %s;\n" n n
5396              | FileIn _ | FileOut _ -> ()
5397            ) args;
5398            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5399              (String.uppercase shortname);
5400            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5401              name;
5402       );
5403       pr "  if (serial == -1) {\n";
5404       pr "    guestfs___end_busy (g);\n";
5405       pr "    return %s;\n" error_code;
5406       pr "  }\n";
5407       pr "\n";
5408
5409       (* Send any additional files (FileIn) requested. *)
5410       let need_read_reply_label = ref false in
5411       List.iter (
5412         function
5413         | FileIn n ->
5414             pr "  r = guestfs___send_file (g, %s);\n" n;
5415             pr "  if (r == -1) {\n";
5416             pr "    guestfs___end_busy (g);\n";
5417             pr "    return %s;\n" error_code;
5418             pr "  }\n";
5419             pr "  if (r == -2) /* daemon cancelled */\n";
5420             pr "    goto read_reply;\n";
5421             need_read_reply_label := true;
5422             pr "\n";
5423         | _ -> ()
5424       ) (snd style);
5425
5426       (* Wait for the reply from the remote end. *)
5427       if !need_read_reply_label then pr " read_reply:\n";
5428       pr "  memset (&hdr, 0, sizeof hdr);\n";
5429       pr "  memset (&err, 0, sizeof err);\n";
5430       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5431       pr "\n";
5432       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5433       if not has_ret then
5434         pr "NULL, NULL"
5435       else
5436         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5437       pr ");\n";
5438
5439       pr "  if (r == -1) {\n";
5440       pr "    guestfs___end_busy (g);\n";
5441       pr "    return %s;\n" error_code;
5442       pr "  }\n";
5443       pr "\n";
5444
5445       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5446         (String.uppercase shortname);
5447       pr "    guestfs___end_busy (g);\n";
5448       pr "    return %s;\n" error_code;
5449       pr "  }\n";
5450       pr "\n";
5451
5452       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5453       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5454       pr "    free (err.error_message);\n";
5455       pr "    guestfs___end_busy (g);\n";
5456       pr "    return %s;\n" error_code;
5457       pr "  }\n";
5458       pr "\n";
5459
5460       (* Expecting to receive further files (FileOut)? *)
5461       List.iter (
5462         function
5463         | FileOut n ->
5464             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5465             pr "    guestfs___end_busy (g);\n";
5466             pr "    return %s;\n" error_code;
5467             pr "  }\n";
5468             pr "\n";
5469         | _ -> ()
5470       ) (snd style);
5471
5472       pr "  guestfs___end_busy (g);\n";
5473
5474       (match fst style with
5475        | RErr -> pr "  return 0;\n"
5476        | RInt n | RInt64 n | RBool n ->
5477            pr "  return ret.%s;\n" n
5478        | RConstString _ | RConstOptString _ ->
5479            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5480        | RString n ->
5481            pr "  return ret.%s; /* caller will free */\n" n
5482        | RStringList n | RHashtable n ->
5483            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5484            pr "  ret.%s.%s_val =\n" n n;
5485            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5486            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5487              n n;
5488            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5489            pr "  return ret.%s.%s_val;\n" n n
5490        | RStruct (n, _) ->
5491            pr "  /* caller will free this */\n";
5492            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5493        | RStructList (n, _) ->
5494            pr "  /* caller will free this */\n";
5495            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5496        | RBufferOut n ->
5497            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5498            pr "   * _val might be NULL here.  To make the API saner for\n";
5499            pr "   * callers, we turn this case into a unique pointer (using\n";
5500            pr "   * malloc(1)).\n";
5501            pr "   */\n";
5502            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5503            pr "    *size_r = ret.%s.%s_len;\n" n n;
5504            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5505            pr "  } else {\n";
5506            pr "    free (ret.%s.%s_val);\n" n n;
5507            pr "    char *p = safe_malloc (g, 1);\n";
5508            pr "    *size_r = ret.%s.%s_len;\n" n n;
5509            pr "    return p;\n";
5510            pr "  }\n";
5511       );
5512
5513       pr "}\n\n"
5514   ) daemon_functions;
5515
5516   (* Functions to free structures. *)
5517   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5518   pr " * structure format is identical to the XDR format.  See note in\n";
5519   pr " * generator.ml.\n";
5520   pr " */\n";
5521   pr "\n";
5522
5523   List.iter (
5524     fun (typ, _) ->
5525       pr "void\n";
5526       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5527       pr "{\n";
5528       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5529       pr "  free (x);\n";
5530       pr "}\n";
5531       pr "\n";
5532
5533       pr "void\n";
5534       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5535       pr "{\n";
5536       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5537       pr "  free (x);\n";
5538       pr "}\n";
5539       pr "\n";
5540
5541   ) structs;
5542
5543 (* Generate daemon/actions.h. *)
5544 and generate_daemon_actions_h () =
5545   generate_header CStyle GPLv2;
5546
5547   pr "#include \"../src/guestfs_protocol.h\"\n";
5548   pr "\n";
5549
5550   List.iter (
5551     fun (name, style, _, _, _, _, _) ->
5552       generate_prototype
5553         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5554         name style;
5555   ) daemon_functions
5556
5557 (* Generate the server-side stubs. *)
5558 and generate_daemon_actions () =
5559   generate_header CStyle GPLv2;
5560
5561   pr "#include <config.h>\n";
5562   pr "\n";
5563   pr "#include <stdio.h>\n";
5564   pr "#include <stdlib.h>\n";
5565   pr "#include <string.h>\n";
5566   pr "#include <inttypes.h>\n";
5567   pr "#include <rpc/types.h>\n";
5568   pr "#include <rpc/xdr.h>\n";
5569   pr "\n";
5570   pr "#include \"daemon.h\"\n";
5571   pr "#include \"c-ctype.h\"\n";
5572   pr "#include \"../src/guestfs_protocol.h\"\n";
5573   pr "#include \"actions.h\"\n";
5574   pr "\n";
5575
5576   List.iter (
5577     fun (name, style, _, _, _, _, _) ->
5578       (* Generate server-side stubs. *)
5579       pr "static void %s_stub (XDR *xdr_in)\n" name;
5580       pr "{\n";
5581       let error_code =
5582         match fst style with
5583         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5584         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5585         | RBool _ -> pr "  int r;\n"; "-1"
5586         | RConstString _ | RConstOptString _ ->
5587             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5588         | RString _ -> pr "  char *r;\n"; "NULL"
5589         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5590         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5591         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5592         | RBufferOut _ ->
5593             pr "  size_t size = 1;\n";
5594             pr "  char *r;\n";
5595             "NULL" in
5596
5597       (match snd style with
5598        | [] -> ()
5599        | args ->
5600            pr "  struct guestfs_%s_args args;\n" name;
5601            List.iter (
5602              function
5603              | Device n | Dev_or_Path n
5604              | Pathname n
5605              | String n -> ()
5606              | OptString n -> pr "  char *%s;\n" n
5607              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5608              | Bool n -> pr "  int %s;\n" n
5609              | Int n -> pr "  int %s;\n" n
5610              | Int64 n -> pr "  int64_t %s;\n" n
5611              | FileIn _ | FileOut _ -> ()
5612            ) args
5613       );
5614       pr "\n";
5615
5616       (match snd style with
5617        | [] -> ()
5618        | args ->
5619            pr "  memset (&args, 0, sizeof args);\n";
5620            pr "\n";
5621            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5622            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5623            pr "    return;\n";
5624            pr "  }\n";
5625            let pr_args n =
5626              pr "  char *%s = args.%s;\n" n n
5627            in
5628            let pr_list_handling_code n =
5629              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5630              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5631              pr "  if (%s == NULL) {\n" n;
5632              pr "    reply_with_perror (\"realloc\");\n";
5633              pr "    goto done;\n";
5634              pr "  }\n";
5635              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5636              pr "  args.%s.%s_val = %s;\n" n n n;
5637            in
5638            List.iter (
5639              function
5640              | Pathname n ->
5641                  pr_args n;
5642                  pr "  ABS_PATH (%s, goto done);\n" n;
5643              | Device n ->
5644                  pr_args n;
5645                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5646              | Dev_or_Path n ->
5647                  pr_args n;
5648                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5649              | String n -> pr_args n
5650              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5651              | StringList n ->
5652                  pr_list_handling_code n;
5653              | DeviceList n ->
5654                  pr_list_handling_code n;
5655                  pr "  /* Ensure that each is a device,\n";
5656                  pr "   * and perform device name translation. */\n";
5657                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5658                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5659                  pr "  }\n";
5660              | Bool n -> pr "  %s = args.%s;\n" n n
5661              | Int n -> pr "  %s = args.%s;\n" n n
5662              | Int64 n -> pr "  %s = args.%s;\n" n n
5663              | FileIn _ | FileOut _ -> ()
5664            ) args;
5665            pr "\n"
5666       );
5667
5668
5669       (* this is used at least for do_equal *)
5670       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5671         (* Emit NEED_ROOT just once, even when there are two or
5672            more Pathname args *)
5673         pr "  NEED_ROOT (goto done);\n";
5674       );
5675
5676       (* Don't want to call the impl with any FileIn or FileOut
5677        * parameters, since these go "outside" the RPC protocol.
5678        *)
5679       let args' =
5680         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5681           (snd style) in
5682       pr "  r = do_%s " name;
5683       generate_c_call_args (fst style, args');
5684       pr ";\n";
5685
5686       (match fst style with
5687        | RErr | RInt _ | RInt64 _ | RBool _
5688        | RConstString _ | RConstOptString _
5689        | RString _ | RStringList _ | RHashtable _
5690        | RStruct (_, _) | RStructList (_, _) ->
5691            pr "  if (r == %s)\n" error_code;
5692            pr "    /* do_%s has already called reply_with_error */\n" name;
5693            pr "    goto done;\n";
5694            pr "\n"
5695        | RBufferOut _ ->
5696            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5697            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5698            pr "   */\n";
5699            pr "  if (size == 1 && r == %s)\n" error_code;
5700            pr "    /* do_%s has already called reply_with_error */\n" name;
5701            pr "    goto done;\n";
5702            pr "\n"
5703       );
5704
5705       (* If there are any FileOut parameters, then the impl must
5706        * send its own reply.
5707        *)
5708       let no_reply =
5709         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5710       if no_reply then
5711         pr "  /* do_%s has already sent a reply */\n" name
5712       else (
5713         match fst style with
5714         | RErr -> pr "  reply (NULL, NULL);\n"
5715         | RInt n | RInt64 n | RBool n ->
5716             pr "  struct guestfs_%s_ret ret;\n" name;
5717             pr "  ret.%s = r;\n" n;
5718             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5719               name
5720         | RConstString _ | RConstOptString _ ->
5721             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5722         | RString n ->
5723             pr "  struct guestfs_%s_ret ret;\n" name;
5724             pr "  ret.%s = r;\n" n;
5725             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5726               name;
5727             pr "  free (r);\n"
5728         | RStringList n | RHashtable n ->
5729             pr "  struct guestfs_%s_ret ret;\n" name;
5730             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5731             pr "  ret.%s.%s_val = r;\n" n n;
5732             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5733               name;
5734             pr "  free_strings (r);\n"
5735         | RStruct (n, _) ->
5736             pr "  struct guestfs_%s_ret ret;\n" name;
5737             pr "  ret.%s = *r;\n" n;
5738             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5739               name;
5740             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5741               name
5742         | RStructList (n, _) ->
5743             pr "  struct guestfs_%s_ret ret;\n" name;
5744             pr "  ret.%s = *r;\n" n;
5745             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5746               name;
5747             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5748               name
5749         | RBufferOut n ->
5750             pr "  struct guestfs_%s_ret ret;\n" name;
5751             pr "  ret.%s.%s_val = r;\n" n n;
5752             pr "  ret.%s.%s_len = size;\n" n n;
5753             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5754               name;
5755             pr "  free (r);\n"
5756       );
5757
5758       (* Free the args. *)
5759       (match snd style with
5760        | [] ->
5761            pr "done: ;\n";
5762        | _ ->
5763            pr "done:\n";
5764            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5765              name
5766       );
5767
5768       pr "}\n\n";
5769   ) daemon_functions;
5770
5771   (* Dispatch function. *)
5772   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5773   pr "{\n";
5774   pr "  switch (proc_nr) {\n";
5775
5776   List.iter (
5777     fun (name, style, _, _, _, _, _) ->
5778       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5779       pr "      %s_stub (xdr_in);\n" name;
5780       pr "      break;\n"
5781   ) daemon_functions;
5782
5783   pr "    default:\n";
5784   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";
5785   pr "  }\n";
5786   pr "}\n";
5787   pr "\n";
5788
5789   (* LVM columns and tokenization functions. *)
5790   (* XXX This generates crap code.  We should rethink how we
5791    * do this parsing.
5792    *)
5793   List.iter (
5794     function
5795     | typ, cols ->
5796         pr "static const char *lvm_%s_cols = \"%s\";\n"
5797           typ (String.concat "," (List.map fst cols));
5798         pr "\n";
5799
5800         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5801         pr "{\n";
5802         pr "  char *tok, *p, *next;\n";
5803         pr "  int i, j;\n";
5804         pr "\n";
5805         (*
5806           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5807           pr "\n";
5808         *)
5809         pr "  if (!str) {\n";
5810         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5811         pr "    return -1;\n";
5812         pr "  }\n";
5813         pr "  if (!*str || c_isspace (*str)) {\n";
5814         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5815         pr "    return -1;\n";
5816         pr "  }\n";
5817         pr "  tok = str;\n";
5818         List.iter (
5819           fun (name, coltype) ->
5820             pr "  if (!tok) {\n";
5821             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5822             pr "    return -1;\n";
5823             pr "  }\n";
5824             pr "  p = strchrnul (tok, ',');\n";
5825             pr "  if (*p) next = p+1; else next = NULL;\n";
5826             pr "  *p = '\\0';\n";
5827             (match coltype with
5828              | FString ->
5829                  pr "  r->%s = strdup (tok);\n" name;
5830                  pr "  if (r->%s == NULL) {\n" name;
5831                  pr "    perror (\"strdup\");\n";
5832                  pr "    return -1;\n";
5833                  pr "  }\n"
5834              | FUUID ->
5835                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5836                  pr "    if (tok[j] == '\\0') {\n";
5837                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5838                  pr "      return -1;\n";
5839                  pr "    } else if (tok[j] != '-')\n";
5840                  pr "      r->%s[i++] = tok[j];\n" name;
5841                  pr "  }\n";
5842              | FBytes ->
5843                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5844                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5845                  pr "    return -1;\n";
5846                  pr "  }\n";
5847              | FInt64 ->
5848                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5849                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5850                  pr "    return -1;\n";
5851                  pr "  }\n";
5852              | FOptPercent ->
5853                  pr "  if (tok[0] == '\\0')\n";
5854                  pr "    r->%s = -1;\n" name;
5855                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5856                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5857                  pr "    return -1;\n";
5858                  pr "  }\n";
5859              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5860                  assert false (* can never be an LVM column *)
5861             );
5862             pr "  tok = next;\n";
5863         ) cols;
5864
5865         pr "  if (tok != NULL) {\n";
5866         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5867         pr "    return -1;\n";
5868         pr "  }\n";
5869         pr "  return 0;\n";
5870         pr "}\n";
5871         pr "\n";
5872
5873         pr "guestfs_int_lvm_%s_list *\n" typ;
5874         pr "parse_command_line_%ss (void)\n" typ;
5875         pr "{\n";
5876         pr "  char *out, *err;\n";
5877         pr "  char *p, *pend;\n";
5878         pr "  int r, i;\n";
5879         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5880         pr "  void *newp;\n";
5881         pr "\n";
5882         pr "  ret = malloc (sizeof *ret);\n";
5883         pr "  if (!ret) {\n";
5884         pr "    reply_with_perror (\"malloc\");\n";
5885         pr "    return NULL;\n";
5886         pr "  }\n";
5887         pr "\n";
5888         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5889         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5890         pr "\n";
5891         pr "  r = command (&out, &err,\n";
5892         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5893         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5894         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5895         pr "  if (r == -1) {\n";
5896         pr "    reply_with_error (\"%%s\", err);\n";
5897         pr "    free (out);\n";
5898         pr "    free (err);\n";
5899         pr "    free (ret);\n";
5900         pr "    return NULL;\n";
5901         pr "  }\n";
5902         pr "\n";
5903         pr "  free (err);\n";
5904         pr "\n";
5905         pr "  /* Tokenize each line of the output. */\n";
5906         pr "  p = out;\n";
5907         pr "  i = 0;\n";
5908         pr "  while (p) {\n";
5909         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5910         pr "    if (pend) {\n";
5911         pr "      *pend = '\\0';\n";
5912         pr "      pend++;\n";
5913         pr "    }\n";
5914         pr "\n";
5915         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5916         pr "      p++;\n";
5917         pr "\n";
5918         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5919         pr "      p = pend;\n";
5920         pr "      continue;\n";
5921         pr "    }\n";
5922         pr "\n";
5923         pr "    /* Allocate some space to store this next entry. */\n";
5924         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5925         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5926         pr "    if (newp == NULL) {\n";
5927         pr "      reply_with_perror (\"realloc\");\n";
5928         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5929         pr "      free (ret);\n";
5930         pr "      free (out);\n";
5931         pr "      return NULL;\n";
5932         pr "    }\n";
5933         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5934         pr "\n";
5935         pr "    /* Tokenize the next entry. */\n";
5936         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5937         pr "    if (r == -1) {\n";
5938         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5939         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5940         pr "      free (ret);\n";
5941         pr "      free (out);\n";
5942         pr "      return NULL;\n";
5943         pr "    }\n";
5944         pr "\n";
5945         pr "    ++i;\n";
5946         pr "    p = pend;\n";
5947         pr "  }\n";
5948         pr "\n";
5949         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5950         pr "\n";
5951         pr "  free (out);\n";
5952         pr "  return ret;\n";
5953         pr "}\n"
5954
5955   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5956
5957 (* Generate a list of function names, for debugging in the daemon.. *)
5958 and generate_daemon_names () =
5959   generate_header CStyle GPLv2;
5960
5961   pr "#include <config.h>\n";
5962   pr "\n";
5963   pr "#include \"daemon.h\"\n";
5964   pr "\n";
5965
5966   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5967   pr "const char *function_names[] = {\n";
5968   List.iter (
5969     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5970   ) daemon_functions;
5971   pr "};\n";
5972
5973 (* Generate the optional groups for the daemon to implement
5974  * guestfs_available.
5975  *)
5976 and generate_daemon_optgroups_c () =
5977   generate_header CStyle GPLv2;
5978
5979   pr "#include <config.h>\n";
5980   pr "\n";
5981   pr "#include \"daemon.h\"\n";
5982   pr "#include \"optgroups.h\"\n";
5983   pr "\n";
5984
5985   pr "struct optgroup optgroups[] = {\n";
5986   List.iter (
5987     fun (group, _) ->
5988       pr "  { \"%s\", optgroup_%s_available },\n" group group
5989   ) optgroups;
5990   pr "  { NULL, NULL }\n";
5991   pr "};\n"
5992
5993 and generate_daemon_optgroups_h () =
5994   generate_header CStyle GPLv2;
5995
5996   List.iter (
5997     fun (group, _) ->
5998       pr "extern int optgroup_%s_available (void);\n" group
5999   ) optgroups
6000
6001 (* Generate the tests. *)
6002 and generate_tests () =
6003   generate_header CStyle GPLv2;
6004
6005   pr "\
6006 #include <stdio.h>
6007 #include <stdlib.h>
6008 #include <string.h>
6009 #include <unistd.h>
6010 #include <sys/types.h>
6011 #include <fcntl.h>
6012
6013 #include \"guestfs.h\"
6014 #include \"guestfs-internal.h\"
6015
6016 static guestfs_h *g;
6017 static int suppress_error = 0;
6018
6019 static void print_error (guestfs_h *g, void *data, const char *msg)
6020 {
6021   if (!suppress_error)
6022     fprintf (stderr, \"%%s\\n\", msg);
6023 }
6024
6025 /* FIXME: nearly identical code appears in fish.c */
6026 static void print_strings (char *const *argv)
6027 {
6028   int argc;
6029
6030   for (argc = 0; argv[argc] != NULL; ++argc)
6031     printf (\"\\t%%s\\n\", argv[argc]);
6032 }
6033
6034 /*
6035 static void print_table (char const *const *argv)
6036 {
6037   int i;
6038
6039   for (i = 0; argv[i] != NULL; i += 2)
6040     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6041 }
6042 */
6043
6044 ";
6045
6046   (* Generate a list of commands which are not tested anywhere. *)
6047   pr "static void no_test_warnings (void)\n";
6048   pr "{\n";
6049
6050   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6051   List.iter (
6052     fun (_, _, _, _, tests, _, _) ->
6053       let tests = filter_map (
6054         function
6055         | (_, (Always|If _|Unless _), test) -> Some test
6056         | (_, Disabled, _) -> None
6057       ) tests in
6058       let seq = List.concat (List.map seq_of_test tests) in
6059       let cmds_tested = List.map List.hd seq in
6060       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6061   ) all_functions;
6062
6063   List.iter (
6064     fun (name, _, _, _, _, _, _) ->
6065       if not (Hashtbl.mem hash name) then
6066         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6067   ) all_functions;
6068
6069   pr "}\n";
6070   pr "\n";
6071
6072   (* Generate the actual tests.  Note that we generate the tests
6073    * in reverse order, deliberately, so that (in general) the
6074    * newest tests run first.  This makes it quicker and easier to
6075    * debug them.
6076    *)
6077   let test_names =
6078     List.map (
6079       fun (name, _, _, _, tests, _, _) ->
6080         mapi (generate_one_test name) tests
6081     ) (List.rev all_functions) in
6082   let test_names = List.concat test_names in
6083   let nr_tests = List.length test_names in
6084
6085   pr "\
6086 int main (int argc, char *argv[])
6087 {
6088   char c = 0;
6089   unsigned long int n_failed = 0;
6090   const char *filename;
6091   int fd;
6092   int nr_tests, test_num = 0;
6093
6094   setbuf (stdout, NULL);
6095
6096   no_test_warnings ();
6097
6098   g = guestfs_create ();
6099   if (g == NULL) {
6100     printf (\"guestfs_create FAILED\\n\");
6101     exit (EXIT_FAILURE);
6102   }
6103
6104   guestfs_set_error_handler (g, print_error, NULL);
6105
6106   guestfs_set_path (g, \"../appliance\");
6107
6108   filename = \"test1.img\";
6109   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6110   if (fd == -1) {
6111     perror (filename);
6112     exit (EXIT_FAILURE);
6113   }
6114   if (lseek (fd, %d, SEEK_SET) == -1) {
6115     perror (\"lseek\");
6116     close (fd);
6117     unlink (filename);
6118     exit (EXIT_FAILURE);
6119   }
6120   if (write (fd, &c, 1) == -1) {
6121     perror (\"write\");
6122     close (fd);
6123     unlink (filename);
6124     exit (EXIT_FAILURE);
6125   }
6126   if (close (fd) == -1) {
6127     perror (filename);
6128     unlink (filename);
6129     exit (EXIT_FAILURE);
6130   }
6131   if (guestfs_add_drive (g, filename) == -1) {
6132     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6133     exit (EXIT_FAILURE);
6134   }
6135
6136   filename = \"test2.img\";
6137   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6138   if (fd == -1) {
6139     perror (filename);
6140     exit (EXIT_FAILURE);
6141   }
6142   if (lseek (fd, %d, SEEK_SET) == -1) {
6143     perror (\"lseek\");
6144     close (fd);
6145     unlink (filename);
6146     exit (EXIT_FAILURE);
6147   }
6148   if (write (fd, &c, 1) == -1) {
6149     perror (\"write\");
6150     close (fd);
6151     unlink (filename);
6152     exit (EXIT_FAILURE);
6153   }
6154   if (close (fd) == -1) {
6155     perror (filename);
6156     unlink (filename);
6157     exit (EXIT_FAILURE);
6158   }
6159   if (guestfs_add_drive (g, filename) == -1) {
6160     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6161     exit (EXIT_FAILURE);
6162   }
6163
6164   filename = \"test3.img\";
6165   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6166   if (fd == -1) {
6167     perror (filename);
6168     exit (EXIT_FAILURE);
6169   }
6170   if (lseek (fd, %d, SEEK_SET) == -1) {
6171     perror (\"lseek\");
6172     close (fd);
6173     unlink (filename);
6174     exit (EXIT_FAILURE);
6175   }
6176   if (write (fd, &c, 1) == -1) {
6177     perror (\"write\");
6178     close (fd);
6179     unlink (filename);
6180     exit (EXIT_FAILURE);
6181   }
6182   if (close (fd) == -1) {
6183     perror (filename);
6184     unlink (filename);
6185     exit (EXIT_FAILURE);
6186   }
6187   if (guestfs_add_drive (g, filename) == -1) {
6188     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6189     exit (EXIT_FAILURE);
6190   }
6191
6192   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6193     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6194     exit (EXIT_FAILURE);
6195   }
6196
6197   if (guestfs_launch (g) == -1) {
6198     printf (\"guestfs_launch FAILED\\n\");
6199     exit (EXIT_FAILURE);
6200   }
6201
6202   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6203   alarm (600);
6204
6205   /* Cancel previous alarm. */
6206   alarm (0);
6207
6208   nr_tests = %d;
6209
6210 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6211
6212   iteri (
6213     fun i test_name ->
6214       pr "  test_num++;\n";
6215       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6216       pr "  if (%s () == -1) {\n" test_name;
6217       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6218       pr "    n_failed++;\n";
6219       pr "  }\n";
6220   ) test_names;
6221   pr "\n";
6222
6223   pr "  guestfs_close (g);\n";
6224   pr "  unlink (\"test1.img\");\n";
6225   pr "  unlink (\"test2.img\");\n";
6226   pr "  unlink (\"test3.img\");\n";
6227   pr "\n";
6228
6229   pr "  if (n_failed > 0) {\n";
6230   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6231   pr "    exit (EXIT_FAILURE);\n";
6232   pr "  }\n";
6233   pr "\n";
6234
6235   pr "  exit (EXIT_SUCCESS);\n";
6236   pr "}\n"
6237
6238 and generate_one_test name i (init, prereq, test) =
6239   let test_name = sprintf "test_%s_%d" name i in
6240
6241   pr "\
6242 static int %s_skip (void)
6243 {
6244   const char *str;
6245
6246   str = getenv (\"TEST_ONLY\");
6247   if (str)
6248     return strstr (str, \"%s\") == NULL;
6249   str = getenv (\"SKIP_%s\");
6250   if (str && STREQ (str, \"1\")) return 1;
6251   str = getenv (\"SKIP_TEST_%s\");
6252   if (str && STREQ (str, \"1\")) return 1;
6253   return 0;
6254 }
6255
6256 " test_name name (String.uppercase test_name) (String.uppercase name);
6257
6258   (match prereq with
6259    | Disabled | Always -> ()
6260    | If code | Unless code ->
6261        pr "static int %s_prereq (void)\n" test_name;
6262        pr "{\n";
6263        pr "  %s\n" code;
6264        pr "}\n";
6265        pr "\n";
6266   );
6267
6268   pr "\
6269 static int %s (void)
6270 {
6271   if (%s_skip ()) {
6272     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6273     return 0;
6274   }
6275
6276 " test_name test_name test_name;
6277
6278   (match prereq with
6279    | Disabled ->
6280        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6281    | If _ ->
6282        pr "  if (! %s_prereq ()) {\n" test_name;
6283        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6284        pr "    return 0;\n";
6285        pr "  }\n";
6286        pr "\n";
6287        generate_one_test_body name i test_name init test;
6288    | Unless _ ->
6289        pr "  if (%s_prereq ()) {\n" test_name;
6290        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6291        pr "    return 0;\n";
6292        pr "  }\n";
6293        pr "\n";
6294        generate_one_test_body name i test_name init test;
6295    | Always ->
6296        generate_one_test_body name i test_name init test
6297   );
6298
6299   pr "  return 0;\n";
6300   pr "}\n";
6301   pr "\n";
6302   test_name
6303
6304 and generate_one_test_body name i test_name init test =
6305   (match init with
6306    | InitNone (* XXX at some point, InitNone and InitEmpty became
6307                * folded together as the same thing.  Really we should
6308                * make InitNone do nothing at all, but the tests may
6309                * need to be checked to make sure this is OK.
6310                *)
6311    | InitEmpty ->
6312        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6313        List.iter (generate_test_command_call test_name)
6314          [["blockdev_setrw"; "/dev/sda"];
6315           ["umount_all"];
6316           ["lvm_remove_all"]]
6317    | InitPartition ->
6318        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6319        List.iter (generate_test_command_call test_name)
6320          [["blockdev_setrw"; "/dev/sda"];
6321           ["umount_all"];
6322           ["lvm_remove_all"];
6323           ["part_disk"; "/dev/sda"; "mbr"]]
6324    | InitBasicFS ->
6325        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6326        List.iter (generate_test_command_call test_name)
6327          [["blockdev_setrw"; "/dev/sda"];
6328           ["umount_all"];
6329           ["lvm_remove_all"];
6330           ["part_disk"; "/dev/sda"; "mbr"];
6331           ["mkfs"; "ext2"; "/dev/sda1"];
6332           ["mount"; "/dev/sda1"; "/"]]
6333    | InitBasicFSonLVM ->
6334        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6335          test_name;
6336        List.iter (generate_test_command_call test_name)
6337          [["blockdev_setrw"; "/dev/sda"];
6338           ["umount_all"];
6339           ["lvm_remove_all"];
6340           ["part_disk"; "/dev/sda"; "mbr"];
6341           ["pvcreate"; "/dev/sda1"];
6342           ["vgcreate"; "VG"; "/dev/sda1"];
6343           ["lvcreate"; "LV"; "VG"; "8"];
6344           ["mkfs"; "ext2"; "/dev/VG/LV"];
6345           ["mount"; "/dev/VG/LV"; "/"]]
6346    | InitISOFS ->
6347        pr "  /* InitISOFS for %s */\n" test_name;
6348        List.iter (generate_test_command_call test_name)
6349          [["blockdev_setrw"; "/dev/sda"];
6350           ["umount_all"];
6351           ["lvm_remove_all"];
6352           ["mount_ro"; "/dev/sdd"; "/"]]
6353   );
6354
6355   let get_seq_last = function
6356     | [] ->
6357         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6358           test_name
6359     | seq ->
6360         let seq = List.rev seq in
6361         List.rev (List.tl seq), List.hd seq
6362   in
6363
6364   match test with
6365   | TestRun seq ->
6366       pr "  /* TestRun for %s (%d) */\n" name i;
6367       List.iter (generate_test_command_call test_name) seq
6368   | TestOutput (seq, expected) ->
6369       pr "  /* TestOutput for %s (%d) */\n" name i;
6370       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6371       let seq, last = get_seq_last seq in
6372       let test () =
6373         pr "    if (STRNEQ (r, expected)) {\n";
6374         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6375         pr "      return -1;\n";
6376         pr "    }\n"
6377       in
6378       List.iter (generate_test_command_call test_name) seq;
6379       generate_test_command_call ~test test_name last
6380   | TestOutputList (seq, expected) ->
6381       pr "  /* TestOutputList for %s (%d) */\n" name i;
6382       let seq, last = get_seq_last seq in
6383       let test () =
6384         iteri (
6385           fun i str ->
6386             pr "    if (!r[%d]) {\n" i;
6387             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6388             pr "      print_strings (r);\n";
6389             pr "      return -1;\n";
6390             pr "    }\n";
6391             pr "    {\n";
6392             pr "      const char *expected = \"%s\";\n" (c_quote str);
6393             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6394             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6395             pr "        return -1;\n";
6396             pr "      }\n";
6397             pr "    }\n"
6398         ) expected;
6399         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6400         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6401           test_name;
6402         pr "      print_strings (r);\n";
6403         pr "      return -1;\n";
6404         pr "    }\n"
6405       in
6406       List.iter (generate_test_command_call test_name) seq;
6407       generate_test_command_call ~test test_name last
6408   | TestOutputListOfDevices (seq, expected) ->
6409       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6410       let seq, last = get_seq_last seq in
6411       let test () =
6412         iteri (
6413           fun i str ->
6414             pr "    if (!r[%d]) {\n" i;
6415             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6416             pr "      print_strings (r);\n";
6417             pr "      return -1;\n";
6418             pr "    }\n";
6419             pr "    {\n";
6420             pr "      const char *expected = \"%s\";\n" (c_quote str);
6421             pr "      r[%d][5] = 's';\n" i;
6422             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6423             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6424             pr "        return -1;\n";
6425             pr "      }\n";
6426             pr "    }\n"
6427         ) expected;
6428         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6429         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6430           test_name;
6431         pr "      print_strings (r);\n";
6432         pr "      return -1;\n";
6433         pr "    }\n"
6434       in
6435       List.iter (generate_test_command_call test_name) seq;
6436       generate_test_command_call ~test test_name last
6437   | TestOutputInt (seq, expected) ->
6438       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6439       let seq, last = get_seq_last seq in
6440       let test () =
6441         pr "    if (r != %d) {\n" expected;
6442         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6443           test_name expected;
6444         pr "               (int) r);\n";
6445         pr "      return -1;\n";
6446         pr "    }\n"
6447       in
6448       List.iter (generate_test_command_call test_name) seq;
6449       generate_test_command_call ~test test_name last
6450   | TestOutputIntOp (seq, op, expected) ->
6451       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6452       let seq, last = get_seq_last seq in
6453       let test () =
6454         pr "    if (! (r %s %d)) {\n" op expected;
6455         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6456           test_name op expected;
6457         pr "               (int) r);\n";
6458         pr "      return -1;\n";
6459         pr "    }\n"
6460       in
6461       List.iter (generate_test_command_call test_name) seq;
6462       generate_test_command_call ~test test_name last
6463   | TestOutputTrue seq ->
6464       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6465       let seq, last = get_seq_last seq in
6466       let test () =
6467         pr "    if (!r) {\n";
6468         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6469           test_name;
6470         pr "      return -1;\n";
6471         pr "    }\n"
6472       in
6473       List.iter (generate_test_command_call test_name) seq;
6474       generate_test_command_call ~test test_name last
6475   | TestOutputFalse seq ->
6476       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6477       let seq, last = get_seq_last seq in
6478       let test () =
6479         pr "    if (r) {\n";
6480         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6481           test_name;
6482         pr "      return -1;\n";
6483         pr "    }\n"
6484       in
6485       List.iter (generate_test_command_call test_name) seq;
6486       generate_test_command_call ~test test_name last
6487   | TestOutputLength (seq, expected) ->
6488       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6489       let seq, last = get_seq_last seq in
6490       let test () =
6491         pr "    int j;\n";
6492         pr "    for (j = 0; j < %d; ++j)\n" expected;
6493         pr "      if (r[j] == NULL) {\n";
6494         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6495           test_name;
6496         pr "        print_strings (r);\n";
6497         pr "        return -1;\n";
6498         pr "      }\n";
6499         pr "    if (r[j] != NULL) {\n";
6500         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6501           test_name;
6502         pr "      print_strings (r);\n";
6503         pr "      return -1;\n";
6504         pr "    }\n"
6505       in
6506       List.iter (generate_test_command_call test_name) seq;
6507       generate_test_command_call ~test test_name last
6508   | TestOutputBuffer (seq, expected) ->
6509       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6510       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6511       let seq, last = get_seq_last seq in
6512       let len = String.length expected in
6513       let test () =
6514         pr "    if (size != %d) {\n" len;
6515         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6516         pr "      return -1;\n";
6517         pr "    }\n";
6518         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6519         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6520         pr "      return -1;\n";
6521         pr "    }\n"
6522       in
6523       List.iter (generate_test_command_call test_name) seq;
6524       generate_test_command_call ~test test_name last
6525   | TestOutputStruct (seq, checks) ->
6526       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6527       let seq, last = get_seq_last seq in
6528       let test () =
6529         List.iter (
6530           function
6531           | CompareWithInt (field, expected) ->
6532               pr "    if (r->%s != %d) {\n" field expected;
6533               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6534                 test_name field expected;
6535               pr "               (int) r->%s);\n" field;
6536               pr "      return -1;\n";
6537               pr "    }\n"
6538           | CompareWithIntOp (field, op, expected) ->
6539               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6540               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6541                 test_name field op expected;
6542               pr "               (int) r->%s);\n" field;
6543               pr "      return -1;\n";
6544               pr "    }\n"
6545           | CompareWithString (field, expected) ->
6546               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6547               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6548                 test_name field expected;
6549               pr "               r->%s);\n" field;
6550               pr "      return -1;\n";
6551               pr "    }\n"
6552           | CompareFieldsIntEq (field1, field2) ->
6553               pr "    if (r->%s != r->%s) {\n" field1 field2;
6554               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6555                 test_name field1 field2;
6556               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6557               pr "      return -1;\n";
6558               pr "    }\n"
6559           | CompareFieldsStrEq (field1, field2) ->
6560               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6561               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6562                 test_name field1 field2;
6563               pr "               r->%s, r->%s);\n" field1 field2;
6564               pr "      return -1;\n";
6565               pr "    }\n"
6566         ) checks
6567       in
6568       List.iter (generate_test_command_call test_name) seq;
6569       generate_test_command_call ~test test_name last
6570   | TestLastFail seq ->
6571       pr "  /* TestLastFail for %s (%d) */\n" name i;
6572       let seq, last = get_seq_last seq in
6573       List.iter (generate_test_command_call test_name) seq;
6574       generate_test_command_call test_name ~expect_error:true last
6575
6576 (* Generate the code to run a command, leaving the result in 'r'.
6577  * If you expect to get an error then you should set expect_error:true.
6578  *)
6579 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6580   match cmd with
6581   | [] -> assert false
6582   | name :: args ->
6583       (* Look up the command to find out what args/ret it has. *)
6584       let style =
6585         try
6586           let _, style, _, _, _, _, _ =
6587             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6588           style
6589         with Not_found ->
6590           failwithf "%s: in test, command %s was not found" test_name name in
6591
6592       if List.length (snd style) <> List.length args then
6593         failwithf "%s: in test, wrong number of args given to %s"
6594           test_name name;
6595
6596       pr "  {\n";
6597
6598       List.iter (
6599         function
6600         | OptString n, "NULL" -> ()
6601         | Pathname n, arg
6602         | Device n, arg
6603         | Dev_or_Path n, arg
6604         | String n, arg
6605         | OptString n, arg ->
6606             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6607         | Int _, _
6608         | Int64 _, _
6609         | Bool _, _
6610         | FileIn _, _ | FileOut _, _ -> ()
6611         | StringList n, arg | DeviceList n, arg ->
6612             let strs = string_split " " arg in
6613             iteri (
6614               fun i str ->
6615                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6616             ) strs;
6617             pr "    const char *const %s[] = {\n" n;
6618             iteri (
6619               fun i _ -> pr "      %s_%d,\n" n i
6620             ) strs;
6621             pr "      NULL\n";
6622             pr "    };\n";
6623       ) (List.combine (snd style) args);
6624
6625       let error_code =
6626         match fst style with
6627         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6628         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6629         | RConstString _ | RConstOptString _ ->
6630             pr "    const char *r;\n"; "NULL"
6631         | RString _ -> pr "    char *r;\n"; "NULL"
6632         | RStringList _ | RHashtable _ ->
6633             pr "    char **r;\n";
6634             pr "    int i;\n";
6635             "NULL"
6636         | RStruct (_, typ) ->
6637             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6638         | RStructList (_, typ) ->
6639             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6640         | RBufferOut _ ->
6641             pr "    char *r;\n";
6642             pr "    size_t size;\n";
6643             "NULL" in
6644
6645       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6646       pr "    r = guestfs_%s (g" name;
6647
6648       (* Generate the parameters. *)
6649       List.iter (
6650         function
6651         | OptString _, "NULL" -> pr ", NULL"
6652         | Pathname n, _
6653         | Device n, _ | Dev_or_Path n, _
6654         | String n, _
6655         | OptString n, _ ->
6656             pr ", %s" n
6657         | FileIn _, arg | FileOut _, arg ->
6658             pr ", \"%s\"" (c_quote arg)
6659         | StringList n, _ | DeviceList n, _ ->
6660             pr ", (char **) %s" n
6661         | Int _, arg ->
6662             let i =
6663               try int_of_string arg
6664               with Failure "int_of_string" ->
6665                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6666             pr ", %d" i
6667         | Int64 _, arg ->
6668             let i =
6669               try Int64.of_string arg
6670               with Failure "int_of_string" ->
6671                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6672             pr ", %Ld" i
6673         | Bool _, arg ->
6674             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6675       ) (List.combine (snd style) args);
6676
6677       (match fst style with
6678        | RBufferOut _ -> pr ", &size"
6679        | _ -> ()
6680       );
6681
6682       pr ");\n";
6683
6684       if not expect_error then
6685         pr "    if (r == %s)\n" error_code
6686       else
6687         pr "    if (r != %s)\n" error_code;
6688       pr "      return -1;\n";
6689
6690       (* Insert the test code. *)
6691       (match test with
6692        | None -> ()
6693        | Some f -> f ()
6694       );
6695
6696       (match fst style with
6697        | RErr | RInt _ | RInt64 _ | RBool _
6698        | RConstString _ | RConstOptString _ -> ()
6699        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6700        | RStringList _ | RHashtable _ ->
6701            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6702            pr "      free (r[i]);\n";
6703            pr "    free (r);\n"
6704        | RStruct (_, typ) ->
6705            pr "    guestfs_free_%s (r);\n" typ
6706        | RStructList (_, typ) ->
6707            pr "    guestfs_free_%s_list (r);\n" typ
6708       );
6709
6710       pr "  }\n"
6711
6712 and c_quote str =
6713   let str = replace_str str "\r" "\\r" in
6714   let str = replace_str str "\n" "\\n" in
6715   let str = replace_str str "\t" "\\t" in
6716   let str = replace_str str "\000" "\\0" in
6717   str
6718
6719 (* Generate a lot of different functions for guestfish. *)
6720 and generate_fish_cmds () =
6721   generate_header CStyle GPLv2;
6722
6723   let all_functions =
6724     List.filter (
6725       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6726     ) all_functions in
6727   let all_functions_sorted =
6728     List.filter (
6729       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6730     ) all_functions_sorted in
6731
6732   pr "#include <stdio.h>\n";
6733   pr "#include <stdlib.h>\n";
6734   pr "#include <string.h>\n";
6735   pr "#include <inttypes.h>\n";
6736   pr "\n";
6737   pr "#include <guestfs.h>\n";
6738   pr "#include \"c-ctype.h\"\n";
6739   pr "#include \"fish.h\"\n";
6740   pr "\n";
6741
6742   (* list_commands function, which implements guestfish -h *)
6743   pr "void list_commands (void)\n";
6744   pr "{\n";
6745   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6746   pr "  list_builtin_commands ();\n";
6747   List.iter (
6748     fun (name, _, _, flags, _, shortdesc, _) ->
6749       let name = replace_char name '_' '-' in
6750       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6751         name shortdesc
6752   ) all_functions_sorted;
6753   pr "  printf (\"    %%s\\n\",";
6754   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6755   pr "}\n";
6756   pr "\n";
6757
6758   (* display_command function, which implements guestfish -h cmd *)
6759   pr "void display_command (const char *cmd)\n";
6760   pr "{\n";
6761   List.iter (
6762     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6763       let name2 = replace_char name '_' '-' in
6764       let alias =
6765         try find_map (function FishAlias n -> Some n | _ -> None) flags
6766         with Not_found -> name in
6767       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6768       let synopsis =
6769         match snd style with
6770         | [] -> name2
6771         | args ->
6772             sprintf "%s %s"
6773               name2 (String.concat " " (List.map name_of_argt args)) in
6774
6775       let warnings =
6776         if List.mem ProtocolLimitWarning flags then
6777           ("\n\n" ^ protocol_limit_warning)
6778         else "" in
6779
6780       (* For DangerWillRobinson commands, we should probably have
6781        * guestfish prompt before allowing you to use them (especially
6782        * in interactive mode). XXX
6783        *)
6784       let warnings =
6785         warnings ^
6786           if List.mem DangerWillRobinson flags then
6787             ("\n\n" ^ danger_will_robinson)
6788           else "" in
6789
6790       let warnings =
6791         warnings ^
6792           match deprecation_notice flags with
6793           | None -> ""
6794           | Some txt -> "\n\n" ^ txt in
6795
6796       let describe_alias =
6797         if name <> alias then
6798           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6799         else "" in
6800
6801       pr "  if (";
6802       pr "STRCASEEQ (cmd, \"%s\")" name;
6803       if name <> name2 then
6804         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6805       if name <> alias then
6806         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6807       pr ")\n";
6808       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6809         name2 shortdesc
6810         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6811          "=head1 DESCRIPTION\n\n" ^
6812          longdesc ^ warnings ^ describe_alias);
6813       pr "  else\n"
6814   ) all_functions;
6815   pr "    display_builtin_command (cmd);\n";
6816   pr "}\n";
6817   pr "\n";
6818
6819   let emit_print_list_function typ =
6820     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6821       typ typ typ;
6822     pr "{\n";
6823     pr "  unsigned int i;\n";
6824     pr "\n";
6825     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6826     pr "    printf (\"[%%d] = {\\n\", i);\n";
6827     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6828     pr "    printf (\"}\\n\");\n";
6829     pr "  }\n";
6830     pr "}\n";
6831     pr "\n";
6832   in
6833
6834   (* print_* functions *)
6835   List.iter (
6836     fun (typ, cols) ->
6837       let needs_i =
6838         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6839
6840       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6841       pr "{\n";
6842       if needs_i then (
6843         pr "  unsigned int i;\n";
6844         pr "\n"
6845       );
6846       List.iter (
6847         function
6848         | name, FString ->
6849             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6850         | name, FUUID ->
6851             pr "  printf (\"%%s%s: \", indent);\n" name;
6852             pr "  for (i = 0; i < 32; ++i)\n";
6853             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6854             pr "  printf (\"\\n\");\n"
6855         | name, FBuffer ->
6856             pr "  printf (\"%%s%s: \", indent);\n" name;
6857             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6858             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6859             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6860             pr "    else\n";
6861             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6862             pr "  printf (\"\\n\");\n"
6863         | name, (FUInt64|FBytes) ->
6864             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6865               name typ name
6866         | name, FInt64 ->
6867             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6868               name typ name
6869         | name, FUInt32 ->
6870             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6871               name typ name
6872         | name, FInt32 ->
6873             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6874               name typ name
6875         | name, FChar ->
6876             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6877               name typ name
6878         | name, FOptPercent ->
6879             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6880               typ name name typ name;
6881             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6882       ) cols;
6883       pr "}\n";
6884       pr "\n";
6885   ) structs;
6886
6887   (* Emit a print_TYPE_list function definition only if that function is used. *)
6888   List.iter (
6889     function
6890     | typ, (RStructListOnly | RStructAndList) ->
6891         (* generate the function for typ *)
6892         emit_print_list_function typ
6893     | typ, _ -> () (* empty *)
6894   ) (rstructs_used_by all_functions);
6895
6896   (* Emit a print_TYPE function definition only if that function is used. *)
6897   List.iter (
6898     function
6899     | typ, (RStructOnly | RStructAndList) ->
6900         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6901         pr "{\n";
6902         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6903         pr "}\n";
6904         pr "\n";
6905     | typ, _ -> () (* empty *)
6906   ) (rstructs_used_by all_functions);
6907
6908   (* run_<action> actions *)
6909   List.iter (
6910     fun (name, style, _, flags, _, _, _) ->
6911       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6912       pr "{\n";
6913       (match fst style with
6914        | RErr
6915        | RInt _
6916        | RBool _ -> pr "  int r;\n"
6917        | RInt64 _ -> pr "  int64_t r;\n"
6918        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6919        | RString _ -> pr "  char *r;\n"
6920        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6921        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6922        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6923        | RBufferOut _ ->
6924            pr "  char *r;\n";
6925            pr "  size_t size;\n";
6926       );
6927       List.iter (
6928         function
6929         | Device n
6930         | String n
6931         | OptString n
6932         | FileIn n
6933         | FileOut n -> pr "  const char *%s;\n" n
6934         | Pathname n
6935         | Dev_or_Path n -> pr "  char *%s;\n" n
6936         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6937         | Bool n -> pr "  int %s;\n" n
6938         | Int n -> pr "  int %s;\n" n
6939         | Int64 n -> pr "  int64_t %s;\n" n
6940       ) (snd style);
6941
6942       (* Check and convert parameters. *)
6943       let argc_expected = List.length (snd style) in
6944       pr "  if (argc != %d) {\n" argc_expected;
6945       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6946         argc_expected;
6947       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6948       pr "    return -1;\n";
6949       pr "  }\n";
6950       iteri (
6951         fun i ->
6952           function
6953           | Device name
6954           | String name ->
6955               pr "  %s = argv[%d];\n" name i
6956           | Pathname name
6957           | Dev_or_Path name ->
6958               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6959               pr "  if (%s == NULL) return -1;\n" name
6960           | OptString name ->
6961               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6962                 name i i
6963           | FileIn name ->
6964               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6965                 name i i
6966           | FileOut name ->
6967               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6968                 name i i
6969           | StringList name | DeviceList name ->
6970               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6971               pr "  if (%s == NULL) return -1;\n" name;
6972           | Bool name ->
6973               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6974           | Int name ->
6975               pr "  %s = atoi (argv[%d]);\n" name i
6976           | Int64 name ->
6977               pr "  %s = atoll (argv[%d]);\n" name i
6978       ) (snd style);
6979
6980       (* Call C API function. *)
6981       let fn =
6982         try find_map (function FishAction n -> Some n | _ -> None) flags
6983         with Not_found -> sprintf "guestfs_%s" name in
6984       pr "  r = %s " fn;
6985       generate_c_call_args ~handle:"g" style;
6986       pr ";\n";
6987
6988       List.iter (
6989         function
6990         | Device name | String name
6991         | OptString name | FileIn name | FileOut name | Bool name
6992         | Int name | Int64 name -> ()
6993         | Pathname name | Dev_or_Path name ->
6994             pr "  free (%s);\n" name
6995         | StringList name | DeviceList name ->
6996             pr "  free_strings (%s);\n" name
6997       ) (snd style);
6998
6999       (* Check return value for errors and display command results. *)
7000       (match fst style with
7001        | RErr -> pr "  return r;\n"
7002        | RInt _ ->
7003            pr "  if (r == -1) return -1;\n";
7004            pr "  printf (\"%%d\\n\", r);\n";
7005            pr "  return 0;\n"
7006        | RInt64 _ ->
7007            pr "  if (r == -1) return -1;\n";
7008            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7009            pr "  return 0;\n"
7010        | RBool _ ->
7011            pr "  if (r == -1) return -1;\n";
7012            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7013            pr "  return 0;\n"
7014        | RConstString _ ->
7015            pr "  if (r == NULL) return -1;\n";
7016            pr "  printf (\"%%s\\n\", r);\n";
7017            pr "  return 0;\n"
7018        | RConstOptString _ ->
7019            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7020            pr "  return 0;\n"
7021        | RString _ ->
7022            pr "  if (r == NULL) return -1;\n";
7023            pr "  printf (\"%%s\\n\", r);\n";
7024            pr "  free (r);\n";
7025            pr "  return 0;\n"
7026        | RStringList _ ->
7027            pr "  if (r == NULL) return -1;\n";
7028            pr "  print_strings (r);\n";
7029            pr "  free_strings (r);\n";
7030            pr "  return 0;\n"
7031        | RStruct (_, typ) ->
7032            pr "  if (r == NULL) return -1;\n";
7033            pr "  print_%s (r);\n" typ;
7034            pr "  guestfs_free_%s (r);\n" typ;
7035            pr "  return 0;\n"
7036        | RStructList (_, typ) ->
7037            pr "  if (r == NULL) return -1;\n";
7038            pr "  print_%s_list (r);\n" typ;
7039            pr "  guestfs_free_%s_list (r);\n" typ;
7040            pr "  return 0;\n"
7041        | RHashtable _ ->
7042            pr "  if (r == NULL) return -1;\n";
7043            pr "  print_table (r);\n";
7044            pr "  free_strings (r);\n";
7045            pr "  return 0;\n"
7046        | RBufferOut _ ->
7047            pr "  if (r == NULL) return -1;\n";
7048            pr "  fwrite (r, size, 1, stdout);\n";
7049            pr "  free (r);\n";
7050            pr "  return 0;\n"
7051       );
7052       pr "}\n";
7053       pr "\n"
7054   ) all_functions;
7055
7056   (* run_action function *)
7057   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7058   pr "{\n";
7059   List.iter (
7060     fun (name, _, _, flags, _, _, _) ->
7061       let name2 = replace_char name '_' '-' in
7062       let alias =
7063         try find_map (function FishAlias n -> Some n | _ -> None) flags
7064         with Not_found -> name in
7065       pr "  if (";
7066       pr "STRCASEEQ (cmd, \"%s\")" name;
7067       if name <> name2 then
7068         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7069       if name <> alias then
7070         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7071       pr ")\n";
7072       pr "    return run_%s (cmd, argc, argv);\n" name;
7073       pr "  else\n";
7074   ) all_functions;
7075   pr "    {\n";
7076   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7077   pr "      return -1;\n";
7078   pr "    }\n";
7079   pr "  return 0;\n";
7080   pr "}\n";
7081   pr "\n"
7082
7083 (* Readline completion for guestfish. *)
7084 and generate_fish_completion () =
7085   generate_header CStyle GPLv2;
7086
7087   let all_functions =
7088     List.filter (
7089       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7090     ) all_functions in
7091
7092   pr "\
7093 #include <config.h>
7094
7095 #include <stdio.h>
7096 #include <stdlib.h>
7097 #include <string.h>
7098
7099 #ifdef HAVE_LIBREADLINE
7100 #include <readline/readline.h>
7101 #endif
7102
7103 #include \"fish.h\"
7104
7105 #ifdef HAVE_LIBREADLINE
7106
7107 static const char *const commands[] = {
7108   BUILTIN_COMMANDS_FOR_COMPLETION,
7109 ";
7110
7111   (* Get the commands, including the aliases.  They don't need to be
7112    * sorted - the generator() function just does a dumb linear search.
7113    *)
7114   let commands =
7115     List.map (
7116       fun (name, _, _, flags, _, _, _) ->
7117         let name2 = replace_char name '_' '-' in
7118         let alias =
7119           try find_map (function FishAlias n -> Some n | _ -> None) flags
7120           with Not_found -> name in
7121
7122         if name <> alias then [name2; alias] else [name2]
7123     ) all_functions in
7124   let commands = List.flatten commands in
7125
7126   List.iter (pr "  \"%s\",\n") commands;
7127
7128   pr "  NULL
7129 };
7130
7131 static char *
7132 generator (const char *text, int state)
7133 {
7134   static int index, len;
7135   const char *name;
7136
7137   if (!state) {
7138     index = 0;
7139     len = strlen (text);
7140   }
7141
7142   rl_attempted_completion_over = 1;
7143
7144   while ((name = commands[index]) != NULL) {
7145     index++;
7146     if (STRCASEEQLEN (name, text, len))
7147       return strdup (name);
7148   }
7149
7150   return NULL;
7151 }
7152
7153 #endif /* HAVE_LIBREADLINE */
7154
7155 char **do_completion (const char *text, int start, int end)
7156 {
7157   char **matches = NULL;
7158
7159 #ifdef HAVE_LIBREADLINE
7160   rl_completion_append_character = ' ';
7161
7162   if (start == 0)
7163     matches = rl_completion_matches (text, generator);
7164   else if (complete_dest_paths)
7165     matches = rl_completion_matches (text, complete_dest_paths_generator);
7166 #endif
7167
7168   return matches;
7169 }
7170 ";
7171
7172 (* Generate the POD documentation for guestfish. *)
7173 and generate_fish_actions_pod () =
7174   let all_functions_sorted =
7175     List.filter (
7176       fun (_, _, _, flags, _, _, _) ->
7177         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7178     ) all_functions_sorted in
7179
7180   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7181
7182   List.iter (
7183     fun (name, style, _, flags, _, _, longdesc) ->
7184       let longdesc =
7185         Str.global_substitute rex (
7186           fun s ->
7187             let sub =
7188               try Str.matched_group 1 s
7189               with Not_found ->
7190                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7191             "C<" ^ replace_char sub '_' '-' ^ ">"
7192         ) longdesc in
7193       let name = replace_char name '_' '-' in
7194       let alias =
7195         try find_map (function FishAlias n -> Some n | _ -> None) flags
7196         with Not_found -> name in
7197
7198       pr "=head2 %s" name;
7199       if name <> alias then
7200         pr " | %s" alias;
7201       pr "\n";
7202       pr "\n";
7203       pr " %s" name;
7204       List.iter (
7205         function
7206         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7207         | OptString n -> pr " %s" n
7208         | StringList n | DeviceList n -> pr " '%s ...'" n
7209         | Bool _ -> pr " true|false"
7210         | Int n -> pr " %s" n
7211         | Int64 n -> pr " %s" n
7212         | FileIn n | FileOut n -> pr " (%s|-)" n
7213       ) (snd style);
7214       pr "\n";
7215       pr "\n";
7216       pr "%s\n\n" longdesc;
7217
7218       if List.exists (function FileIn _ | FileOut _ -> true
7219                       | _ -> false) (snd style) then
7220         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7221
7222       if List.mem ProtocolLimitWarning flags then
7223         pr "%s\n\n" protocol_limit_warning;
7224
7225       if List.mem DangerWillRobinson flags then
7226         pr "%s\n\n" danger_will_robinson;
7227
7228       match deprecation_notice flags with
7229       | None -> ()
7230       | Some txt -> pr "%s\n\n" txt
7231   ) all_functions_sorted
7232
7233 (* Generate a C function prototype. *)
7234 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7235     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7236     ?(prefix = "")
7237     ?handle name style =
7238   if extern then pr "extern ";
7239   if static then pr "static ";
7240   (match fst style with
7241    | RErr -> pr "int "
7242    | RInt _ -> pr "int "
7243    | RInt64 _ -> pr "int64_t "
7244    | RBool _ -> pr "int "
7245    | RConstString _ | RConstOptString _ -> pr "const char *"
7246    | RString _ | RBufferOut _ -> pr "char *"
7247    | RStringList _ | RHashtable _ -> pr "char **"
7248    | RStruct (_, typ) ->
7249        if not in_daemon then pr "struct guestfs_%s *" typ
7250        else pr "guestfs_int_%s *" typ
7251    | RStructList (_, typ) ->
7252        if not in_daemon then pr "struct guestfs_%s_list *" typ
7253        else pr "guestfs_int_%s_list *" typ
7254   );
7255   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7256   pr "%s%s (" prefix name;
7257   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7258     pr "void"
7259   else (
7260     let comma = ref false in
7261     (match handle with
7262      | None -> ()
7263      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7264     );
7265     let next () =
7266       if !comma then (
7267         if single_line then pr ", " else pr ",\n\t\t"
7268       );
7269       comma := true
7270     in
7271     List.iter (
7272       function
7273       | Pathname n
7274       | Device n | Dev_or_Path n
7275       | String n
7276       | OptString n ->
7277           next ();
7278           pr "const char *%s" n
7279       | StringList n | DeviceList n ->
7280           next ();
7281           pr "char *const *%s" n
7282       | Bool n -> next (); pr "int %s" n
7283       | Int n -> next (); pr "int %s" n
7284       | Int64 n -> next (); pr "int64_t %s" n
7285       | FileIn n
7286       | FileOut n ->
7287           if not in_daemon then (next (); pr "const char *%s" n)
7288     ) (snd style);
7289     if is_RBufferOut then (next (); pr "size_t *size_r");
7290   );
7291   pr ")";
7292   if semicolon then pr ";";
7293   if newline then pr "\n"
7294
7295 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7296 and generate_c_call_args ?handle ?(decl = false) style =
7297   pr "(";
7298   let comma = ref false in
7299   let next () =
7300     if !comma then pr ", ";
7301     comma := true
7302   in
7303   (match handle with
7304    | None -> ()
7305    | Some handle -> pr "%s" handle; comma := true
7306   );
7307   List.iter (
7308     fun arg ->
7309       next ();
7310       pr "%s" (name_of_argt arg)
7311   ) (snd style);
7312   (* For RBufferOut calls, add implicit &size parameter. *)
7313   if not decl then (
7314     match fst style with
7315     | RBufferOut _ ->
7316         next ();
7317         pr "&size"
7318     | _ -> ()
7319   );
7320   pr ")"
7321
7322 (* Generate the OCaml bindings interface. *)
7323 and generate_ocaml_mli () =
7324   generate_header OCamlStyle LGPLv2;
7325
7326   pr "\
7327 (** For API documentation you should refer to the C API
7328     in the guestfs(3) manual page.  The OCaml API uses almost
7329     exactly the same calls. *)
7330
7331 type t
7332 (** A [guestfs_h] handle. *)
7333
7334 exception Error of string
7335 (** This exception is raised when there is an error. *)
7336
7337 exception Handle_closed of string
7338 (** This exception is raised if you use a {!Guestfs.t} handle
7339     after calling {!close} on it.  The string is the name of
7340     the function. *)
7341
7342 val create : unit -> t
7343 (** Create a {!Guestfs.t} handle. *)
7344
7345 val close : t -> unit
7346 (** Close the {!Guestfs.t} handle and free up all resources used
7347     by it immediately.
7348
7349     Handles are closed by the garbage collector when they become
7350     unreferenced, but callers can call this in order to provide
7351     predictable cleanup. *)
7352
7353 ";
7354   generate_ocaml_structure_decls ();
7355
7356   (* The actions. *)
7357   List.iter (
7358     fun (name, style, _, _, _, shortdesc, _) ->
7359       generate_ocaml_prototype name style;
7360       pr "(** %s *)\n" shortdesc;
7361       pr "\n"
7362   ) all_functions_sorted
7363
7364 (* Generate the OCaml bindings implementation. *)
7365 and generate_ocaml_ml () =
7366   generate_header OCamlStyle LGPLv2;
7367
7368   pr "\
7369 type t
7370
7371 exception Error of string
7372 exception Handle_closed of string
7373
7374 external create : unit -> t = \"ocaml_guestfs_create\"
7375 external close : t -> unit = \"ocaml_guestfs_close\"
7376
7377 (* Give the exceptions names, so they can be raised from the C code. *)
7378 let () =
7379   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7380   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7381
7382 ";
7383
7384   generate_ocaml_structure_decls ();
7385
7386   (* The actions. *)
7387   List.iter (
7388     fun (name, style, _, _, _, shortdesc, _) ->
7389       generate_ocaml_prototype ~is_external:true name style;
7390   ) all_functions_sorted
7391
7392 (* Generate the OCaml bindings C implementation. *)
7393 and generate_ocaml_c () =
7394   generate_header CStyle LGPLv2;
7395
7396   pr "\
7397 #include <stdio.h>
7398 #include <stdlib.h>
7399 #include <string.h>
7400
7401 #include <caml/config.h>
7402 #include <caml/alloc.h>
7403 #include <caml/callback.h>
7404 #include <caml/fail.h>
7405 #include <caml/memory.h>
7406 #include <caml/mlvalues.h>
7407 #include <caml/signals.h>
7408
7409 #include <guestfs.h>
7410
7411 #include \"guestfs_c.h\"
7412
7413 /* Copy a hashtable of string pairs into an assoc-list.  We return
7414  * the list in reverse order, but hashtables aren't supposed to be
7415  * ordered anyway.
7416  */
7417 static CAMLprim value
7418 copy_table (char * const * argv)
7419 {
7420   CAMLparam0 ();
7421   CAMLlocal5 (rv, pairv, kv, vv, cons);
7422   int i;
7423
7424   rv = Val_int (0);
7425   for (i = 0; argv[i] != NULL; i += 2) {
7426     kv = caml_copy_string (argv[i]);
7427     vv = caml_copy_string (argv[i+1]);
7428     pairv = caml_alloc (2, 0);
7429     Store_field (pairv, 0, kv);
7430     Store_field (pairv, 1, vv);
7431     cons = caml_alloc (2, 0);
7432     Store_field (cons, 1, rv);
7433     rv = cons;
7434     Store_field (cons, 0, pairv);
7435   }
7436
7437   CAMLreturn (rv);
7438 }
7439
7440 ";
7441
7442   (* Struct copy functions. *)
7443
7444   let emit_ocaml_copy_list_function typ =
7445     pr "static CAMLprim value\n";
7446     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7447     pr "{\n";
7448     pr "  CAMLparam0 ();\n";
7449     pr "  CAMLlocal2 (rv, v);\n";
7450     pr "  unsigned int i;\n";
7451     pr "\n";
7452     pr "  if (%ss->len == 0)\n" typ;
7453     pr "    CAMLreturn (Atom (0));\n";
7454     pr "  else {\n";
7455     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7456     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7457     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7458     pr "      caml_modify (&Field (rv, i), v);\n";
7459     pr "    }\n";
7460     pr "    CAMLreturn (rv);\n";
7461     pr "  }\n";
7462     pr "}\n";
7463     pr "\n";
7464   in
7465
7466   List.iter (
7467     fun (typ, cols) ->
7468       let has_optpercent_col =
7469         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7470
7471       pr "static CAMLprim value\n";
7472       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7473       pr "{\n";
7474       pr "  CAMLparam0 ();\n";
7475       if has_optpercent_col then
7476         pr "  CAMLlocal3 (rv, v, v2);\n"
7477       else
7478         pr "  CAMLlocal2 (rv, v);\n";
7479       pr "\n";
7480       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7481       iteri (
7482         fun i col ->
7483           (match col with
7484            | name, FString ->
7485                pr "  v = caml_copy_string (%s->%s);\n" typ name
7486            | name, FBuffer ->
7487                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7488                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7489                  typ name typ name
7490            | name, FUUID ->
7491                pr "  v = caml_alloc_string (32);\n";
7492                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7493            | name, (FBytes|FInt64|FUInt64) ->
7494                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7495            | name, (FInt32|FUInt32) ->
7496                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7497            | name, FOptPercent ->
7498                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7499                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7500                pr "    v = caml_alloc (1, 0);\n";
7501                pr "    Store_field (v, 0, v2);\n";
7502                pr "  } else /* None */\n";
7503                pr "    v = Val_int (0);\n";
7504            | name, FChar ->
7505                pr "  v = Val_int (%s->%s);\n" typ name
7506           );
7507           pr "  Store_field (rv, %d, v);\n" i
7508       ) cols;
7509       pr "  CAMLreturn (rv);\n";
7510       pr "}\n";
7511       pr "\n";
7512   ) structs;
7513
7514   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7515   List.iter (
7516     function
7517     | typ, (RStructListOnly | RStructAndList) ->
7518         (* generate the function for typ *)
7519         emit_ocaml_copy_list_function typ
7520     | typ, _ -> () (* empty *)
7521   ) (rstructs_used_by all_functions);
7522
7523   (* The wrappers. *)
7524   List.iter (
7525     fun (name, style, _, _, _, _, _) ->
7526       pr "/* Automatically generated wrapper for function\n";
7527       pr " * ";
7528       generate_ocaml_prototype name style;
7529       pr " */\n";
7530       pr "\n";
7531
7532       let params =
7533         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7534
7535       let needs_extra_vs =
7536         match fst style with RConstOptString _ -> true | _ -> false in
7537
7538       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7539       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7540       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7541       pr "\n";
7542
7543       pr "CAMLprim value\n";
7544       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7545       List.iter (pr ", value %s") (List.tl params);
7546       pr ")\n";
7547       pr "{\n";
7548
7549       (match params with
7550        | [p1; p2; p3; p4; p5] ->
7551            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7552        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7553            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7554            pr "  CAMLxparam%d (%s);\n"
7555              (List.length rest) (String.concat ", " rest)
7556        | ps ->
7557            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7558       );
7559       if not needs_extra_vs then
7560         pr "  CAMLlocal1 (rv);\n"
7561       else
7562         pr "  CAMLlocal3 (rv, v, v2);\n";
7563       pr "\n";
7564
7565       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7566       pr "  if (g == NULL)\n";
7567       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7568       pr "\n";
7569
7570       List.iter (
7571         function
7572         | Pathname n
7573         | Device n | Dev_or_Path n
7574         | String n
7575         | FileIn n
7576         | FileOut n ->
7577             pr "  const char *%s = String_val (%sv);\n" n n
7578         | OptString n ->
7579             pr "  const char *%s =\n" n;
7580             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7581               n n
7582         | StringList n | DeviceList n ->
7583             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7584         | Bool n ->
7585             pr "  int %s = Bool_val (%sv);\n" n n
7586         | Int n ->
7587             pr "  int %s = Int_val (%sv);\n" n n
7588         | Int64 n ->
7589             pr "  int64_t %s = Int64_val (%sv);\n" n n
7590       ) (snd style);
7591       let error_code =
7592         match fst style with
7593         | RErr -> pr "  int r;\n"; "-1"
7594         | RInt _ -> pr "  int r;\n"; "-1"
7595         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7596         | RBool _ -> pr "  int r;\n"; "-1"
7597         | RConstString _ | RConstOptString _ ->
7598             pr "  const char *r;\n"; "NULL"
7599         | RString _ -> pr "  char *r;\n"; "NULL"
7600         | RStringList _ ->
7601             pr "  int i;\n";
7602             pr "  char **r;\n";
7603             "NULL"
7604         | RStruct (_, typ) ->
7605             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7606         | RStructList (_, typ) ->
7607             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7608         | RHashtable _ ->
7609             pr "  int i;\n";
7610             pr "  char **r;\n";
7611             "NULL"
7612         | RBufferOut _ ->
7613             pr "  char *r;\n";
7614             pr "  size_t size;\n";
7615             "NULL" in
7616       pr "\n";
7617
7618       pr "  caml_enter_blocking_section ();\n";
7619       pr "  r = guestfs_%s " name;
7620       generate_c_call_args ~handle:"g" style;
7621       pr ";\n";
7622       pr "  caml_leave_blocking_section ();\n";
7623
7624       List.iter (
7625         function
7626         | StringList n | DeviceList n ->
7627             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7628         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7629         | Bool _ | Int _ | Int64 _
7630         | FileIn _ | FileOut _ -> ()
7631       ) (snd style);
7632
7633       pr "  if (r == %s)\n" error_code;
7634       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7635       pr "\n";
7636
7637       (match fst style with
7638        | RErr -> pr "  rv = Val_unit;\n"
7639        | RInt _ -> pr "  rv = Val_int (r);\n"
7640        | RInt64 _ ->
7641            pr "  rv = caml_copy_int64 (r);\n"
7642        | RBool _ -> pr "  rv = Val_bool (r);\n"
7643        | RConstString _ ->
7644            pr "  rv = caml_copy_string (r);\n"
7645        | RConstOptString _ ->
7646            pr "  if (r) { /* Some string */\n";
7647            pr "    v = caml_alloc (1, 0);\n";
7648            pr "    v2 = caml_copy_string (r);\n";
7649            pr "    Store_field (v, 0, v2);\n";
7650            pr "  } else /* None */\n";
7651            pr "    v = Val_int (0);\n";
7652        | RString _ ->
7653            pr "  rv = caml_copy_string (r);\n";
7654            pr "  free (r);\n"
7655        | RStringList _ ->
7656            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7657            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7658            pr "  free (r);\n"
7659        | RStruct (_, typ) ->
7660            pr "  rv = copy_%s (r);\n" typ;
7661            pr "  guestfs_free_%s (r);\n" typ;
7662        | RStructList (_, typ) ->
7663            pr "  rv = copy_%s_list (r);\n" typ;
7664            pr "  guestfs_free_%s_list (r);\n" typ;
7665        | RHashtable _ ->
7666            pr "  rv = copy_table (r);\n";
7667            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7668            pr "  free (r);\n";
7669        | RBufferOut _ ->
7670            pr "  rv = caml_alloc_string (size);\n";
7671            pr "  memcpy (String_val (rv), r, size);\n";
7672       );
7673
7674       pr "  CAMLreturn (rv);\n";
7675       pr "}\n";
7676       pr "\n";
7677
7678       if List.length params > 5 then (
7679         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7680         pr "CAMLprim value ";
7681         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7682         pr "CAMLprim value\n";
7683         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7684         pr "{\n";
7685         pr "  return ocaml_guestfs_%s (argv[0]" name;
7686         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7687         pr ");\n";
7688         pr "}\n";
7689         pr "\n"
7690       )
7691   ) all_functions_sorted
7692
7693 and generate_ocaml_structure_decls () =
7694   List.iter (
7695     fun (typ, cols) ->
7696       pr "type %s = {\n" typ;
7697       List.iter (
7698         function
7699         | name, FString -> pr "  %s : string;\n" name
7700         | name, FBuffer -> pr "  %s : string;\n" name
7701         | name, FUUID -> pr "  %s : string;\n" name
7702         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7703         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7704         | name, FChar -> pr "  %s : char;\n" name
7705         | name, FOptPercent -> pr "  %s : float option;\n" name
7706       ) cols;
7707       pr "}\n";
7708       pr "\n"
7709   ) structs
7710
7711 and generate_ocaml_prototype ?(is_external = false) name style =
7712   if is_external then pr "external " else pr "val ";
7713   pr "%s : t -> " name;
7714   List.iter (
7715     function
7716     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7717     | OptString _ -> pr "string option -> "
7718     | StringList _ | DeviceList _ -> pr "string array -> "
7719     | Bool _ -> pr "bool -> "
7720     | Int _ -> pr "int -> "
7721     | Int64 _ -> pr "int64 -> "
7722   ) (snd style);
7723   (match fst style with
7724    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7725    | RInt _ -> pr "int"
7726    | RInt64 _ -> pr "int64"
7727    | RBool _ -> pr "bool"
7728    | RConstString _ -> pr "string"
7729    | RConstOptString _ -> pr "string option"
7730    | RString _ | RBufferOut _ -> pr "string"
7731    | RStringList _ -> pr "string array"
7732    | RStruct (_, typ) -> pr "%s" typ
7733    | RStructList (_, typ) -> pr "%s array" typ
7734    | RHashtable _ -> pr "(string * string) list"
7735   );
7736   if is_external then (
7737     pr " = ";
7738     if List.length (snd style) + 1 > 5 then
7739       pr "\"ocaml_guestfs_%s_byte\" " name;
7740     pr "\"ocaml_guestfs_%s\"" name
7741   );
7742   pr "\n"
7743
7744 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7745 and generate_perl_xs () =
7746   generate_header CStyle LGPLv2;
7747
7748   pr "\
7749 #include \"EXTERN.h\"
7750 #include \"perl.h\"
7751 #include \"XSUB.h\"
7752
7753 #include <guestfs.h>
7754
7755 #ifndef PRId64
7756 #define PRId64 \"lld\"
7757 #endif
7758
7759 static SV *
7760 my_newSVll(long long val) {
7761 #ifdef USE_64_BIT_ALL
7762   return newSViv(val);
7763 #else
7764   char buf[100];
7765   int len;
7766   len = snprintf(buf, 100, \"%%\" PRId64, val);
7767   return newSVpv(buf, len);
7768 #endif
7769 }
7770
7771 #ifndef PRIu64
7772 #define PRIu64 \"llu\"
7773 #endif
7774
7775 static SV *
7776 my_newSVull(unsigned long long val) {
7777 #ifdef USE_64_BIT_ALL
7778   return newSVuv(val);
7779 #else
7780   char buf[100];
7781   int len;
7782   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7783   return newSVpv(buf, len);
7784 #endif
7785 }
7786
7787 /* http://www.perlmonks.org/?node_id=680842 */
7788 static char **
7789 XS_unpack_charPtrPtr (SV *arg) {
7790   char **ret;
7791   AV *av;
7792   I32 i;
7793
7794   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7795     croak (\"array reference expected\");
7796
7797   av = (AV *)SvRV (arg);
7798   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7799   if (!ret)
7800     croak (\"malloc failed\");
7801
7802   for (i = 0; i <= av_len (av); i++) {
7803     SV **elem = av_fetch (av, i, 0);
7804
7805     if (!elem || !*elem)
7806       croak (\"missing element in list\");
7807
7808     ret[i] = SvPV_nolen (*elem);
7809   }
7810
7811   ret[i] = NULL;
7812
7813   return ret;
7814 }
7815
7816 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7817
7818 PROTOTYPES: ENABLE
7819
7820 guestfs_h *
7821 _create ()
7822    CODE:
7823       RETVAL = guestfs_create ();
7824       if (!RETVAL)
7825         croak (\"could not create guestfs handle\");
7826       guestfs_set_error_handler (RETVAL, NULL, NULL);
7827  OUTPUT:
7828       RETVAL
7829
7830 void
7831 DESTROY (g)
7832       guestfs_h *g;
7833  PPCODE:
7834       guestfs_close (g);
7835
7836 ";
7837
7838   List.iter (
7839     fun (name, style, _, _, _, _, _) ->
7840       (match fst style with
7841        | RErr -> pr "void\n"
7842        | RInt _ -> pr "SV *\n"
7843        | RInt64 _ -> pr "SV *\n"
7844        | RBool _ -> pr "SV *\n"
7845        | RConstString _ -> pr "SV *\n"
7846        | RConstOptString _ -> pr "SV *\n"
7847        | RString _ -> pr "SV *\n"
7848        | RBufferOut _ -> pr "SV *\n"
7849        | RStringList _
7850        | RStruct _ | RStructList _
7851        | RHashtable _ ->
7852            pr "void\n" (* all lists returned implictly on the stack *)
7853       );
7854       (* Call and arguments. *)
7855       pr "%s " name;
7856       generate_c_call_args ~handle:"g" ~decl:true style;
7857       pr "\n";
7858       pr "      guestfs_h *g;\n";
7859       iteri (
7860         fun i ->
7861           function
7862           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7863               pr "      char *%s;\n" n
7864           | OptString n ->
7865               (* http://www.perlmonks.org/?node_id=554277
7866                * Note that the implicit handle argument means we have
7867                * to add 1 to the ST(x) operator.
7868                *)
7869               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7870           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7871           | Bool n -> pr "      int %s;\n" n
7872           | Int n -> pr "      int %s;\n" n
7873           | Int64 n -> pr "      int64_t %s;\n" n
7874       ) (snd style);
7875
7876       let do_cleanups () =
7877         List.iter (
7878           function
7879           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7880           | Bool _ | Int _ | Int64 _
7881           | FileIn _ | FileOut _ -> ()
7882           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7883         ) (snd style)
7884       in
7885
7886       (* Code. *)
7887       (match fst style with
7888        | RErr ->
7889            pr "PREINIT:\n";
7890            pr "      int r;\n";
7891            pr " PPCODE:\n";
7892            pr "      r = guestfs_%s " name;
7893            generate_c_call_args ~handle:"g" style;
7894            pr ";\n";
7895            do_cleanups ();
7896            pr "      if (r == -1)\n";
7897            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7898        | RInt n
7899        | RBool n ->
7900            pr "PREINIT:\n";
7901            pr "      int %s;\n" n;
7902            pr "   CODE:\n";
7903            pr "      %s = guestfs_%s " n name;
7904            generate_c_call_args ~handle:"g" style;
7905            pr ";\n";
7906            do_cleanups ();
7907            pr "      if (%s == -1)\n" n;
7908            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7909            pr "      RETVAL = newSViv (%s);\n" n;
7910            pr " OUTPUT:\n";
7911            pr "      RETVAL\n"
7912        | RInt64 n ->
7913            pr "PREINIT:\n";
7914            pr "      int64_t %s;\n" n;
7915            pr "   CODE:\n";
7916            pr "      %s = guestfs_%s " n name;
7917            generate_c_call_args ~handle:"g" style;
7918            pr ";\n";
7919            do_cleanups ();
7920            pr "      if (%s == -1)\n" n;
7921            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7922            pr "      RETVAL = my_newSVll (%s);\n" n;
7923            pr " OUTPUT:\n";
7924            pr "      RETVAL\n"
7925        | RConstString n ->
7926            pr "PREINIT:\n";
7927            pr "      const char *%s;\n" n;
7928            pr "   CODE:\n";
7929            pr "      %s = guestfs_%s " n name;
7930            generate_c_call_args ~handle:"g" style;
7931            pr ";\n";
7932            do_cleanups ();
7933            pr "      if (%s == NULL)\n" n;
7934            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7935            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7936            pr " OUTPUT:\n";
7937            pr "      RETVAL\n"
7938        | RConstOptString n ->
7939            pr "PREINIT:\n";
7940            pr "      const char *%s;\n" n;
7941            pr "   CODE:\n";
7942            pr "      %s = guestfs_%s " n name;
7943            generate_c_call_args ~handle:"g" style;
7944            pr ";\n";
7945            do_cleanups ();
7946            pr "      if (%s == NULL)\n" n;
7947            pr "        RETVAL = &PL_sv_undef;\n";
7948            pr "      else\n";
7949            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7950            pr " OUTPUT:\n";
7951            pr "      RETVAL\n"
7952        | RString n ->
7953            pr "PREINIT:\n";
7954            pr "      char *%s;\n" n;
7955            pr "   CODE:\n";
7956            pr "      %s = guestfs_%s " n name;
7957            generate_c_call_args ~handle:"g" style;
7958            pr ";\n";
7959            do_cleanups ();
7960            pr "      if (%s == NULL)\n" n;
7961            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7962            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7963            pr "      free (%s);\n" n;
7964            pr " OUTPUT:\n";
7965            pr "      RETVAL\n"
7966        | RStringList n | RHashtable n ->
7967            pr "PREINIT:\n";
7968            pr "      char **%s;\n" n;
7969            pr "      int i, n;\n";
7970            pr " PPCODE:\n";
7971            pr "      %s = guestfs_%s " n name;
7972            generate_c_call_args ~handle:"g" style;
7973            pr ";\n";
7974            do_cleanups ();
7975            pr "      if (%s == NULL)\n" n;
7976            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7977            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7978            pr "      EXTEND (SP, n);\n";
7979            pr "      for (i = 0; i < n; ++i) {\n";
7980            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7981            pr "        free (%s[i]);\n" n;
7982            pr "      }\n";
7983            pr "      free (%s);\n" n;
7984        | RStruct (n, typ) ->
7985            let cols = cols_of_struct typ in
7986            generate_perl_struct_code typ cols name style n do_cleanups
7987        | RStructList (n, typ) ->
7988            let cols = cols_of_struct typ in
7989            generate_perl_struct_list_code typ cols name style n do_cleanups
7990        | RBufferOut n ->
7991            pr "PREINIT:\n";
7992            pr "      char *%s;\n" n;
7993            pr "      size_t size;\n";
7994            pr "   CODE:\n";
7995            pr "      %s = guestfs_%s " n name;
7996            generate_c_call_args ~handle:"g" style;
7997            pr ";\n";
7998            do_cleanups ();
7999            pr "      if (%s == NULL)\n" n;
8000            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8001            pr "      RETVAL = newSVpv (%s, size);\n" n;
8002            pr "      free (%s);\n" n;
8003            pr " OUTPUT:\n";
8004            pr "      RETVAL\n"
8005       );
8006
8007       pr "\n"
8008   ) all_functions
8009
8010 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8011   pr "PREINIT:\n";
8012   pr "      struct guestfs_%s_list *%s;\n" typ n;
8013   pr "      int i;\n";
8014   pr "      HV *hv;\n";
8015   pr " PPCODE:\n";
8016   pr "      %s = guestfs_%s " n name;
8017   generate_c_call_args ~handle:"g" style;
8018   pr ";\n";
8019   do_cleanups ();
8020   pr "      if (%s == NULL)\n" n;
8021   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8022   pr "      EXTEND (SP, %s->len);\n" n;
8023   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8024   pr "        hv = newHV ();\n";
8025   List.iter (
8026     function
8027     | name, FString ->
8028         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8029           name (String.length name) n name
8030     | name, FUUID ->
8031         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8032           name (String.length name) n name
8033     | name, FBuffer ->
8034         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8035           name (String.length name) n name n name
8036     | name, (FBytes|FUInt64) ->
8037         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8038           name (String.length name) n name
8039     | name, FInt64 ->
8040         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8041           name (String.length name) n name
8042     | name, (FInt32|FUInt32) ->
8043         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8044           name (String.length name) n name
8045     | name, FChar ->
8046         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8047           name (String.length name) n name
8048     | name, FOptPercent ->
8049         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8050           name (String.length name) n name
8051   ) cols;
8052   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8053   pr "      }\n";
8054   pr "      guestfs_free_%s_list (%s);\n" typ n
8055
8056 and generate_perl_struct_code typ cols name style n do_cleanups =
8057   pr "PREINIT:\n";
8058   pr "      struct guestfs_%s *%s;\n" typ n;
8059   pr " PPCODE:\n";
8060   pr "      %s = guestfs_%s " n name;
8061   generate_c_call_args ~handle:"g" style;
8062   pr ";\n";
8063   do_cleanups ();
8064   pr "      if (%s == NULL)\n" n;
8065   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8066   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8067   List.iter (
8068     fun ((name, _) as col) ->
8069       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8070
8071       match col with
8072       | name, FString ->
8073           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8074             n name
8075       | name, FBuffer ->
8076           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8077             n name n name
8078       | name, FUUID ->
8079           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8080             n name
8081       | name, (FBytes|FUInt64) ->
8082           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8083             n name
8084       | name, FInt64 ->
8085           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8086             n name
8087       | name, (FInt32|FUInt32) ->
8088           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8089             n name
8090       | name, FChar ->
8091           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8092             n name
8093       | name, FOptPercent ->
8094           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8095             n name
8096   ) cols;
8097   pr "      free (%s);\n" n
8098
8099 (* Generate Sys/Guestfs.pm. *)
8100 and generate_perl_pm () =
8101   generate_header HashStyle LGPLv2;
8102
8103   pr "\
8104 =pod
8105
8106 =head1 NAME
8107
8108 Sys::Guestfs - Perl bindings for libguestfs
8109
8110 =head1 SYNOPSIS
8111
8112  use Sys::Guestfs;
8113
8114  my $h = Sys::Guestfs->new ();
8115  $h->add_drive ('guest.img');
8116  $h->launch ();
8117  $h->mount ('/dev/sda1', '/');
8118  $h->touch ('/hello');
8119  $h->sync ();
8120
8121 =head1 DESCRIPTION
8122
8123 The C<Sys::Guestfs> module provides a Perl XS binding to the
8124 libguestfs API for examining and modifying virtual machine
8125 disk images.
8126
8127 Amongst the things this is good for: making batch configuration
8128 changes to guests, getting disk used/free statistics (see also:
8129 virt-df), migrating between virtualization systems (see also:
8130 virt-p2v), performing partial backups, performing partial guest
8131 clones, cloning guests and changing registry/UUID/hostname info, and
8132 much else besides.
8133
8134 Libguestfs uses Linux kernel and qemu code, and can access any type of
8135 guest filesystem that Linux and qemu can, including but not limited
8136 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8137 schemes, qcow, qcow2, vmdk.
8138
8139 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8140 LVs, what filesystem is in each LV, etc.).  It can also run commands
8141 in the context of the guest.  Also you can access filesystems over FTP.
8142
8143 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8144 functions for using libguestfs from Perl, including integration
8145 with libvirt.
8146
8147 =head1 ERRORS
8148
8149 All errors turn into calls to C<croak> (see L<Carp(3)>).
8150
8151 =head1 METHODS
8152
8153 =over 4
8154
8155 =cut
8156
8157 package Sys::Guestfs;
8158
8159 use strict;
8160 use warnings;
8161
8162 require XSLoader;
8163 XSLoader::load ('Sys::Guestfs');
8164
8165 =item $h = Sys::Guestfs->new ();
8166
8167 Create a new guestfs handle.
8168
8169 =cut
8170
8171 sub new {
8172   my $proto = shift;
8173   my $class = ref ($proto) || $proto;
8174
8175   my $self = Sys::Guestfs::_create ();
8176   bless $self, $class;
8177   return $self;
8178 }
8179
8180 ";
8181
8182   (* Actions.  We only need to print documentation for these as
8183    * they are pulled in from the XS code automatically.
8184    *)
8185   List.iter (
8186     fun (name, style, _, flags, _, _, longdesc) ->
8187       if not (List.mem NotInDocs flags) then (
8188         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8189         pr "=item ";
8190         generate_perl_prototype name style;
8191         pr "\n\n";
8192         pr "%s\n\n" longdesc;
8193         if List.mem ProtocolLimitWarning flags then
8194           pr "%s\n\n" protocol_limit_warning;
8195         if List.mem DangerWillRobinson flags then
8196           pr "%s\n\n" danger_will_robinson;
8197         match deprecation_notice flags with
8198         | None -> ()
8199         | Some txt -> pr "%s\n\n" txt
8200       )
8201   ) all_functions_sorted;
8202
8203   (* End of file. *)
8204   pr "\
8205 =cut
8206
8207 1;
8208
8209 =back
8210
8211 =head1 COPYRIGHT
8212
8213 Copyright (C) 2009 Red Hat Inc.
8214
8215 =head1 LICENSE
8216
8217 Please see the file COPYING.LIB for the full license.
8218
8219 =head1 SEE ALSO
8220
8221 L<guestfs(3)>,
8222 L<guestfish(1)>,
8223 L<http://libguestfs.org>,
8224 L<Sys::Guestfs::Lib(3)>.
8225
8226 =cut
8227 "
8228
8229 and generate_perl_prototype name style =
8230   (match fst style with
8231    | RErr -> ()
8232    | RBool n
8233    | RInt n
8234    | RInt64 n
8235    | RConstString n
8236    | RConstOptString n
8237    | RString n
8238    | RBufferOut n -> pr "$%s = " n
8239    | RStruct (n,_)
8240    | RHashtable n -> pr "%%%s = " n
8241    | RStringList n
8242    | RStructList (n,_) -> pr "@%s = " n
8243   );
8244   pr "$h->%s (" name;
8245   let comma = ref false in
8246   List.iter (
8247     fun arg ->
8248       if !comma then pr ", ";
8249       comma := true;
8250       match arg with
8251       | Pathname n | Device n | Dev_or_Path n | String n
8252       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8253           pr "$%s" n
8254       | StringList n | DeviceList n ->
8255           pr "\\@%s" n
8256   ) (snd style);
8257   pr ");"
8258
8259 (* Generate Python C module. *)
8260 and generate_python_c () =
8261   generate_header CStyle LGPLv2;
8262
8263   pr "\
8264 #include <Python.h>
8265
8266 #include <stdio.h>
8267 #include <stdlib.h>
8268 #include <assert.h>
8269
8270 #include \"guestfs.h\"
8271
8272 typedef struct {
8273   PyObject_HEAD
8274   guestfs_h *g;
8275 } Pyguestfs_Object;
8276
8277 static guestfs_h *
8278 get_handle (PyObject *obj)
8279 {
8280   assert (obj);
8281   assert (obj != Py_None);
8282   return ((Pyguestfs_Object *) obj)->g;
8283 }
8284
8285 static PyObject *
8286 put_handle (guestfs_h *g)
8287 {
8288   assert (g);
8289   return
8290     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8291 }
8292
8293 /* This list should be freed (but not the strings) after use. */
8294 static char **
8295 get_string_list (PyObject *obj)
8296 {
8297   int i, len;
8298   char **r;
8299
8300   assert (obj);
8301
8302   if (!PyList_Check (obj)) {
8303     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8304     return NULL;
8305   }
8306
8307   len = PyList_Size (obj);
8308   r = malloc (sizeof (char *) * (len+1));
8309   if (r == NULL) {
8310     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8311     return NULL;
8312   }
8313
8314   for (i = 0; i < len; ++i)
8315     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8316   r[len] = NULL;
8317
8318   return r;
8319 }
8320
8321 static PyObject *
8322 put_string_list (char * const * const argv)
8323 {
8324   PyObject *list;
8325   int argc, i;
8326
8327   for (argc = 0; argv[argc] != NULL; ++argc)
8328     ;
8329
8330   list = PyList_New (argc);
8331   for (i = 0; i < argc; ++i)
8332     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8333
8334   return list;
8335 }
8336
8337 static PyObject *
8338 put_table (char * const * const argv)
8339 {
8340   PyObject *list, *item;
8341   int argc, i;
8342
8343   for (argc = 0; argv[argc] != NULL; ++argc)
8344     ;
8345
8346   list = PyList_New (argc >> 1);
8347   for (i = 0; i < argc; i += 2) {
8348     item = PyTuple_New (2);
8349     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8350     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8351     PyList_SetItem (list, i >> 1, item);
8352   }
8353
8354   return list;
8355 }
8356
8357 static void
8358 free_strings (char **argv)
8359 {
8360   int argc;
8361
8362   for (argc = 0; argv[argc] != NULL; ++argc)
8363     free (argv[argc]);
8364   free (argv);
8365 }
8366
8367 static PyObject *
8368 py_guestfs_create (PyObject *self, PyObject *args)
8369 {
8370   guestfs_h *g;
8371
8372   g = guestfs_create ();
8373   if (g == NULL) {
8374     PyErr_SetString (PyExc_RuntimeError,
8375                      \"guestfs.create: failed to allocate handle\");
8376     return NULL;
8377   }
8378   guestfs_set_error_handler (g, NULL, NULL);
8379   return put_handle (g);
8380 }
8381
8382 static PyObject *
8383 py_guestfs_close (PyObject *self, PyObject *args)
8384 {
8385   PyObject *py_g;
8386   guestfs_h *g;
8387
8388   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8389     return NULL;
8390   g = get_handle (py_g);
8391
8392   guestfs_close (g);
8393
8394   Py_INCREF (Py_None);
8395   return Py_None;
8396 }
8397
8398 ";
8399
8400   let emit_put_list_function typ =
8401     pr "static PyObject *\n";
8402     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8403     pr "{\n";
8404     pr "  PyObject *list;\n";
8405     pr "  int i;\n";
8406     pr "\n";
8407     pr "  list = PyList_New (%ss->len);\n" typ;
8408     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8409     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8410     pr "  return list;\n";
8411     pr "};\n";
8412     pr "\n"
8413   in
8414
8415   (* Structures, turned into Python dictionaries. *)
8416   List.iter (
8417     fun (typ, cols) ->
8418       pr "static PyObject *\n";
8419       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8420       pr "{\n";
8421       pr "  PyObject *dict;\n";
8422       pr "\n";
8423       pr "  dict = PyDict_New ();\n";
8424       List.iter (
8425         function
8426         | name, FString ->
8427             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8428             pr "                        PyString_FromString (%s->%s));\n"
8429               typ name
8430         | name, FBuffer ->
8431             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8432             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8433               typ name typ name
8434         | name, FUUID ->
8435             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8436             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8437               typ name
8438         | name, (FBytes|FUInt64) ->
8439             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8440             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8441               typ name
8442         | name, FInt64 ->
8443             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8444             pr "                        PyLong_FromLongLong (%s->%s));\n"
8445               typ name
8446         | name, FUInt32 ->
8447             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8448             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8449               typ name
8450         | name, FInt32 ->
8451             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8452             pr "                        PyLong_FromLong (%s->%s));\n"
8453               typ name
8454         | name, FOptPercent ->
8455             pr "  if (%s->%s >= 0)\n" typ name;
8456             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8457             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8458               typ name;
8459             pr "  else {\n";
8460             pr "    Py_INCREF (Py_None);\n";
8461             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8462             pr "  }\n"
8463         | name, FChar ->
8464             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8465             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8466       ) cols;
8467       pr "  return dict;\n";
8468       pr "};\n";
8469       pr "\n";
8470
8471   ) structs;
8472
8473   (* Emit a put_TYPE_list function definition only if that function is used. *)
8474   List.iter (
8475     function
8476     | typ, (RStructListOnly | RStructAndList) ->
8477         (* generate the function for typ *)
8478         emit_put_list_function typ
8479     | typ, _ -> () (* empty *)
8480   ) (rstructs_used_by all_functions);
8481
8482   (* Python wrapper functions. *)
8483   List.iter (
8484     fun (name, style, _, _, _, _, _) ->
8485       pr "static PyObject *\n";
8486       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8487       pr "{\n";
8488
8489       pr "  PyObject *py_g;\n";
8490       pr "  guestfs_h *g;\n";
8491       pr "  PyObject *py_r;\n";
8492
8493       let error_code =
8494         match fst style with
8495         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8496         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8497         | RConstString _ | RConstOptString _ ->
8498             pr "  const char *r;\n"; "NULL"
8499         | RString _ -> pr "  char *r;\n"; "NULL"
8500         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8501         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8502         | RStructList (_, typ) ->
8503             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8504         | RBufferOut _ ->
8505             pr "  char *r;\n";
8506             pr "  size_t size;\n";
8507             "NULL" in
8508
8509       List.iter (
8510         function
8511         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8512             pr "  const char *%s;\n" n
8513         | OptString n -> pr "  const char *%s;\n" n
8514         | StringList n | DeviceList n ->
8515             pr "  PyObject *py_%s;\n" n;
8516             pr "  char **%s;\n" n
8517         | Bool n -> pr "  int %s;\n" n
8518         | Int n -> pr "  int %s;\n" n
8519         | Int64 n -> pr "  long long %s;\n" n
8520       ) (snd style);
8521
8522       pr "\n";
8523
8524       (* Convert the parameters. *)
8525       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8526       List.iter (
8527         function
8528         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8529         | OptString _ -> pr "z"
8530         | StringList _ | DeviceList _ -> pr "O"
8531         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8532         | Int _ -> pr "i"
8533         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8534                              * emulate C's int/long/long long in Python?
8535                              *)
8536       ) (snd style);
8537       pr ":guestfs_%s\",\n" name;
8538       pr "                         &py_g";
8539       List.iter (
8540         function
8541         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8542         | OptString n -> pr ", &%s" n
8543         | StringList n | DeviceList n -> pr ", &py_%s" n
8544         | Bool n -> pr ", &%s" n
8545         | Int n -> pr ", &%s" n
8546         | Int64 n -> pr ", &%s" n
8547       ) (snd style);
8548
8549       pr "))\n";
8550       pr "    return NULL;\n";
8551
8552       pr "  g = get_handle (py_g);\n";
8553       List.iter (
8554         function
8555         | Pathname _ | Device _ | Dev_or_Path _ | String _
8556         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8557         | StringList n | DeviceList n ->
8558             pr "  %s = get_string_list (py_%s);\n" n n;
8559             pr "  if (!%s) return NULL;\n" n
8560       ) (snd style);
8561
8562       pr "\n";
8563
8564       pr "  r = guestfs_%s " name;
8565       generate_c_call_args ~handle:"g" style;
8566       pr ";\n";
8567
8568       List.iter (
8569         function
8570         | Pathname _ | Device _ | Dev_or_Path _ | String _
8571         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8572         | StringList n | DeviceList n ->
8573             pr "  free (%s);\n" n
8574       ) (snd style);
8575
8576       pr "  if (r == %s) {\n" error_code;
8577       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8578       pr "    return NULL;\n";
8579       pr "  }\n";
8580       pr "\n";
8581
8582       (match fst style with
8583        | RErr ->
8584            pr "  Py_INCREF (Py_None);\n";
8585            pr "  py_r = Py_None;\n"
8586        | RInt _
8587        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8588        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8589        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8590        | RConstOptString _ ->
8591            pr "  if (r)\n";
8592            pr "    py_r = PyString_FromString (r);\n";
8593            pr "  else {\n";
8594            pr "    Py_INCREF (Py_None);\n";
8595            pr "    py_r = Py_None;\n";
8596            pr "  }\n"
8597        | RString _ ->
8598            pr "  py_r = PyString_FromString (r);\n";
8599            pr "  free (r);\n"
8600        | RStringList _ ->
8601            pr "  py_r = put_string_list (r);\n";
8602            pr "  free_strings (r);\n"
8603        | RStruct (_, typ) ->
8604            pr "  py_r = put_%s (r);\n" typ;
8605            pr "  guestfs_free_%s (r);\n" typ
8606        | RStructList (_, typ) ->
8607            pr "  py_r = put_%s_list (r);\n" typ;
8608            pr "  guestfs_free_%s_list (r);\n" typ
8609        | RHashtable n ->
8610            pr "  py_r = put_table (r);\n";
8611            pr "  free_strings (r);\n"
8612        | RBufferOut _ ->
8613            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8614            pr "  free (r);\n"
8615       );
8616
8617       pr "  return py_r;\n";
8618       pr "}\n";
8619       pr "\n"
8620   ) all_functions;
8621
8622   (* Table of functions. *)
8623   pr "static PyMethodDef methods[] = {\n";
8624   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8625   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8626   List.iter (
8627     fun (name, _, _, _, _, _, _) ->
8628       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8629         name name
8630   ) all_functions;
8631   pr "  { NULL, NULL, 0, NULL }\n";
8632   pr "};\n";
8633   pr "\n";
8634
8635   (* Init function. *)
8636   pr "\
8637 void
8638 initlibguestfsmod (void)
8639 {
8640   static int initialized = 0;
8641
8642   if (initialized) return;
8643   Py_InitModule ((char *) \"libguestfsmod\", methods);
8644   initialized = 1;
8645 }
8646 "
8647
8648 (* Generate Python module. *)
8649 and generate_python_py () =
8650   generate_header HashStyle LGPLv2;
8651
8652   pr "\
8653 u\"\"\"Python bindings for libguestfs
8654
8655 import guestfs
8656 g = guestfs.GuestFS ()
8657 g.add_drive (\"guest.img\")
8658 g.launch ()
8659 parts = g.list_partitions ()
8660
8661 The guestfs module provides a Python binding to the libguestfs API
8662 for examining and modifying virtual machine disk images.
8663
8664 Amongst the things this is good for: making batch configuration
8665 changes to guests, getting disk used/free statistics (see also:
8666 virt-df), migrating between virtualization systems (see also:
8667 virt-p2v), performing partial backups, performing partial guest
8668 clones, cloning guests and changing registry/UUID/hostname info, and
8669 much else besides.
8670
8671 Libguestfs uses Linux kernel and qemu code, and can access any type of
8672 guest filesystem that Linux and qemu can, including but not limited
8673 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8674 schemes, qcow, qcow2, vmdk.
8675
8676 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8677 LVs, what filesystem is in each LV, etc.).  It can also run commands
8678 in the context of the guest.  Also you can access filesystems over FTP.
8679
8680 Errors which happen while using the API are turned into Python
8681 RuntimeError exceptions.
8682
8683 To create a guestfs handle you usually have to perform the following
8684 sequence of calls:
8685
8686 # Create the handle, call add_drive at least once, and possibly
8687 # several times if the guest has multiple block devices:
8688 g = guestfs.GuestFS ()
8689 g.add_drive (\"guest.img\")
8690
8691 # Launch the qemu subprocess and wait for it to become ready:
8692 g.launch ()
8693
8694 # Now you can issue commands, for example:
8695 logvols = g.lvs ()
8696
8697 \"\"\"
8698
8699 import libguestfsmod
8700
8701 class GuestFS:
8702     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8703
8704     def __init__ (self):
8705         \"\"\"Create a new libguestfs handle.\"\"\"
8706         self._o = libguestfsmod.create ()
8707
8708     def __del__ (self):
8709         libguestfsmod.close (self._o)
8710
8711 ";
8712
8713   List.iter (
8714     fun (name, style, _, flags, _, _, longdesc) ->
8715       pr "    def %s " name;
8716       generate_py_call_args ~handle:"self" (snd style);
8717       pr ":\n";
8718
8719       if not (List.mem NotInDocs flags) then (
8720         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8721         let doc =
8722           match fst style with
8723           | RErr | RInt _ | RInt64 _ | RBool _
8724           | RConstOptString _ | RConstString _
8725           | RString _ | RBufferOut _ -> doc
8726           | RStringList _ ->
8727               doc ^ "\n\nThis function returns a list of strings."
8728           | RStruct (_, typ) ->
8729               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8730           | RStructList (_, typ) ->
8731               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8732           | RHashtable _ ->
8733               doc ^ "\n\nThis function returns a dictionary." in
8734         let doc =
8735           if List.mem ProtocolLimitWarning flags then
8736             doc ^ "\n\n" ^ protocol_limit_warning
8737           else doc in
8738         let doc =
8739           if List.mem DangerWillRobinson flags then
8740             doc ^ "\n\n" ^ danger_will_robinson
8741           else doc in
8742         let doc =
8743           match deprecation_notice flags with
8744           | None -> doc
8745           | Some txt -> doc ^ "\n\n" ^ txt in
8746         let doc = pod2text ~width:60 name doc in
8747         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8748         let doc = String.concat "\n        " doc in
8749         pr "        u\"\"\"%s\"\"\"\n" doc;
8750       );
8751       pr "        return libguestfsmod.%s " name;
8752       generate_py_call_args ~handle:"self._o" (snd style);
8753       pr "\n";
8754       pr "\n";
8755   ) all_functions
8756
8757 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8758 and generate_py_call_args ~handle args =
8759   pr "(%s" handle;
8760   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8761   pr ")"
8762
8763 (* Useful if you need the longdesc POD text as plain text.  Returns a
8764  * list of lines.
8765  *
8766  * Because this is very slow (the slowest part of autogeneration),
8767  * we memoize the results.
8768  *)
8769 and pod2text ~width name longdesc =
8770   let key = width, name, longdesc in
8771   try Hashtbl.find pod2text_memo key
8772   with Not_found ->
8773     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8774     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8775     close_out chan;
8776     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8777     let chan = open_process_in cmd in
8778     let lines = ref [] in
8779     let rec loop i =
8780       let line = input_line chan in
8781       if i = 1 then             (* discard the first line of output *)
8782         loop (i+1)
8783       else (
8784         let line = triml line in
8785         lines := line :: !lines;
8786         loop (i+1)
8787       ) in
8788     let lines = try loop 1 with End_of_file -> List.rev !lines in
8789     unlink filename;
8790     (match close_process_in chan with
8791      | WEXITED 0 -> ()
8792      | WEXITED i ->
8793          failwithf "pod2text: process exited with non-zero status (%d)" i
8794      | WSIGNALED i | WSTOPPED i ->
8795          failwithf "pod2text: process signalled or stopped by signal %d" i
8796     );
8797     Hashtbl.add pod2text_memo key lines;
8798     pod2text_memo_updated ();
8799     lines
8800
8801 (* Generate ruby bindings. *)
8802 and generate_ruby_c () =
8803   generate_header CStyle LGPLv2;
8804
8805   pr "\
8806 #include <stdio.h>
8807 #include <stdlib.h>
8808
8809 #include <ruby.h>
8810
8811 #include \"guestfs.h\"
8812
8813 #include \"extconf.h\"
8814
8815 /* For Ruby < 1.9 */
8816 #ifndef RARRAY_LEN
8817 #define RARRAY_LEN(r) (RARRAY((r))->len)
8818 #endif
8819
8820 static VALUE m_guestfs;                 /* guestfs module */
8821 static VALUE c_guestfs;                 /* guestfs_h handle */
8822 static VALUE e_Error;                   /* used for all errors */
8823
8824 static void ruby_guestfs_free (void *p)
8825 {
8826   if (!p) return;
8827   guestfs_close ((guestfs_h *) p);
8828 }
8829
8830 static VALUE ruby_guestfs_create (VALUE m)
8831 {
8832   guestfs_h *g;
8833
8834   g = guestfs_create ();
8835   if (!g)
8836     rb_raise (e_Error, \"failed to create guestfs handle\");
8837
8838   /* Don't print error messages to stderr by default. */
8839   guestfs_set_error_handler (g, NULL, NULL);
8840
8841   /* Wrap it, and make sure the close function is called when the
8842    * handle goes away.
8843    */
8844   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8845 }
8846
8847 static VALUE ruby_guestfs_close (VALUE gv)
8848 {
8849   guestfs_h *g;
8850   Data_Get_Struct (gv, guestfs_h, g);
8851
8852   ruby_guestfs_free (g);
8853   DATA_PTR (gv) = NULL;
8854
8855   return Qnil;
8856 }
8857
8858 ";
8859
8860   List.iter (
8861     fun (name, style, _, _, _, _, _) ->
8862       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8863       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8864       pr ")\n";
8865       pr "{\n";
8866       pr "  guestfs_h *g;\n";
8867       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8868       pr "  if (!g)\n";
8869       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8870         name;
8871       pr "\n";
8872
8873       List.iter (
8874         function
8875         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8876             pr "  Check_Type (%sv, T_STRING);\n" n;
8877             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8878             pr "  if (!%s)\n" n;
8879             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8880             pr "              \"%s\", \"%s\");\n" n name
8881         | OptString n ->
8882             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8883         | StringList n | DeviceList n ->
8884             pr "  char **%s;\n" n;
8885             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8886             pr "  {\n";
8887             pr "    int i, len;\n";
8888             pr "    len = RARRAY_LEN (%sv);\n" n;
8889             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8890               n;
8891             pr "    for (i = 0; i < len; ++i) {\n";
8892             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8893             pr "      %s[i] = StringValueCStr (v);\n" n;
8894             pr "    }\n";
8895             pr "    %s[len] = NULL;\n" n;
8896             pr "  }\n";
8897         | Bool n ->
8898             pr "  int %s = RTEST (%sv);\n" n n
8899         | Int n ->
8900             pr "  int %s = NUM2INT (%sv);\n" n n
8901         | Int64 n ->
8902             pr "  long long %s = NUM2LL (%sv);\n" n n
8903       ) (snd style);
8904       pr "\n";
8905
8906       let error_code =
8907         match fst style with
8908         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8909         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8910         | RConstString _ | RConstOptString _ ->
8911             pr "  const char *r;\n"; "NULL"
8912         | RString _ -> pr "  char *r;\n"; "NULL"
8913         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8914         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8915         | RStructList (_, typ) ->
8916             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8917         | RBufferOut _ ->
8918             pr "  char *r;\n";
8919             pr "  size_t size;\n";
8920             "NULL" in
8921       pr "\n";
8922
8923       pr "  r = guestfs_%s " name;
8924       generate_c_call_args ~handle:"g" style;
8925       pr ";\n";
8926
8927       List.iter (
8928         function
8929         | Pathname _ | Device _ | Dev_or_Path _ | String _
8930         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8931         | StringList n | DeviceList n ->
8932             pr "  free (%s);\n" n
8933       ) (snd style);
8934
8935       pr "  if (r == %s)\n" error_code;
8936       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8937       pr "\n";
8938
8939       (match fst style with
8940        | RErr ->
8941            pr "  return Qnil;\n"
8942        | RInt _ | RBool _ ->
8943            pr "  return INT2NUM (r);\n"
8944        | RInt64 _ ->
8945            pr "  return ULL2NUM (r);\n"
8946        | RConstString _ ->
8947            pr "  return rb_str_new2 (r);\n";
8948        | RConstOptString _ ->
8949            pr "  if (r)\n";
8950            pr "    return rb_str_new2 (r);\n";
8951            pr "  else\n";
8952            pr "    return Qnil;\n";
8953        | RString _ ->
8954            pr "  VALUE rv = rb_str_new2 (r);\n";
8955            pr "  free (r);\n";
8956            pr "  return rv;\n";
8957        | RStringList _ ->
8958            pr "  int i, len = 0;\n";
8959            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8960            pr "  VALUE rv = rb_ary_new2 (len);\n";
8961            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8962            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8963            pr "    free (r[i]);\n";
8964            pr "  }\n";
8965            pr "  free (r);\n";
8966            pr "  return rv;\n"
8967        | RStruct (_, typ) ->
8968            let cols = cols_of_struct typ in
8969            generate_ruby_struct_code typ cols
8970        | RStructList (_, typ) ->
8971            let cols = cols_of_struct typ in
8972            generate_ruby_struct_list_code typ cols
8973        | RHashtable _ ->
8974            pr "  VALUE rv = rb_hash_new ();\n";
8975            pr "  int i;\n";
8976            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8977            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8978            pr "    free (r[i]);\n";
8979            pr "    free (r[i+1]);\n";
8980            pr "  }\n";
8981            pr "  free (r);\n";
8982            pr "  return rv;\n"
8983        | RBufferOut _ ->
8984            pr "  VALUE rv = rb_str_new (r, size);\n";
8985            pr "  free (r);\n";
8986            pr "  return rv;\n";
8987       );
8988
8989       pr "}\n";
8990       pr "\n"
8991   ) all_functions;
8992
8993   pr "\
8994 /* Initialize the module. */
8995 void Init__guestfs ()
8996 {
8997   m_guestfs = rb_define_module (\"Guestfs\");
8998   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8999   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9000
9001   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9002   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9003
9004 ";
9005   (* Define the rest of the methods. *)
9006   List.iter (
9007     fun (name, style, _, _, _, _, _) ->
9008       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9009       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9010   ) all_functions;
9011
9012   pr "}\n"
9013
9014 (* Ruby code to return a struct. *)
9015 and generate_ruby_struct_code typ cols =
9016   pr "  VALUE rv = rb_hash_new ();\n";
9017   List.iter (
9018     function
9019     | name, FString ->
9020         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9021     | name, FBuffer ->
9022         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9023     | name, FUUID ->
9024         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9025     | name, (FBytes|FUInt64) ->
9026         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9027     | name, FInt64 ->
9028         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9029     | name, FUInt32 ->
9030         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9031     | name, FInt32 ->
9032         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9033     | name, FOptPercent ->
9034         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9035     | name, FChar -> (* XXX wrong? *)
9036         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9037   ) cols;
9038   pr "  guestfs_free_%s (r);\n" typ;
9039   pr "  return rv;\n"
9040
9041 (* Ruby code to return a struct list. *)
9042 and generate_ruby_struct_list_code typ cols =
9043   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9044   pr "  int i;\n";
9045   pr "  for (i = 0; i < r->len; ++i) {\n";
9046   pr "    VALUE hv = rb_hash_new ();\n";
9047   List.iter (
9048     function
9049     | name, FString ->
9050         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9051     | name, FBuffer ->
9052         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
9053     | name, FUUID ->
9054         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9055     | name, (FBytes|FUInt64) ->
9056         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9057     | name, FInt64 ->
9058         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9059     | name, FUInt32 ->
9060         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9061     | name, FInt32 ->
9062         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9063     | name, FOptPercent ->
9064         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9065     | name, FChar -> (* XXX wrong? *)
9066         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9067   ) cols;
9068   pr "    rb_ary_push (rv, hv);\n";
9069   pr "  }\n";
9070   pr "  guestfs_free_%s_list (r);\n" typ;
9071   pr "  return rv;\n"
9072
9073 (* Generate Java bindings GuestFS.java file. *)
9074 and generate_java_java () =
9075   generate_header CStyle LGPLv2;
9076
9077   pr "\
9078 package com.redhat.et.libguestfs;
9079
9080 import java.util.HashMap;
9081 import com.redhat.et.libguestfs.LibGuestFSException;
9082 import com.redhat.et.libguestfs.PV;
9083 import com.redhat.et.libguestfs.VG;
9084 import com.redhat.et.libguestfs.LV;
9085 import com.redhat.et.libguestfs.Stat;
9086 import com.redhat.et.libguestfs.StatVFS;
9087 import com.redhat.et.libguestfs.IntBool;
9088 import com.redhat.et.libguestfs.Dirent;
9089
9090 /**
9091  * The GuestFS object is a libguestfs handle.
9092  *
9093  * @author rjones
9094  */
9095 public class GuestFS {
9096   // Load the native code.
9097   static {
9098     System.loadLibrary (\"guestfs_jni\");
9099   }
9100
9101   /**
9102    * The native guestfs_h pointer.
9103    */
9104   long g;
9105
9106   /**
9107    * Create a libguestfs handle.
9108    *
9109    * @throws LibGuestFSException
9110    */
9111   public GuestFS () throws LibGuestFSException
9112   {
9113     g = _create ();
9114   }
9115   private native long _create () throws LibGuestFSException;
9116
9117   /**
9118    * Close a libguestfs handle.
9119    *
9120    * You can also leave handles to be collected by the garbage
9121    * collector, but this method ensures that the resources used
9122    * by the handle are freed up immediately.  If you call any
9123    * other methods after closing the handle, you will get an
9124    * exception.
9125    *
9126    * @throws LibGuestFSException
9127    */
9128   public void close () throws LibGuestFSException
9129   {
9130     if (g != 0)
9131       _close (g);
9132     g = 0;
9133   }
9134   private native void _close (long g) throws LibGuestFSException;
9135
9136   public void finalize () throws LibGuestFSException
9137   {
9138     close ();
9139   }
9140
9141 ";
9142
9143   List.iter (
9144     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9145       if not (List.mem NotInDocs flags); then (
9146         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9147         let doc =
9148           if List.mem ProtocolLimitWarning flags then
9149             doc ^ "\n\n" ^ protocol_limit_warning
9150           else doc in
9151         let doc =
9152           if List.mem DangerWillRobinson flags then
9153             doc ^ "\n\n" ^ danger_will_robinson
9154           else doc in
9155         let doc =
9156           match deprecation_notice flags with
9157           | None -> doc
9158           | Some txt -> doc ^ "\n\n" ^ txt in
9159         let doc = pod2text ~width:60 name doc in
9160         let doc = List.map (            (* RHBZ#501883 *)
9161           function
9162           | "" -> "<p>"
9163           | nonempty -> nonempty
9164         ) doc in
9165         let doc = String.concat "\n   * " doc in
9166
9167         pr "  /**\n";
9168         pr "   * %s\n" shortdesc;
9169         pr "   * <p>\n";
9170         pr "   * %s\n" doc;
9171         pr "   * @throws LibGuestFSException\n";
9172         pr "   */\n";
9173         pr "  ";
9174       );
9175       generate_java_prototype ~public:true ~semicolon:false name style;
9176       pr "\n";
9177       pr "  {\n";
9178       pr "    if (g == 0)\n";
9179       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9180         name;
9181       pr "    ";
9182       if fst style <> RErr then pr "return ";
9183       pr "_%s " name;
9184       generate_java_call_args ~handle:"g" (snd style);
9185       pr ";\n";
9186       pr "  }\n";
9187       pr "  ";
9188       generate_java_prototype ~privat:true ~native:true name style;
9189       pr "\n";
9190       pr "\n";
9191   ) all_functions;
9192
9193   pr "}\n"
9194
9195 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9196 and generate_java_call_args ~handle args =
9197   pr "(%s" handle;
9198   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9199   pr ")"
9200
9201 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9202     ?(semicolon=true) name style =
9203   if privat then pr "private ";
9204   if public then pr "public ";
9205   if native then pr "native ";
9206
9207   (* return type *)
9208   (match fst style with
9209    | RErr -> pr "void ";
9210    | RInt _ -> pr "int ";
9211    | RInt64 _ -> pr "long ";
9212    | RBool _ -> pr "boolean ";
9213    | RConstString _ | RConstOptString _ | RString _
9214    | RBufferOut _ -> pr "String ";
9215    | RStringList _ -> pr "String[] ";
9216    | RStruct (_, typ) ->
9217        let name = java_name_of_struct typ in
9218        pr "%s " name;
9219    | RStructList (_, typ) ->
9220        let name = java_name_of_struct typ in
9221        pr "%s[] " name;
9222    | RHashtable _ -> pr "HashMap<String,String> ";
9223   );
9224
9225   if native then pr "_%s " name else pr "%s " name;
9226   pr "(";
9227   let needs_comma = ref false in
9228   if native then (
9229     pr "long g";
9230     needs_comma := true
9231   );
9232
9233   (* args *)
9234   List.iter (
9235     fun arg ->
9236       if !needs_comma then pr ", ";
9237       needs_comma := true;
9238
9239       match arg with
9240       | Pathname n
9241       | Device n | Dev_or_Path n
9242       | String n
9243       | OptString n
9244       | FileIn n
9245       | FileOut n ->
9246           pr "String %s" n
9247       | StringList n | DeviceList n ->
9248           pr "String[] %s" n
9249       | Bool n ->
9250           pr "boolean %s" n
9251       | Int n ->
9252           pr "int %s" n
9253       | Int64 n ->
9254           pr "long %s" n
9255   ) (snd style);
9256
9257   pr ")\n";
9258   pr "    throws LibGuestFSException";
9259   if semicolon then pr ";"
9260
9261 and generate_java_struct jtyp cols =
9262   generate_header CStyle LGPLv2;
9263
9264   pr "\
9265 package com.redhat.et.libguestfs;
9266
9267 /**
9268  * Libguestfs %s structure.
9269  *
9270  * @author rjones
9271  * @see GuestFS
9272  */
9273 public class %s {
9274 " jtyp jtyp;
9275
9276   List.iter (
9277     function
9278     | name, FString
9279     | name, FUUID
9280     | name, FBuffer -> pr "  public String %s;\n" name
9281     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9282     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9283     | name, FChar -> pr "  public char %s;\n" name
9284     | name, FOptPercent ->
9285         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9286         pr "  public float %s;\n" name
9287   ) cols;
9288
9289   pr "}\n"
9290
9291 and generate_java_c () =
9292   generate_header CStyle LGPLv2;
9293
9294   pr "\
9295 #include <stdio.h>
9296 #include <stdlib.h>
9297 #include <string.h>
9298
9299 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9300 #include \"guestfs.h\"
9301
9302 /* Note that this function returns.  The exception is not thrown
9303  * until after the wrapper function returns.
9304  */
9305 static void
9306 throw_exception (JNIEnv *env, const char *msg)
9307 {
9308   jclass cl;
9309   cl = (*env)->FindClass (env,
9310                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9311   (*env)->ThrowNew (env, cl, msg);
9312 }
9313
9314 JNIEXPORT jlong JNICALL
9315 Java_com_redhat_et_libguestfs_GuestFS__1create
9316   (JNIEnv *env, jobject obj)
9317 {
9318   guestfs_h *g;
9319
9320   g = guestfs_create ();
9321   if (g == NULL) {
9322     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9323     return 0;
9324   }
9325   guestfs_set_error_handler (g, NULL, NULL);
9326   return (jlong) (long) g;
9327 }
9328
9329 JNIEXPORT void JNICALL
9330 Java_com_redhat_et_libguestfs_GuestFS__1close
9331   (JNIEnv *env, jobject obj, jlong jg)
9332 {
9333   guestfs_h *g = (guestfs_h *) (long) jg;
9334   guestfs_close (g);
9335 }
9336
9337 ";
9338
9339   List.iter (
9340     fun (name, style, _, _, _, _, _) ->
9341       pr "JNIEXPORT ";
9342       (match fst style with
9343        | RErr -> pr "void ";
9344        | RInt _ -> pr "jint ";
9345        | RInt64 _ -> pr "jlong ";
9346        | RBool _ -> pr "jboolean ";
9347        | RConstString _ | RConstOptString _ | RString _
9348        | RBufferOut _ -> pr "jstring ";
9349        | RStruct _ | RHashtable _ ->
9350            pr "jobject ";
9351        | RStringList _ | RStructList _ ->
9352            pr "jobjectArray ";
9353       );
9354       pr "JNICALL\n";
9355       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9356       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9357       pr "\n";
9358       pr "  (JNIEnv *env, jobject obj, jlong jg";
9359       List.iter (
9360         function
9361         | Pathname n
9362         | Device n | Dev_or_Path n
9363         | String n
9364         | OptString n
9365         | FileIn n
9366         | FileOut n ->
9367             pr ", jstring j%s" n
9368         | StringList n | DeviceList n ->
9369             pr ", jobjectArray j%s" n
9370         | Bool n ->
9371             pr ", jboolean j%s" n
9372         | Int n ->
9373             pr ", jint j%s" n
9374         | Int64 n ->
9375             pr ", jlong j%s" n
9376       ) (snd style);
9377       pr ")\n";
9378       pr "{\n";
9379       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9380       let error_code, no_ret =
9381         match fst style with
9382         | RErr -> pr "  int r;\n"; "-1", ""
9383         | RBool _
9384         | RInt _ -> pr "  int r;\n"; "-1", "0"
9385         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9386         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9387         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9388         | RString _ ->
9389             pr "  jstring jr;\n";
9390             pr "  char *r;\n"; "NULL", "NULL"
9391         | RStringList _ ->
9392             pr "  jobjectArray jr;\n";
9393             pr "  int r_len;\n";
9394             pr "  jclass cl;\n";
9395             pr "  jstring jstr;\n";
9396             pr "  char **r;\n"; "NULL", "NULL"
9397         | RStruct (_, typ) ->
9398             pr "  jobject jr;\n";
9399             pr "  jclass cl;\n";
9400             pr "  jfieldID fl;\n";
9401             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9402         | RStructList (_, typ) ->
9403             pr "  jobjectArray jr;\n";
9404             pr "  jclass cl;\n";
9405             pr "  jfieldID fl;\n";
9406             pr "  jobject jfl;\n";
9407             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9408         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9409         | RBufferOut _ ->
9410             pr "  jstring jr;\n";
9411             pr "  char *r;\n";
9412             pr "  size_t size;\n";
9413             "NULL", "NULL" in
9414       List.iter (
9415         function
9416         | Pathname n
9417         | Device n | Dev_or_Path n
9418         | String n
9419         | OptString n
9420         | FileIn n
9421         | FileOut n ->
9422             pr "  const char *%s;\n" n
9423         | StringList n | DeviceList n ->
9424             pr "  int %s_len;\n" n;
9425             pr "  const char **%s;\n" n
9426         | Bool n
9427         | Int n ->
9428             pr "  int %s;\n" n
9429         | Int64 n ->
9430             pr "  int64_t %s;\n" n
9431       ) (snd style);
9432
9433       let needs_i =
9434         (match fst style with
9435          | RStringList _ | RStructList _ -> true
9436          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9437          | RConstOptString _
9438          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9439           List.exists (function
9440                        | StringList _ -> true
9441                        | DeviceList _ -> true
9442                        | _ -> false) (snd style) in
9443       if needs_i then
9444         pr "  int i;\n";
9445
9446       pr "\n";
9447
9448       (* Get the parameters. *)
9449       List.iter (
9450         function
9451         | Pathname n
9452         | Device n | Dev_or_Path n
9453         | String n
9454         | FileIn n
9455         | FileOut n ->
9456             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9457         | OptString n ->
9458             (* This is completely undocumented, but Java null becomes
9459              * a NULL parameter.
9460              *)
9461             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9462         | StringList n | DeviceList n ->
9463             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9464             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9465             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9466             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9467               n;
9468             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9469             pr "  }\n";
9470             pr "  %s[%s_len] = NULL;\n" n n;
9471         | Bool n
9472         | Int n
9473         | Int64 n ->
9474             pr "  %s = j%s;\n" n n
9475       ) (snd style);
9476
9477       (* Make the call. *)
9478       pr "  r = guestfs_%s " name;
9479       generate_c_call_args ~handle:"g" style;
9480       pr ";\n";
9481
9482       (* Release the parameters. *)
9483       List.iter (
9484         function
9485         | Pathname n
9486         | Device n | Dev_or_Path n
9487         | String n
9488         | FileIn n
9489         | FileOut n ->
9490             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9491         | OptString n ->
9492             pr "  if (j%s)\n" n;
9493             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9494         | StringList n | DeviceList n ->
9495             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9496             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9497               n;
9498             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9499             pr "  }\n";
9500             pr "  free (%s);\n" n
9501         | Bool n
9502         | Int n
9503         | Int64 n -> ()
9504       ) (snd style);
9505
9506       (* Check for errors. *)
9507       pr "  if (r == %s) {\n" error_code;
9508       pr "    throw_exception (env, guestfs_last_error (g));\n";
9509       pr "    return %s;\n" no_ret;
9510       pr "  }\n";
9511
9512       (* Return value. *)
9513       (match fst style with
9514        | RErr -> ()
9515        | RInt _ -> pr "  return (jint) r;\n"
9516        | RBool _ -> pr "  return (jboolean) r;\n"
9517        | RInt64 _ -> pr "  return (jlong) r;\n"
9518        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9519        | RConstOptString _ ->
9520            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9521        | RString _ ->
9522            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9523            pr "  free (r);\n";
9524            pr "  return jr;\n"
9525        | RStringList _ ->
9526            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9527            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9528            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9529            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9530            pr "  for (i = 0; i < r_len; ++i) {\n";
9531            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9532            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9533            pr "    free (r[i]);\n";
9534            pr "  }\n";
9535            pr "  free (r);\n";
9536            pr "  return jr;\n"
9537        | RStruct (_, typ) ->
9538            let jtyp = java_name_of_struct typ in
9539            let cols = cols_of_struct typ in
9540            generate_java_struct_return typ jtyp cols
9541        | RStructList (_, typ) ->
9542            let jtyp = java_name_of_struct typ in
9543            let cols = cols_of_struct typ in
9544            generate_java_struct_list_return typ jtyp cols
9545        | RHashtable _ ->
9546            (* XXX *)
9547            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9548            pr "  return NULL;\n"
9549        | RBufferOut _ ->
9550            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9551            pr "  free (r);\n";
9552            pr "  return jr;\n"
9553       );
9554
9555       pr "}\n";
9556       pr "\n"
9557   ) all_functions
9558
9559 and generate_java_struct_return typ jtyp cols =
9560   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9561   pr "  jr = (*env)->AllocObject (env, cl);\n";
9562   List.iter (
9563     function
9564     | name, FString ->
9565         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9566         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9567     | name, FUUID ->
9568         pr "  {\n";
9569         pr "    char s[33];\n";
9570         pr "    memcpy (s, r->%s, 32);\n" name;
9571         pr "    s[32] = 0;\n";
9572         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9573         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9574         pr "  }\n";
9575     | name, FBuffer ->
9576         pr "  {\n";
9577         pr "    int len = r->%s_len;\n" name;
9578         pr "    char s[len+1];\n";
9579         pr "    memcpy (s, r->%s, len);\n" name;
9580         pr "    s[len] = 0;\n";
9581         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9582         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9583         pr "  }\n";
9584     | name, (FBytes|FUInt64|FInt64) ->
9585         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9586         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9587     | name, (FUInt32|FInt32) ->
9588         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9589         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9590     | name, FOptPercent ->
9591         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9592         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9593     | name, FChar ->
9594         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9595         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9596   ) cols;
9597   pr "  free (r);\n";
9598   pr "  return jr;\n"
9599
9600 and generate_java_struct_list_return typ jtyp cols =
9601   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9602   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9603   pr "  for (i = 0; i < r->len; ++i) {\n";
9604   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9605   List.iter (
9606     function
9607     | name, FString ->
9608         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9609         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9610     | name, FUUID ->
9611         pr "    {\n";
9612         pr "      char s[33];\n";
9613         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9614         pr "      s[32] = 0;\n";
9615         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9616         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9617         pr "    }\n";
9618     | name, FBuffer ->
9619         pr "    {\n";
9620         pr "      int len = r->val[i].%s_len;\n" name;
9621         pr "      char s[len+1];\n";
9622         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9623         pr "      s[len] = 0;\n";
9624         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9625         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9626         pr "    }\n";
9627     | name, (FBytes|FUInt64|FInt64) ->
9628         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9629         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9630     | name, (FUInt32|FInt32) ->
9631         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9632         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9633     | name, FOptPercent ->
9634         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9635         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9636     | name, FChar ->
9637         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9638         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9639   ) cols;
9640   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9641   pr "  }\n";
9642   pr "  guestfs_free_%s_list (r);\n" typ;
9643   pr "  return jr;\n"
9644
9645 and generate_java_makefile_inc () =
9646   generate_header HashStyle GPLv2;
9647
9648   pr "java_built_sources = \\\n";
9649   List.iter (
9650     fun (typ, jtyp) ->
9651         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9652   ) java_structs;
9653   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9654
9655 and generate_haskell_hs () =
9656   generate_header HaskellStyle LGPLv2;
9657
9658   (* XXX We only know how to generate partial FFI for Haskell
9659    * at the moment.  Please help out!
9660    *)
9661   let can_generate style =
9662     match style with
9663     | RErr, _
9664     | RInt _, _
9665     | RInt64 _, _ -> true
9666     | RBool _, _
9667     | RConstString _, _
9668     | RConstOptString _, _
9669     | RString _, _
9670     | RStringList _, _
9671     | RStruct _, _
9672     | RStructList _, _
9673     | RHashtable _, _
9674     | RBufferOut _, _ -> false in
9675
9676   pr "\
9677 {-# INCLUDE <guestfs.h> #-}
9678 {-# LANGUAGE ForeignFunctionInterface #-}
9679
9680 module Guestfs (
9681   create";
9682
9683   (* List out the names of the actions we want to export. *)
9684   List.iter (
9685     fun (name, style, _, _, _, _, _) ->
9686       if can_generate style then pr ",\n  %s" name
9687   ) all_functions;
9688
9689   pr "
9690   ) where
9691
9692 -- Unfortunately some symbols duplicate ones already present
9693 -- in Prelude.  We don't know which, so we hard-code a list
9694 -- here.
9695 import Prelude hiding (truncate)
9696
9697 import Foreign
9698 import Foreign.C
9699 import Foreign.C.Types
9700 import IO
9701 import Control.Exception
9702 import Data.Typeable
9703
9704 data GuestfsS = GuestfsS            -- represents the opaque C struct
9705 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9706 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9707
9708 -- XXX define properly later XXX
9709 data PV = PV
9710 data VG = VG
9711 data LV = LV
9712 data IntBool = IntBool
9713 data Stat = Stat
9714 data StatVFS = StatVFS
9715 data Hashtable = Hashtable
9716
9717 foreign import ccall unsafe \"guestfs_create\" c_create
9718   :: IO GuestfsP
9719 foreign import ccall unsafe \"&guestfs_close\" c_close
9720   :: FunPtr (GuestfsP -> IO ())
9721 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9722   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9723
9724 create :: IO GuestfsH
9725 create = do
9726   p <- c_create
9727   c_set_error_handler p nullPtr nullPtr
9728   h <- newForeignPtr c_close p
9729   return h
9730
9731 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9732   :: GuestfsP -> IO CString
9733
9734 -- last_error :: GuestfsH -> IO (Maybe String)
9735 -- last_error h = do
9736 --   str <- withForeignPtr h (\\p -> c_last_error p)
9737 --   maybePeek peekCString str
9738
9739 last_error :: GuestfsH -> IO (String)
9740 last_error h = do
9741   str <- withForeignPtr h (\\p -> c_last_error p)
9742   if (str == nullPtr)
9743     then return \"no error\"
9744     else peekCString str
9745
9746 ";
9747
9748   (* Generate wrappers for each foreign function. *)
9749   List.iter (
9750     fun (name, style, _, _, _, _, _) ->
9751       if can_generate style then (
9752         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9753         pr "  :: ";
9754         generate_haskell_prototype ~handle:"GuestfsP" style;
9755         pr "\n";
9756         pr "\n";
9757         pr "%s :: " name;
9758         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9759         pr "\n";
9760         pr "%s %s = do\n" name
9761           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9762         pr "  r <- ";
9763         (* Convert pointer arguments using with* functions. *)
9764         List.iter (
9765           function
9766           | FileIn n
9767           | FileOut n
9768           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9769           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9770           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9771           | Bool _ | Int _ | Int64 _ -> ()
9772         ) (snd style);
9773         (* Convert integer arguments. *)
9774         let args =
9775           List.map (
9776             function
9777             | Bool n -> sprintf "(fromBool %s)" n
9778             | Int n -> sprintf "(fromIntegral %s)" n
9779             | Int64 n -> sprintf "(fromIntegral %s)" n
9780             | FileIn n | FileOut n
9781             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9782           ) (snd style) in
9783         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9784           (String.concat " " ("p" :: args));
9785         (match fst style with
9786          | RErr | RInt _ | RInt64 _ | RBool _ ->
9787              pr "  if (r == -1)\n";
9788              pr "    then do\n";
9789              pr "      err <- last_error h\n";
9790              pr "      fail err\n";
9791          | RConstString _ | RConstOptString _ | RString _
9792          | RStringList _ | RStruct _
9793          | RStructList _ | RHashtable _ | RBufferOut _ ->
9794              pr "  if (r == nullPtr)\n";
9795              pr "    then do\n";
9796              pr "      err <- last_error h\n";
9797              pr "      fail err\n";
9798         );
9799         (match fst style with
9800          | RErr ->
9801              pr "    else return ()\n"
9802          | RInt _ ->
9803              pr "    else return (fromIntegral r)\n"
9804          | RInt64 _ ->
9805              pr "    else return (fromIntegral r)\n"
9806          | RBool _ ->
9807              pr "    else return (toBool r)\n"
9808          | RConstString _
9809          | RConstOptString _
9810          | RString _
9811          | RStringList _
9812          | RStruct _
9813          | RStructList _
9814          | RHashtable _
9815          | RBufferOut _ ->
9816              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9817         );
9818         pr "\n";
9819       )
9820   ) all_functions
9821
9822 and generate_haskell_prototype ~handle ?(hs = false) style =
9823   pr "%s -> " handle;
9824   let string = if hs then "String" else "CString" in
9825   let int = if hs then "Int" else "CInt" in
9826   let bool = if hs then "Bool" else "CInt" in
9827   let int64 = if hs then "Integer" else "Int64" in
9828   List.iter (
9829     fun arg ->
9830       (match arg with
9831        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9832        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9833        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9834        | Bool _ -> pr "%s" bool
9835        | Int _ -> pr "%s" int
9836        | Int64 _ -> pr "%s" int
9837        | FileIn _ -> pr "%s" string
9838        | FileOut _ -> pr "%s" string
9839       );
9840       pr " -> ";
9841   ) (snd style);
9842   pr "IO (";
9843   (match fst style with
9844    | RErr -> if not hs then pr "CInt"
9845    | RInt _ -> pr "%s" int
9846    | RInt64 _ -> pr "%s" int64
9847    | RBool _ -> pr "%s" bool
9848    | RConstString _ -> pr "%s" string
9849    | RConstOptString _ -> pr "Maybe %s" string
9850    | RString _ -> pr "%s" string
9851    | RStringList _ -> pr "[%s]" string
9852    | RStruct (_, typ) ->
9853        let name = java_name_of_struct typ in
9854        pr "%s" name
9855    | RStructList (_, typ) ->
9856        let name = java_name_of_struct typ in
9857        pr "[%s]" name
9858    | RHashtable _ -> pr "Hashtable"
9859    | RBufferOut _ -> pr "%s" string
9860   );
9861   pr ")"
9862
9863 and generate_bindtests () =
9864   generate_header CStyle LGPLv2;
9865
9866   pr "\
9867 #include <stdio.h>
9868 #include <stdlib.h>
9869 #include <inttypes.h>
9870 #include <string.h>
9871
9872 #include \"guestfs.h\"
9873 #include \"guestfs-internal.h\"
9874 #include \"guestfs-internal-actions.h\"
9875 #include \"guestfs_protocol.h\"
9876
9877 #define error guestfs_error
9878 #define safe_calloc guestfs_safe_calloc
9879 #define safe_malloc guestfs_safe_malloc
9880
9881 static void
9882 print_strings (char *const *argv)
9883 {
9884   int argc;
9885
9886   printf (\"[\");
9887   for (argc = 0; argv[argc] != NULL; ++argc) {
9888     if (argc > 0) printf (\", \");
9889     printf (\"\\\"%%s\\\"\", argv[argc]);
9890   }
9891   printf (\"]\\n\");
9892 }
9893
9894 /* The test0 function prints its parameters to stdout. */
9895 ";
9896
9897   let test0, tests =
9898     match test_functions with
9899     | [] -> assert false
9900     | test0 :: tests -> test0, tests in
9901
9902   let () =
9903     let (name, style, _, _, _, _, _) = test0 in
9904     generate_prototype ~extern:false ~semicolon:false ~newline:true
9905       ~handle:"g" ~prefix:"guestfs__" name style;
9906     pr "{\n";
9907     List.iter (
9908       function
9909       | Pathname n
9910       | Device n | Dev_or_Path n
9911       | String n
9912       | FileIn n
9913       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9914       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9915       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9916       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9917       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9918       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9919     ) (snd style);
9920     pr "  /* Java changes stdout line buffering so we need this: */\n";
9921     pr "  fflush (stdout);\n";
9922     pr "  return 0;\n";
9923     pr "}\n";
9924     pr "\n" in
9925
9926   List.iter (
9927     fun (name, style, _, _, _, _, _) ->
9928       if String.sub name (String.length name - 3) 3 <> "err" then (
9929         pr "/* Test normal return. */\n";
9930         generate_prototype ~extern:false ~semicolon:false ~newline:true
9931           ~handle:"g" ~prefix:"guestfs__" name style;
9932         pr "{\n";
9933         (match fst style with
9934          | RErr ->
9935              pr "  return 0;\n"
9936          | RInt _ ->
9937              pr "  int r;\n";
9938              pr "  sscanf (val, \"%%d\", &r);\n";
9939              pr "  return r;\n"
9940          | RInt64 _ ->
9941              pr "  int64_t r;\n";
9942              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9943              pr "  return r;\n"
9944          | RBool _ ->
9945              pr "  return STREQ (val, \"true\");\n"
9946          | RConstString _
9947          | RConstOptString _ ->
9948              (* Can't return the input string here.  Return a static
9949               * string so we ensure we get a segfault if the caller
9950               * tries to free it.
9951               *)
9952              pr "  return \"static string\";\n"
9953          | RString _ ->
9954              pr "  return strdup (val);\n"
9955          | RStringList _ ->
9956              pr "  char **strs;\n";
9957              pr "  int n, i;\n";
9958              pr "  sscanf (val, \"%%d\", &n);\n";
9959              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9960              pr "  for (i = 0; i < n; ++i) {\n";
9961              pr "    strs[i] = safe_malloc (g, 16);\n";
9962              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9963              pr "  }\n";
9964              pr "  strs[n] = NULL;\n";
9965              pr "  return strs;\n"
9966          | RStruct (_, typ) ->
9967              pr "  struct guestfs_%s *r;\n" typ;
9968              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9969              pr "  return r;\n"
9970          | RStructList (_, typ) ->
9971              pr "  struct guestfs_%s_list *r;\n" typ;
9972              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9973              pr "  sscanf (val, \"%%d\", &r->len);\n";
9974              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9975              pr "  return r;\n"
9976          | RHashtable _ ->
9977              pr "  char **strs;\n";
9978              pr "  int n, i;\n";
9979              pr "  sscanf (val, \"%%d\", &n);\n";
9980              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9981              pr "  for (i = 0; i < n; ++i) {\n";
9982              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9983              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9984              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9985              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9986              pr "  }\n";
9987              pr "  strs[n*2] = NULL;\n";
9988              pr "  return strs;\n"
9989          | RBufferOut _ ->
9990              pr "  return strdup (val);\n"
9991         );
9992         pr "}\n";
9993         pr "\n"
9994       ) else (
9995         pr "/* Test error return. */\n";
9996         generate_prototype ~extern:false ~semicolon:false ~newline:true
9997           ~handle:"g" ~prefix:"guestfs__" name style;
9998         pr "{\n";
9999         pr "  error (g, \"error\");\n";
10000         (match fst style with
10001          | RErr | RInt _ | RInt64 _ | RBool _ ->
10002              pr "  return -1;\n"
10003          | RConstString _ | RConstOptString _
10004          | RString _ | RStringList _ | RStruct _
10005          | RStructList _
10006          | RHashtable _
10007          | RBufferOut _ ->
10008              pr "  return NULL;\n"
10009         );
10010         pr "}\n";
10011         pr "\n"
10012       )
10013   ) tests
10014
10015 and generate_ocaml_bindtests () =
10016   generate_header OCamlStyle GPLv2;
10017
10018   pr "\
10019 let () =
10020   let g = Guestfs.create () in
10021 ";
10022
10023   let mkargs args =
10024     String.concat " " (
10025       List.map (
10026         function
10027         | CallString s -> "\"" ^ s ^ "\""
10028         | CallOptString None -> "None"
10029         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10030         | CallStringList xs ->
10031             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10032         | CallInt i when i >= 0 -> string_of_int i
10033         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10034         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10035         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10036         | CallBool b -> string_of_bool b
10037       ) args
10038     )
10039   in
10040
10041   generate_lang_bindtests (
10042     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10043   );
10044
10045   pr "print_endline \"EOF\"\n"
10046
10047 and generate_perl_bindtests () =
10048   pr "#!/usr/bin/perl -w\n";
10049   generate_header HashStyle GPLv2;
10050
10051   pr "\
10052 use strict;
10053
10054 use Sys::Guestfs;
10055
10056 my $g = Sys::Guestfs->new ();
10057 ";
10058
10059   let mkargs args =
10060     String.concat ", " (
10061       List.map (
10062         function
10063         | CallString s -> "\"" ^ s ^ "\""
10064         | CallOptString None -> "undef"
10065         | CallOptString (Some s) -> sprintf "\"%s\"" s
10066         | CallStringList xs ->
10067             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10068         | CallInt i -> string_of_int i
10069         | CallInt64 i -> Int64.to_string i
10070         | CallBool b -> if b then "1" else "0"
10071       ) args
10072     )
10073   in
10074
10075   generate_lang_bindtests (
10076     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10077   );
10078
10079   pr "print \"EOF\\n\"\n"
10080
10081 and generate_python_bindtests () =
10082   generate_header HashStyle GPLv2;
10083
10084   pr "\
10085 import guestfs
10086
10087 g = guestfs.GuestFS ()
10088 ";
10089
10090   let mkargs args =
10091     String.concat ", " (
10092       List.map (
10093         function
10094         | CallString s -> "\"" ^ s ^ "\""
10095         | CallOptString None -> "None"
10096         | CallOptString (Some s) -> sprintf "\"%s\"" s
10097         | CallStringList xs ->
10098             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10099         | CallInt i -> string_of_int i
10100         | CallInt64 i -> Int64.to_string i
10101         | CallBool b -> if b then "1" else "0"
10102       ) args
10103     )
10104   in
10105
10106   generate_lang_bindtests (
10107     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10108   );
10109
10110   pr "print \"EOF\"\n"
10111
10112 and generate_ruby_bindtests () =
10113   generate_header HashStyle GPLv2;
10114
10115   pr "\
10116 require 'guestfs'
10117
10118 g = Guestfs::create()
10119 ";
10120
10121   let mkargs args =
10122     String.concat ", " (
10123       List.map (
10124         function
10125         | CallString s -> "\"" ^ s ^ "\""
10126         | CallOptString None -> "nil"
10127         | CallOptString (Some s) -> sprintf "\"%s\"" s
10128         | CallStringList xs ->
10129             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10130         | CallInt i -> string_of_int i
10131         | CallInt64 i -> Int64.to_string i
10132         | CallBool b -> string_of_bool b
10133       ) args
10134     )
10135   in
10136
10137   generate_lang_bindtests (
10138     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10139   );
10140
10141   pr "print \"EOF\\n\"\n"
10142
10143 and generate_java_bindtests () =
10144   generate_header CStyle GPLv2;
10145
10146   pr "\
10147 import com.redhat.et.libguestfs.*;
10148
10149 public class Bindtests {
10150     public static void main (String[] argv)
10151     {
10152         try {
10153             GuestFS g = new GuestFS ();
10154 ";
10155
10156   let mkargs args =
10157     String.concat ", " (
10158       List.map (
10159         function
10160         | CallString s -> "\"" ^ s ^ "\""
10161         | CallOptString None -> "null"
10162         | CallOptString (Some s) -> sprintf "\"%s\"" s
10163         | CallStringList xs ->
10164             "new String[]{" ^
10165               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10166         | CallInt i -> string_of_int i
10167         | CallInt64 i -> Int64.to_string i
10168         | CallBool b -> string_of_bool b
10169       ) args
10170     )
10171   in
10172
10173   generate_lang_bindtests (
10174     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10175   );
10176
10177   pr "
10178             System.out.println (\"EOF\");
10179         }
10180         catch (Exception exn) {
10181             System.err.println (exn);
10182             System.exit (1);
10183         }
10184     }
10185 }
10186 "
10187
10188 and generate_haskell_bindtests () =
10189   generate_header HaskellStyle GPLv2;
10190
10191   pr "\
10192 module Bindtests where
10193 import qualified Guestfs
10194
10195 main = do
10196   g <- Guestfs.create
10197 ";
10198
10199   let mkargs args =
10200     String.concat " " (
10201       List.map (
10202         function
10203         | CallString s -> "\"" ^ s ^ "\""
10204         | CallOptString None -> "Nothing"
10205         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10206         | CallStringList xs ->
10207             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10208         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10209         | CallInt i -> string_of_int i
10210         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10211         | CallInt64 i -> Int64.to_string i
10212         | CallBool true -> "True"
10213         | CallBool false -> "False"
10214       ) args
10215     )
10216   in
10217
10218   generate_lang_bindtests (
10219     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10220   );
10221
10222   pr "  putStrLn \"EOF\"\n"
10223
10224 (* Language-independent bindings tests - we do it this way to
10225  * ensure there is parity in testing bindings across all languages.
10226  *)
10227 and generate_lang_bindtests call =
10228   call "test0" [CallString "abc"; CallOptString (Some "def");
10229                 CallStringList []; CallBool false;
10230                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10231   call "test0" [CallString "abc"; CallOptString None;
10232                 CallStringList []; CallBool false;
10233                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10234   call "test0" [CallString ""; CallOptString (Some "def");
10235                 CallStringList []; CallBool false;
10236                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10237   call "test0" [CallString ""; CallOptString (Some "");
10238                 CallStringList []; CallBool false;
10239                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10240   call "test0" [CallString "abc"; CallOptString (Some "def");
10241                 CallStringList ["1"]; CallBool false;
10242                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10243   call "test0" [CallString "abc"; CallOptString (Some "def");
10244                 CallStringList ["1"; "2"]; CallBool false;
10245                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10246   call "test0" [CallString "abc"; CallOptString (Some "def");
10247                 CallStringList ["1"]; CallBool true;
10248                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10249   call "test0" [CallString "abc"; CallOptString (Some "def");
10250                 CallStringList ["1"]; CallBool false;
10251                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10252   call "test0" [CallString "abc"; CallOptString (Some "def");
10253                 CallStringList ["1"]; CallBool false;
10254                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10255   call "test0" [CallString "abc"; CallOptString (Some "def");
10256                 CallStringList ["1"]; CallBool false;
10257                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10258   call "test0" [CallString "abc"; CallOptString (Some "def");
10259                 CallStringList ["1"]; CallBool false;
10260                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10261   call "test0" [CallString "abc"; CallOptString (Some "def");
10262                 CallStringList ["1"]; CallBool false;
10263                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10264   call "test0" [CallString "abc"; CallOptString (Some "def");
10265                 CallStringList ["1"]; CallBool false;
10266                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10267
10268 (* XXX Add here tests of the return and error functions. *)
10269
10270 (* This is used to generate the src/MAX_PROC_NR file which
10271  * contains the maximum procedure number, a surrogate for the
10272  * ABI version number.  See src/Makefile.am for the details.
10273  *)
10274 and generate_max_proc_nr () =
10275   let proc_nrs = List.map (
10276     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10277   ) daemon_functions in
10278
10279   let max_proc_nr = List.fold_left max 0 proc_nrs in
10280
10281   pr "%d\n" max_proc_nr
10282
10283 let output_to filename =
10284   let filename_new = filename ^ ".new" in
10285   chan := open_out filename_new;
10286   let close () =
10287     close_out !chan;
10288     chan := Pervasives.stdout;
10289
10290     (* Is the new file different from the current file? *)
10291     if Sys.file_exists filename && files_equal filename filename_new then
10292       unlink filename_new               (* same, so skip it *)
10293     else (
10294       (* different, overwrite old one *)
10295       (try chmod filename 0o644 with Unix_error _ -> ());
10296       rename filename_new filename;
10297       chmod filename 0o444;
10298       printf "written %s\n%!" filename;
10299     )
10300   in
10301   close
10302
10303 let perror msg = function
10304   | Unix_error (err, _, _) ->
10305       eprintf "%s: %s\n" msg (error_message err)
10306   | exn ->
10307       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10308
10309 (* Main program. *)
10310 let () =
10311   let lock_fd =
10312     try openfile "HACKING" [O_RDWR] 0
10313     with
10314     | Unix_error (ENOENT, _, _) ->
10315         eprintf "\
10316 You are probably running this from the wrong directory.
10317 Run it from the top source directory using the command
10318   src/generator.ml
10319 ";
10320         exit 1
10321     | exn ->
10322         perror "open: HACKING" exn;
10323         exit 1 in
10324
10325   (* Acquire a lock so parallel builds won't try to run the generator
10326    * twice at the same time.  Subsequent builds will wait for the first
10327    * one to finish.  Note the lock is released implicitly when the
10328    * program exits.
10329    *)
10330   (try lockf lock_fd F_LOCK 1
10331    with exn ->
10332      perror "lock: HACKING" exn;
10333      exit 1);
10334
10335   check_functions ();
10336
10337   let close = output_to "src/guestfs_protocol.x" in
10338   generate_xdr ();
10339   close ();
10340
10341   let close = output_to "src/guestfs-structs.h" in
10342   generate_structs_h ();
10343   close ();
10344
10345   let close = output_to "src/guestfs-actions.h" in
10346   generate_actions_h ();
10347   close ();
10348
10349   let close = output_to "src/guestfs-internal-actions.h" in
10350   generate_internal_actions_h ();
10351   close ();
10352
10353   let close = output_to "src/guestfs-actions.c" in
10354   generate_client_actions ();
10355   close ();
10356
10357   let close = output_to "daemon/actions.h" in
10358   generate_daemon_actions_h ();
10359   close ();
10360
10361   let close = output_to "daemon/stubs.c" in
10362   generate_daemon_actions ();
10363   close ();
10364
10365   let close = output_to "daemon/names.c" in
10366   generate_daemon_names ();
10367   close ();
10368
10369   let close = output_to "daemon/optgroups.c" in
10370   generate_daemon_optgroups_c ();
10371   close ();
10372
10373   let close = output_to "daemon/optgroups.h" in
10374   generate_daemon_optgroups_h ();
10375   close ();
10376
10377   let close = output_to "capitests/tests.c" in
10378   generate_tests ();
10379   close ();
10380
10381   let close = output_to "src/guestfs-bindtests.c" in
10382   generate_bindtests ();
10383   close ();
10384
10385   let close = output_to "fish/cmds.c" in
10386   generate_fish_cmds ();
10387   close ();
10388
10389   let close = output_to "fish/completion.c" in
10390   generate_fish_completion ();
10391   close ();
10392
10393   let close = output_to "guestfs-structs.pod" in
10394   generate_structs_pod ();
10395   close ();
10396
10397   let close = output_to "guestfs-actions.pod" in
10398   generate_actions_pod ();
10399   close ();
10400
10401   let close = output_to "guestfs-availability.pod" in
10402   generate_availability_pod ();
10403   close ();
10404
10405   let close = output_to "guestfish-actions.pod" in
10406   generate_fish_actions_pod ();
10407   close ();
10408
10409   let close = output_to "ocaml/guestfs.mli" in
10410   generate_ocaml_mli ();
10411   close ();
10412
10413   let close = output_to "ocaml/guestfs.ml" in
10414   generate_ocaml_ml ();
10415   close ();
10416
10417   let close = output_to "ocaml/guestfs_c_actions.c" in
10418   generate_ocaml_c ();
10419   close ();
10420
10421   let close = output_to "ocaml/bindtests.ml" in
10422   generate_ocaml_bindtests ();
10423   close ();
10424
10425   let close = output_to "perl/Guestfs.xs" in
10426   generate_perl_xs ();
10427   close ();
10428
10429   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10430   generate_perl_pm ();
10431   close ();
10432
10433   let close = output_to "perl/bindtests.pl" in
10434   generate_perl_bindtests ();
10435   close ();
10436
10437   let close = output_to "python/guestfs-py.c" in
10438   generate_python_c ();
10439   close ();
10440
10441   let close = output_to "python/guestfs.py" in
10442   generate_python_py ();
10443   close ();
10444
10445   let close = output_to "python/bindtests.py" in
10446   generate_python_bindtests ();
10447   close ();
10448
10449   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10450   generate_ruby_c ();
10451   close ();
10452
10453   let close = output_to "ruby/bindtests.rb" in
10454   generate_ruby_bindtests ();
10455   close ();
10456
10457   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10458   generate_java_java ();
10459   close ();
10460
10461   List.iter (
10462     fun (typ, jtyp) ->
10463       let cols = cols_of_struct typ in
10464       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10465       let close = output_to filename in
10466       generate_java_struct jtyp cols;
10467       close ();
10468   ) java_structs;
10469
10470   let close = output_to "java/Makefile.inc" in
10471   generate_java_makefile_inc ();
10472   close ();
10473
10474   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10475   generate_java_c ();
10476   close ();
10477
10478   let close = output_to "java/Bindtests.java" in
10479   generate_java_bindtests ();
10480   close ();
10481
10482   let close = output_to "haskell/Guestfs.hs" in
10483   generate_haskell_hs ();
10484   close ();
10485
10486   let close = output_to "haskell/Bindtests.hs" in
10487   generate_haskell_bindtests ();
10488   close ();
10489
10490   let close = output_to "src/MAX_PROC_NR" in
10491   generate_max_proc_nr ();
10492   close ();
10493
10494   (* Always generate this file last, and unconditionally.  It's used
10495    * by the Makefile to know when we must re-run the generator.
10496    *)
10497   let chan = open_out "src/stamp-generator" in
10498   fprintf chan "1\n";
10499   close_out chan