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