New API calls: truncate, truncate_size, mkdir_mode, utimens, lchown.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145   | Int64 of string     (* any 64 bit int *)
146     (* These are treated as filenames (simple string parameters) in
147      * the C API and bindings.  But in the RPC protocol, we transfer
148      * the actual file content up to or down from the daemon.
149      * FileIn: local machine -> daemon (in request)
150      * FileOut: daemon -> local machine (in reply)
151      * In guestfish (only), the special name "-" means read from
152      * stdin or write to stdout.
153      *)
154   | FileIn of string
155   | FileOut of string
156 (* Not implemented:
157     (* Opaque buffer which can contain arbitrary 8 bit data.
158      * In the C API, this is expressed as <char *, int> pair.
159      * Most other languages have a string type which can contain
160      * ASCII NUL.  We use whatever type is appropriate for each
161      * language.
162      * Buffers are limited by the total message size.  To transfer
163      * large blocks of data, use FileIn/FileOut parameters instead.
164      * To return an arbitrary buffer, use RBufferOut.
165      *)
166   | BufferIn of string
167 *)
168
169 type flags =
170   | ProtocolLimitWarning  (* display warning about protocol size limits *)
171   | DangerWillRobinson    (* flags particularly dangerous commands *)
172   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
173   | FishAction of string  (* call this function in guestfish *)
174   | NotInFish             (* do not export via guestfish *)
175   | NotInDocs             (* do not add this function to documentation *)
176   | DeprecatedBy of string (* function is deprecated, use .. instead *)
177
178 (* You can supply zero or as many tests as you want per API call.
179  *
180  * Note that the test environment has 3 block devices, of size 500MB,
181  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
182  * a fourth ISO block device with some known files on it (/dev/sdd).
183  *
184  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
185  * Number of cylinders was 63 for IDE emulated disks with precisely
186  * the same size.  How exactly this is calculated is a mystery.
187  *
188  * The ISO block device (/dev/sdd) comes from images/test.iso.
189  *
190  * To be able to run the tests in a reasonable amount of time,
191  * the virtual machine and block devices are reused between tests.
192  * So don't try testing kill_subprocess :-x
193  *
194  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
195  *
196  * Don't assume anything about the previous contents of the block
197  * devices.  Use 'Init*' to create some initial scenarios.
198  *
199  * You can add a prerequisite clause to any individual test.  This
200  * is a run-time check, which, if it fails, causes the test to be
201  * skipped.  Useful if testing a command which might not work on
202  * all variations of libguestfs builds.  A test that has prerequisite
203  * of 'Always' is run unconditionally.
204  *
205  * In addition, packagers can skip individual tests by setting the
206  * environment variables:     eg:
207  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
208  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
209  *)
210 type tests = (test_init * test_prereq * test) list
211 and test =
212     (* Run the command sequence and just expect nothing to fail. *)
213   | TestRun of seq
214
215     (* Run the command sequence and expect the output of the final
216      * command to be the string.
217      *)
218   | TestOutput of seq * string
219
220     (* Run the command sequence and expect the output of the final
221      * command to be the list of strings.
222      *)
223   | TestOutputList of seq * string list
224
225     (* Run the command sequence and expect the output of the final
226      * command to be the list of block devices (could be either
227      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
228      * character of each string).
229      *)
230   | TestOutputListOfDevices of seq * string list
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the integer.
234      *)
235   | TestOutputInt of seq * int
236
237     (* Run the command sequence and expect the output of the final
238      * command to be <op> <int>, eg. ">=", "1".
239      *)
240   | TestOutputIntOp of seq * string * int
241
242     (* Run the command sequence and expect the output of the final
243      * command to be a true value (!= 0 or != NULL).
244      *)
245   | TestOutputTrue of seq
246
247     (* Run the command sequence and expect the output of the final
248      * command to be a false value (== 0 or == NULL, but not an error).
249      *)
250   | TestOutputFalse of seq
251
252     (* Run the command sequence and expect the output of the final
253      * command to be a list of the given length (but don't care about
254      * content).
255      *)
256   | TestOutputLength of seq * int
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a buffer (RBufferOut), ie. string + size.
260      *)
261   | TestOutputBuffer of seq * string
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a structure.
265      *)
266   | TestOutputStruct of seq * test_field_compare list
267
268     (* Run the command sequence and expect the final command (only)
269      * to fail.
270      *)
271   | TestLastFail of seq
272
273 and test_field_compare =
274   | CompareWithInt of string * int
275   | CompareWithIntOp of string * string * int
276   | CompareWithString of string * string
277   | CompareFieldsIntEq of string * string
278   | CompareFieldsStrEq of string * string
279
280 (* Test prerequisites. *)
281 and test_prereq =
282     (* Test always runs. *)
283   | Always
284
285     (* Test is currently disabled - eg. it fails, or it tests some
286      * unimplemented feature.
287      *)
288   | Disabled
289
290     (* 'string' is some C code (a function body) that should return
291      * true or false.  The test will run if the code returns true.
292      *)
293   | If of string
294
295     (* As for 'If' but the test runs _unless_ the code returns true. *)
296   | Unless of string
297
298 (* Some initial scenarios for testing. *)
299 and test_init =
300     (* Do nothing, block devices could contain random stuff including
301      * LVM PVs, and some filesystems might be mounted.  This is usually
302      * a bad idea.
303      *)
304   | InitNone
305
306     (* Block devices are empty and no filesystems are mounted. *)
307   | InitEmpty
308
309     (* /dev/sda contains a single partition /dev/sda1, with random
310      * content.  /dev/sdb and /dev/sdc may have random content.
311      * No LVM.
312      *)
313   | InitPartition
314
315     (* /dev/sda contains a single partition /dev/sda1, which is formatted
316      * as ext2, empty [except for lost+found] and mounted on /.
317      * /dev/sdb and /dev/sdc may have random content.
318      * No LVM.
319      *)
320   | InitBasicFS
321
322     (* /dev/sda:
323      *   /dev/sda1 (is a PV):
324      *     /dev/VG/LV (size 8MB):
325      *       formatted as ext2, empty [except for lost+found], mounted on /
326      * /dev/sdb and /dev/sdc may have random content.
327      *)
328   | InitBasicFSonLVM
329
330     (* /dev/sdd (the ISO, see images/ directory in source)
331      * is mounted on /
332      *)
333   | InitISOFS
334
335 (* Sequence of commands for testing. *)
336 and seq = cmd list
337 and cmd = string list
338
339 (* Note about long descriptions: When referring to another
340  * action, use the format C<guestfs_other> (ie. the full name of
341  * the C function).  This will be replaced as appropriate in other
342  * language bindings.
343  *
344  * Apart from that, long descriptions are just perldoc paragraphs.
345  *)
346
347 (* Generate a random UUID (used in tests). *)
348 let uuidgen () =
349   let chan = Unix.open_process_in "uuidgen" in
350   let uuid = input_line chan in
351   (match Unix.close_process_in chan with
352    | Unix.WEXITED 0 -> ()
353    | Unix.WEXITED _ ->
354        failwith "uuidgen: process exited with non-zero status"
355    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
356        failwith "uuidgen: process signalled or stopped by signal"
357   );
358   uuid
359
360 (* These test functions are used in the language binding tests. *)
361
362 let test_all_args = [
363   String "str";
364   OptString "optstr";
365   StringList "strlist";
366   Bool "b";
367   Int "integer";
368   Int64 "integer64";
369   FileIn "filein";
370   FileOut "fileout";
371 ]
372
373 let test_all_rets = [
374   (* except for RErr, which is tested thoroughly elsewhere *)
375   "test0rint",         RInt "valout";
376   "test0rint64",       RInt64 "valout";
377   "test0rbool",        RBool "valout";
378   "test0rconststring", RConstString "valout";
379   "test0rconstoptstring", RConstOptString "valout";
380   "test0rstring",      RString "valout";
381   "test0rstringlist",  RStringList "valout";
382   "test0rstruct",      RStruct ("valout", "lvm_pv");
383   "test0rstructlist",  RStructList ("valout", "lvm_pv");
384   "test0rhashtable",   RHashtable "valout";
385 ]
386
387 let test_functions = [
388   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
389    [],
390    "internal test function - do not use",
391    "\
392 This is an internal test function which is used to test whether
393 the automatically generated bindings can handle every possible
394 parameter type correctly.
395
396 It echos the contents of each parameter to stdout.
397
398 You probably don't want to call this function.");
399 ] @ List.flatten (
400   List.map (
401     fun (name, ret) ->
402       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
403         [],
404         "internal test function - do not use",
405         "\
406 This is an internal test function which is used to test whether
407 the automatically generated bindings can handle every possible
408 return type correctly.
409
410 It converts string C<val> to the return type.
411
412 You probably don't want to call this function.");
413        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
414         [],
415         "internal test function - do not use",
416         "\
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
420
421 This function always returns an error.
422
423 You probably don't want to call this function.")]
424   ) test_all_rets
425 )
426
427 (* non_daemon_functions are any functions which don't get processed
428  * in the daemon, eg. functions for setting and getting local
429  * configuration values.
430  *)
431
432 let non_daemon_functions = test_functions @ [
433   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
434    [],
435    "launch the qemu subprocess",
436    "\
437 Internally libguestfs is implemented by running a virtual machine
438 using L<qemu(1)>.
439
440 You should call this after configuring the handle
441 (eg. adding drives) but before performing any actions.");
442
443   ("wait_ready", (RErr, []), -1, [NotInFish],
444    [],
445    "wait until the qemu subprocess launches (no op)",
446    "\
447 This function is a no op.
448
449 In versions of the API E<lt> 1.0.71 you had to call this function
450 just after calling C<guestfs_launch> to wait for the launch
451 to complete.  However this is no longer necessary because
452 C<guestfs_launch> now does the waiting.
453
454 If you see any calls to this function in code then you can just
455 remove them, unless you want to retain compatibility with older
456 versions of the API.");
457
458   ("kill_subprocess", (RErr, []), -1, [],
459    [],
460    "kill the qemu subprocess",
461    "\
462 This kills the qemu subprocess.  You should never need to call this.");
463
464   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
465    [],
466    "add an image to examine or modify",
467    "\
468 This function adds a virtual machine disk image C<filename> to the
469 guest.  The first time you call this function, the disk appears as IDE
470 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
471 so on.
472
473 You don't necessarily need to be root when using libguestfs.  However
474 you obviously do need sufficient permissions to access the filename
475 for whatever operations you want to perform (ie. read access if you
476 just want to read the image or write access if you want to modify the
477 image).
478
479 This is equivalent to the qemu parameter
480 C<-drive file=filename,cache=off,if=...>.
481 C<cache=off> is omitted in cases where it is not supported by
482 the underlying filesystem.
483
484 Note that this call checks for the existence of C<filename>.  This
485 stops you from specifying other types of drive which are supported
486 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
487 the general C<guestfs_config> call instead.");
488
489   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
490    [],
491    "add a CD-ROM disk image to examine",
492    "\
493 This function adds a virtual CD-ROM disk image to the guest.
494
495 This is equivalent to the qemu parameter C<-cdrom filename>.
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   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
503    [],
504    "add a drive in snapshot mode (read-only)",
505    "\
506 This adds a drive in snapshot mode, making it effectively
507 read-only.
508
509 Note that writes to the device are allowed, and will be seen for
510 the duration of the guestfs handle, but they are written
511 to a temporary file which is discarded as soon as the guestfs
512 handle is closed.  We don't currently have any method to enable
513 changes to be committed, although qemu can support this.
514
515 This is equivalent to the qemu parameter
516 C<-drive file=filename,snapshot=on,if=...>.
517
518 Note that this call checks for the existence of C<filename>.  This
519 stops you from specifying other types of drive which are supported
520 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
521 the general C<guestfs_config> call instead.");
522
523   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
524    [],
525    "add qemu parameters",
526    "\
527 This can be used to add arbitrary qemu command line parameters
528 of the form C<-param value>.  Actually it's not quite arbitrary - we
529 prevent you from setting some parameters which would interfere with
530 parameters that we use.
531
532 The first character of C<param> string must be a C<-> (dash).
533
534 C<value> can be NULL.");
535
536   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
537    [],
538    "set the qemu binary",
539    "\
540 Set the qemu binary that we will use.
541
542 The default is chosen when the library was compiled by the
543 configure script.
544
545 You can also override this by setting the C<LIBGUESTFS_QEMU>
546 environment variable.
547
548 Setting C<qemu> to C<NULL> restores the default qemu binary.");
549
550   ("get_qemu", (RConstString "qemu", []), -1, [],
551    [InitNone, Always, TestRun (
552       [["get_qemu"]])],
553    "get the qemu binary",
554    "\
555 Return the current qemu binary.
556
557 This is always non-NULL.  If it wasn't set already, then this will
558 return the default qemu binary name.");
559
560   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
561    [],
562    "set the search path",
563    "\
564 Set the path that libguestfs searches for kernel and initrd.img.
565
566 The default is C<$libdir/guestfs> unless overridden by setting
567 C<LIBGUESTFS_PATH> environment variable.
568
569 Setting C<path> to C<NULL> restores the default path.");
570
571   ("get_path", (RConstString "path", []), -1, [],
572    [InitNone, Always, TestRun (
573       [["get_path"]])],
574    "get the search path",
575    "\
576 Return the current search path.
577
578 This is always non-NULL.  If it wasn't set already, then this will
579 return the default path.");
580
581   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
582    [],
583    "add options to kernel command line",
584    "\
585 This function is used to add additional options to the
586 guest kernel command line.
587
588 The default is C<NULL> unless overridden by setting
589 C<LIBGUESTFS_APPEND> environment variable.
590
591 Setting C<append> to C<NULL> means I<no> additional options
592 are passed (libguestfs always adds a few of its own).");
593
594   ("get_append", (RConstOptString "append", []), -1, [],
595    (* This cannot be tested with the current framework.  The
596     * function can return NULL in normal operations, which the
597     * test framework interprets as an error.
598     *)
599    [],
600    "get the additional kernel options",
601    "\
602 Return the additional kernel options which are added to the
603 guest kernel command line.
604
605 If C<NULL> then no options are added.");
606
607   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
608    [],
609    "set autosync mode",
610    "\
611 If C<autosync> is true, this enables autosync.  Libguestfs will make a
612 best effort attempt to run C<guestfs_umount_all> followed by
613 C<guestfs_sync> when the handle is closed
614 (also if the program exits without closing handles).
615
616 This is disabled by default (except in guestfish where it is
617 enabled by default).");
618
619   ("get_autosync", (RBool "autosync", []), -1, [],
620    [InitNone, Always, TestRun (
621       [["get_autosync"]])],
622    "get autosync mode",
623    "\
624 Get the autosync flag.");
625
626   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
627    [],
628    "set verbose mode",
629    "\
630 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
631
632 Verbose messages are disabled unless the environment variable
633 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
634
635   ("get_verbose", (RBool "verbose", []), -1, [],
636    [],
637    "get verbose mode",
638    "\
639 This returns the verbose messages flag.");
640
641   ("is_ready", (RBool "ready", []), -1, [],
642    [InitNone, Always, TestOutputTrue (
643       [["is_ready"]])],
644    "is ready to accept commands",
645    "\
646 This returns true iff this handle is ready to accept commands
647 (in the C<READY> state).
648
649 For more information on states, see L<guestfs(3)>.");
650
651   ("is_config", (RBool "config", []), -1, [],
652    [InitNone, Always, TestOutputFalse (
653       [["is_config"]])],
654    "is in configuration state",
655    "\
656 This returns true iff this handle is being configured
657 (in the C<CONFIG> state).
658
659 For more information on states, see L<guestfs(3)>.");
660
661   ("is_launching", (RBool "launching", []), -1, [],
662    [InitNone, Always, TestOutputFalse (
663       [["is_launching"]])],
664    "is launching subprocess",
665    "\
666 This returns true iff this handle is launching the subprocess
667 (in the C<LAUNCHING> state).
668
669 For more information on states, see L<guestfs(3)>.");
670
671   ("is_busy", (RBool "busy", []), -1, [],
672    [InitNone, Always, TestOutputFalse (
673       [["is_busy"]])],
674    "is busy processing a command",
675    "\
676 This returns true iff this handle is busy processing a command
677 (in the C<BUSY> state).
678
679 For more information on states, see L<guestfs(3)>.");
680
681   ("get_state", (RInt "state", []), -1, [],
682    [],
683    "get the current state",
684    "\
685 This returns the current state as an opaque integer.  This is
686 only useful for printing debug and internal error messages.
687
688 For more information on states, see L<guestfs(3)>.");
689
690   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
691    [InitNone, Always, TestOutputInt (
692       [["set_memsize"; "500"];
693        ["get_memsize"]], 500)],
694    "set memory allocated to the qemu subprocess",
695    "\
696 This sets the memory size in megabytes allocated to the
697 qemu subprocess.  This only has any effect if called before
698 C<guestfs_launch>.
699
700 You can also change this by setting the environment
701 variable C<LIBGUESTFS_MEMSIZE> before the handle is
702 created.
703
704 For more information on the architecture of libguestfs,
705 see L<guestfs(3)>.");
706
707   ("get_memsize", (RInt "memsize", []), -1, [],
708    [InitNone, Always, TestOutputIntOp (
709       [["get_memsize"]], ">=", 256)],
710    "get memory allocated to the qemu subprocess",
711    "\
712 This gets the memory size in megabytes allocated to the
713 qemu subprocess.
714
715 If C<guestfs_set_memsize> was not called
716 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
717 then this returns the compiled-in default value for memsize.
718
719 For more information on the architecture of libguestfs,
720 see L<guestfs(3)>.");
721
722   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
723    [InitNone, Always, TestOutputIntOp (
724       [["get_pid"]], ">=", 1)],
725    "get PID of qemu subprocess",
726    "\
727 Return the process ID of the qemu subprocess.  If there is no
728 qemu subprocess, then this will return an error.
729
730 This is an internal call used for debugging and testing.");
731
732   ("version", (RStruct ("version", "version"), []), -1, [],
733    [InitNone, Always, TestOutputStruct (
734       [["version"]], [CompareWithInt ("major", 1)])],
735    "get the library version number",
736    "\
737 Return the libguestfs version number that the program is linked
738 against.
739
740 Note that because of dynamic linking this is not necessarily
741 the version of libguestfs that you compiled against.  You can
742 compile the program, and then at runtime dynamically link
743 against a completely different C<libguestfs.so> library.
744
745 This call was added in version C<1.0.58>.  In previous
746 versions of libguestfs there was no way to get the version
747 number.  From C code you can use ELF weak linking tricks to find out if
748 this symbol exists (if it doesn't, then it's an earlier version).
749
750 The call returns a structure with four elements.  The first
751 three (C<major>, C<minor> and C<release>) are numbers and
752 correspond to the usual version triplet.  The fourth element
753 (C<extra>) is a string and is normally empty, but may be
754 used for distro-specific information.
755
756 To construct the original version string:
757 C<$major.$minor.$release$extra>
758
759 I<Note:> Don't use this call to test for availability
760 of features.  Distro backports makes this unreliable.");
761
762   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
763    [InitNone, Always, TestOutputTrue (
764       [["set_selinux"; "true"];
765        ["get_selinux"]])],
766    "set SELinux enabled or disabled at appliance boot",
767    "\
768 This sets the selinux flag that is passed to the appliance
769 at boot time.  The default is C<selinux=0> (disabled).
770
771 Note that if SELinux is enabled, it is always in
772 Permissive mode (C<enforcing=0>).
773
774 For more information on the architecture of libguestfs,
775 see L<guestfs(3)>.");
776
777   ("get_selinux", (RBool "selinux", []), -1, [],
778    [],
779    "get SELinux enabled flag",
780    "\
781 This returns the current setting of the selinux flag which
782 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
783
784 For more information on the architecture of libguestfs,
785 see L<guestfs(3)>.");
786
787   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
788    [InitNone, Always, TestOutputFalse (
789       [["set_trace"; "false"];
790        ["get_trace"]])],
791    "enable or disable command traces",
792    "\
793 If the command trace flag is set to 1, then commands are
794 printed on stdout before they are executed in a format
795 which is very similar to the one used by guestfish.  In
796 other words, you can run a program with this enabled, and
797 you will get out a script which you can feed to guestfish
798 to perform the same set of actions.
799
800 If you want to trace C API calls into libguestfs (and
801 other libraries) then possibly a better way is to use
802 the external ltrace(1) command.
803
804 Command traces are disabled unless the environment variable
805 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
806
807   ("get_trace", (RBool "trace", []), -1, [],
808    [],
809    "get command trace enabled flag",
810    "\
811 Return the command trace flag.");
812
813   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
814    [InitNone, Always, TestOutputFalse (
815       [["set_direct"; "false"];
816        ["get_direct"]])],
817    "enable or disable direct appliance mode",
818    "\
819 If the direct appliance mode flag is enabled, then stdin and
820 stdout are passed directly through to the appliance once it
821 is launched.
822
823 One consequence of this is that log messages aren't caught
824 by the library and handled by C<guestfs_set_log_message_callback>,
825 but go straight to stdout.
826
827 You probably don't want to use this unless you know what you
828 are doing.
829
830 The default is disabled.");
831
832   ("get_direct", (RBool "direct", []), -1, [],
833    [],
834    "get direct appliance mode flag",
835    "\
836 Return the direct appliance mode flag.");
837
838 ]
839
840 (* daemon_functions are any functions which cause some action
841  * to take place in the daemon.
842  *)
843
844 let daemon_functions = [
845   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
846    [InitEmpty, Always, TestOutput (
847       [["sfdiskM"; "/dev/sda"; ","];
848        ["mkfs"; "ext2"; "/dev/sda1"];
849        ["mount"; "/dev/sda1"; "/"];
850        ["write_file"; "/new"; "new file contents"; "0"];
851        ["cat"; "/new"]], "new file contents")],
852    "mount a guest disk at a position in the filesystem",
853    "\
854 Mount a guest disk at a position in the filesystem.  Block devices
855 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
856 the guest.  If those block devices contain partitions, they will have
857 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
858 names can be used.
859
860 The rules are the same as for L<mount(2)>:  A filesystem must
861 first be mounted on C</> before others can be mounted.  Other
862 filesystems can only be mounted on directories which already
863 exist.
864
865 The mounted filesystem is writable, if we have sufficient permissions
866 on the underlying device.
867
868 The filesystem options C<sync> and C<noatime> are set with this
869 call, in order to improve reliability.");
870
871   ("sync", (RErr, []), 2, [],
872    [ InitEmpty, Always, TestRun [["sync"]]],
873    "sync disks, writes are flushed through to the disk image",
874    "\
875 This syncs the disk, so that any writes are flushed through to the
876 underlying disk image.
877
878 You should always call this if you have modified a disk image, before
879 closing the handle.");
880
881   ("touch", (RErr, [Pathname "path"]), 3, [],
882    [InitBasicFS, Always, TestOutputTrue (
883       [["touch"; "/new"];
884        ["exists"; "/new"]])],
885    "update file timestamps or create a new file",
886    "\
887 Touch acts like the L<touch(1)> command.  It can be used to
888 update the timestamps on a file, or, if the file does not exist,
889 to create a new zero-length file.");
890
891   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
892    [InitISOFS, Always, TestOutput (
893       [["cat"; "/known-2"]], "abcdef\n")],
894    "list the contents of a file",
895    "\
896 Return the contents of the file named C<path>.
897
898 Note that this function cannot correctly handle binary files
899 (specifically, files containing C<\\0> character which is treated
900 as end of string).  For those you need to use the C<guestfs_read_file>
901 or C<guestfs_download> functions which have a more complex interface.");
902
903   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
904    [], (* XXX Tricky to test because it depends on the exact format
905         * of the 'ls -l' command, which changes between F10 and F11.
906         *)
907    "list the files in a directory (long format)",
908    "\
909 List the files in C<directory> (relative to the root directory,
910 there is no cwd) in the format of 'ls -la'.
911
912 This command is mostly useful for interactive sessions.  It
913 is I<not> intended that you try to parse the output string.");
914
915   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
916    [InitBasicFS, Always, TestOutputList (
917       [["touch"; "/new"];
918        ["touch"; "/newer"];
919        ["touch"; "/newest"];
920        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
921    "list the files in a directory",
922    "\
923 List the files in C<directory> (relative to the root directory,
924 there is no cwd).  The '.' and '..' entries are not returned, but
925 hidden files are shown.
926
927 This command is mostly useful for interactive sessions.  Programs
928 should probably use C<guestfs_readdir> instead.");
929
930   ("list_devices", (RStringList "devices", []), 7, [],
931    [InitEmpty, Always, TestOutputListOfDevices (
932       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
933    "list the block devices",
934    "\
935 List all the block devices.
936
937 The full block device names are returned, eg. C</dev/sda>");
938
939   ("list_partitions", (RStringList "partitions", []), 8, [],
940    [InitBasicFS, Always, TestOutputListOfDevices (
941       [["list_partitions"]], ["/dev/sda1"]);
942     InitEmpty, Always, TestOutputListOfDevices (
943       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
944        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
945    "list the partitions",
946    "\
947 List all the partitions detected on all block devices.
948
949 The full partition device names are returned, eg. C</dev/sda1>
950
951 This does not return logical volumes.  For that you will need to
952 call C<guestfs_lvs>.");
953
954   ("pvs", (RStringList "physvols", []), 9, [],
955    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
956       [["pvs"]], ["/dev/sda1"]);
957     InitEmpty, Always, TestOutputListOfDevices (
958       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
959        ["pvcreate"; "/dev/sda1"];
960        ["pvcreate"; "/dev/sda2"];
961        ["pvcreate"; "/dev/sda3"];
962        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
963    "list the LVM physical volumes (PVs)",
964    "\
965 List all the physical volumes detected.  This is the equivalent
966 of the L<pvs(8)> command.
967
968 This returns a list of just the device names that contain
969 PVs (eg. C</dev/sda2>).
970
971 See also C<guestfs_pvs_full>.");
972
973   ("vgs", (RStringList "volgroups", []), 10, [],
974    [InitBasicFSonLVM, Always, TestOutputList (
975       [["vgs"]], ["VG"]);
976     InitEmpty, Always, TestOutputList (
977       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
978        ["pvcreate"; "/dev/sda1"];
979        ["pvcreate"; "/dev/sda2"];
980        ["pvcreate"; "/dev/sda3"];
981        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
982        ["vgcreate"; "VG2"; "/dev/sda3"];
983        ["vgs"]], ["VG1"; "VG2"])],
984    "list the LVM volume groups (VGs)",
985    "\
986 List all the volumes groups detected.  This is the equivalent
987 of the L<vgs(8)> command.
988
989 This returns a list of just the volume group names that were
990 detected (eg. C<VolGroup00>).
991
992 See also C<guestfs_vgs_full>.");
993
994   ("lvs", (RStringList "logvols", []), 11, [],
995    [InitBasicFSonLVM, Always, TestOutputList (
996       [["lvs"]], ["/dev/VG/LV"]);
997     InitEmpty, Always, TestOutputList (
998       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
999        ["pvcreate"; "/dev/sda1"];
1000        ["pvcreate"; "/dev/sda2"];
1001        ["pvcreate"; "/dev/sda3"];
1002        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1003        ["vgcreate"; "VG2"; "/dev/sda3"];
1004        ["lvcreate"; "LV1"; "VG1"; "50"];
1005        ["lvcreate"; "LV2"; "VG1"; "50"];
1006        ["lvcreate"; "LV3"; "VG2"; "50"];
1007        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1008    "list the LVM logical volumes (LVs)",
1009    "\
1010 List all the logical volumes detected.  This is the equivalent
1011 of the L<lvs(8)> command.
1012
1013 This returns a list of the logical volume device names
1014 (eg. C</dev/VolGroup00/LogVol00>).
1015
1016 See also C<guestfs_lvs_full>.");
1017
1018   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1019    [], (* XXX how to test? *)
1020    "list the LVM physical volumes (PVs)",
1021    "\
1022 List all the physical volumes detected.  This is the equivalent
1023 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1024
1025   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1026    [], (* XXX how to test? *)
1027    "list the LVM volume groups (VGs)",
1028    "\
1029 List all the volumes groups detected.  This is the equivalent
1030 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1031
1032   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1033    [], (* XXX how to test? *)
1034    "list the LVM logical volumes (LVs)",
1035    "\
1036 List all the logical volumes detected.  This is the equivalent
1037 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1038
1039   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1040    [InitISOFS, Always, TestOutputList (
1041       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1042     InitISOFS, Always, TestOutputList (
1043       [["read_lines"; "/empty"]], [])],
1044    "read file as lines",
1045    "\
1046 Return the contents of the file named C<path>.
1047
1048 The file contents are returned as a list of lines.  Trailing
1049 C<LF> and C<CRLF> character sequences are I<not> returned.
1050
1051 Note that this function cannot correctly handle binary files
1052 (specifically, files containing C<\\0> character which is treated
1053 as end of line).  For those you need to use the C<guestfs_read_file>
1054 function which has a more complex interface.");
1055
1056   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1057    [], (* XXX Augeas code needs tests. *)
1058    "create a new Augeas handle",
1059    "\
1060 Create a new Augeas handle for editing configuration files.
1061 If there was any previous Augeas handle associated with this
1062 guestfs session, then it is closed.
1063
1064 You must call this before using any other C<guestfs_aug_*>
1065 commands.
1066
1067 C<root> is the filesystem root.  C<root> must not be NULL,
1068 use C</> instead.
1069
1070 The flags are the same as the flags defined in
1071 E<lt>augeas.hE<gt>, the logical I<or> of the following
1072 integers:
1073
1074 =over 4
1075
1076 =item C<AUG_SAVE_BACKUP> = 1
1077
1078 Keep the original file with a C<.augsave> extension.
1079
1080 =item C<AUG_SAVE_NEWFILE> = 2
1081
1082 Save changes into a file with extension C<.augnew>, and
1083 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1084
1085 =item C<AUG_TYPE_CHECK> = 4
1086
1087 Typecheck lenses (can be expensive).
1088
1089 =item C<AUG_NO_STDINC> = 8
1090
1091 Do not use standard load path for modules.
1092
1093 =item C<AUG_SAVE_NOOP> = 16
1094
1095 Make save a no-op, just record what would have been changed.
1096
1097 =item C<AUG_NO_LOAD> = 32
1098
1099 Do not load the tree in C<guestfs_aug_init>.
1100
1101 =back
1102
1103 To close the handle, you can call C<guestfs_aug_close>.
1104
1105 To find out more about Augeas, see L<http://augeas.net/>.");
1106
1107   ("aug_close", (RErr, []), 26, [],
1108    [], (* XXX Augeas code needs tests. *)
1109    "close the current Augeas handle",
1110    "\
1111 Close the current Augeas handle and free up any resources
1112 used by it.  After calling this, you have to call
1113 C<guestfs_aug_init> again before you can use any other
1114 Augeas functions.");
1115
1116   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1117    [], (* XXX Augeas code needs tests. *)
1118    "define an Augeas variable",
1119    "\
1120 Defines an Augeas variable C<name> whose value is the result
1121 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1122 undefined.
1123
1124 On success this returns the number of nodes in C<expr>, or
1125 C<0> if C<expr> evaluates to something which is not a nodeset.");
1126
1127   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1128    [], (* XXX Augeas code needs tests. *)
1129    "define an Augeas node",
1130    "\
1131 Defines a variable C<name> whose value is the result of
1132 evaluating C<expr>.
1133
1134 If C<expr> evaluates to an empty nodeset, a node is created,
1135 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1136 C<name> will be the nodeset containing that single node.
1137
1138 On success this returns a pair containing the
1139 number of nodes in the nodeset, and a boolean flag
1140 if a node was created.");
1141
1142   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1143    [], (* XXX Augeas code needs tests. *)
1144    "look up the value of an Augeas path",
1145    "\
1146 Look up the value associated with C<path>.  If C<path>
1147 matches exactly one node, the C<value> is returned.");
1148
1149   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1150    [], (* XXX Augeas code needs tests. *)
1151    "set Augeas path to value",
1152    "\
1153 Set the value associated with C<path> to C<value>.");
1154
1155   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1156    [], (* XXX Augeas code needs tests. *)
1157    "insert a sibling Augeas node",
1158    "\
1159 Create a new sibling C<label> for C<path>, inserting it into
1160 the tree before or after C<path> (depending on the boolean
1161 flag C<before>).
1162
1163 C<path> must match exactly one existing node in the tree, and
1164 C<label> must be a label, ie. not contain C</>, C<*> or end
1165 with a bracketed index C<[N]>.");
1166
1167   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1168    [], (* XXX Augeas code needs tests. *)
1169    "remove an Augeas path",
1170    "\
1171 Remove C<path> and all of its children.
1172
1173 On success this returns the number of entries which were removed.");
1174
1175   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1176    [], (* XXX Augeas code needs tests. *)
1177    "move Augeas node",
1178    "\
1179 Move the node C<src> to C<dest>.  C<src> must match exactly
1180 one node.  C<dest> is overwritten if it exists.");
1181
1182   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1183    [], (* XXX Augeas code needs tests. *)
1184    "return Augeas nodes which match augpath",
1185    "\
1186 Returns a list of paths which match the path expression C<path>.
1187 The returned paths are sufficiently qualified so that they match
1188 exactly one node in the current tree.");
1189
1190   ("aug_save", (RErr, []), 25, [],
1191    [], (* XXX Augeas code needs tests. *)
1192    "write all pending Augeas changes to disk",
1193    "\
1194 This writes all pending changes to disk.
1195
1196 The flags which were passed to C<guestfs_aug_init> affect exactly
1197 how files are saved.");
1198
1199   ("aug_load", (RErr, []), 27, [],
1200    [], (* XXX Augeas code needs tests. *)
1201    "load files into the tree",
1202    "\
1203 Load files into the tree.
1204
1205 See C<aug_load> in the Augeas documentation for the full gory
1206 details.");
1207
1208   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1209    [], (* XXX Augeas code needs tests. *)
1210    "list Augeas nodes under augpath",
1211    "\
1212 This is just a shortcut for listing C<guestfs_aug_match>
1213 C<path/*> and sorting the resulting nodes into alphabetical order.");
1214
1215   ("rm", (RErr, [Pathname "path"]), 29, [],
1216    [InitBasicFS, Always, TestRun
1217       [["touch"; "/new"];
1218        ["rm"; "/new"]];
1219     InitBasicFS, Always, TestLastFail
1220       [["rm"; "/new"]];
1221     InitBasicFS, Always, TestLastFail
1222       [["mkdir"; "/new"];
1223        ["rm"; "/new"]]],
1224    "remove a file",
1225    "\
1226 Remove the single file C<path>.");
1227
1228   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1229    [InitBasicFS, Always, TestRun
1230       [["mkdir"; "/new"];
1231        ["rmdir"; "/new"]];
1232     InitBasicFS, Always, TestLastFail
1233       [["rmdir"; "/new"]];
1234     InitBasicFS, Always, TestLastFail
1235       [["touch"; "/new"];
1236        ["rmdir"; "/new"]]],
1237    "remove a directory",
1238    "\
1239 Remove the single directory C<path>.");
1240
1241   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1242    [InitBasicFS, Always, TestOutputFalse
1243       [["mkdir"; "/new"];
1244        ["mkdir"; "/new/foo"];
1245        ["touch"; "/new/foo/bar"];
1246        ["rm_rf"; "/new"];
1247        ["exists"; "/new"]]],
1248    "remove a file or directory recursively",
1249    "\
1250 Remove the file or directory C<path>, recursively removing the
1251 contents if its a directory.  This is like the C<rm -rf> shell
1252 command.");
1253
1254   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1255    [InitBasicFS, Always, TestOutputTrue
1256       [["mkdir"; "/new"];
1257        ["is_dir"; "/new"]];
1258     InitBasicFS, Always, TestLastFail
1259       [["mkdir"; "/new/foo/bar"]]],
1260    "create a directory",
1261    "\
1262 Create a directory named C<path>.");
1263
1264   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1265    [InitBasicFS, Always, TestOutputTrue
1266       [["mkdir_p"; "/new/foo/bar"];
1267        ["is_dir"; "/new/foo/bar"]];
1268     InitBasicFS, Always, TestOutputTrue
1269       [["mkdir_p"; "/new/foo/bar"];
1270        ["is_dir"; "/new/foo"]];
1271     InitBasicFS, Always, TestOutputTrue
1272       [["mkdir_p"; "/new/foo/bar"];
1273        ["is_dir"; "/new"]];
1274     (* Regression tests for RHBZ#503133: *)
1275     InitBasicFS, Always, TestRun
1276       [["mkdir"; "/new"];
1277        ["mkdir_p"; "/new"]];
1278     InitBasicFS, Always, TestLastFail
1279       [["touch"; "/new"];
1280        ["mkdir_p"; "/new"]]],
1281    "create a directory and parents",
1282    "\
1283 Create a directory named C<path>, creating any parent directories
1284 as necessary.  This is like the C<mkdir -p> shell command.");
1285
1286   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1287    [], (* XXX Need stat command to test *)
1288    "change file mode",
1289    "\
1290 Change the mode (permissions) of C<path> to C<mode>.  Only
1291 numeric modes are supported.");
1292
1293   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1294    [], (* XXX Need stat command to test *)
1295    "change file owner and group",
1296    "\
1297 Change the file owner to C<owner> and group to C<group>.
1298
1299 Only numeric uid and gid are supported.  If you want to use
1300 names, you will need to locate and parse the password file
1301 yourself (Augeas support makes this relatively easy).");
1302
1303   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1304    [InitISOFS, Always, TestOutputTrue (
1305       [["exists"; "/empty"]]);
1306     InitISOFS, Always, TestOutputTrue (
1307       [["exists"; "/directory"]])],
1308    "test if file or directory exists",
1309    "\
1310 This returns C<true> if and only if there is a file, directory
1311 (or anything) with the given C<path> name.
1312
1313 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1314
1315   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1316    [InitISOFS, Always, TestOutputTrue (
1317       [["is_file"; "/known-1"]]);
1318     InitISOFS, Always, TestOutputFalse (
1319       [["is_file"; "/directory"]])],
1320    "test if file exists",
1321    "\
1322 This returns C<true> if and only if there is a file
1323 with the given C<path> name.  Note that it returns false for
1324 other objects like directories.
1325
1326 See also C<guestfs_stat>.");
1327
1328   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1329    [InitISOFS, Always, TestOutputFalse (
1330       [["is_dir"; "/known-3"]]);
1331     InitISOFS, Always, TestOutputTrue (
1332       [["is_dir"; "/directory"]])],
1333    "test if file exists",
1334    "\
1335 This returns C<true> if and only if there is a directory
1336 with the given C<path> name.  Note that it returns false for
1337 other objects like files.
1338
1339 See also C<guestfs_stat>.");
1340
1341   ("pvcreate", (RErr, [Device "device"]), 39, [],
1342    [InitEmpty, Always, TestOutputListOfDevices (
1343       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1344        ["pvcreate"; "/dev/sda1"];
1345        ["pvcreate"; "/dev/sda2"];
1346        ["pvcreate"; "/dev/sda3"];
1347        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1348    "create an LVM physical volume",
1349    "\
1350 This creates an LVM physical volume on the named C<device>,
1351 where C<device> should usually be a partition name such
1352 as C</dev/sda1>.");
1353
1354   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1355    [InitEmpty, Always, TestOutputList (
1356       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1357        ["pvcreate"; "/dev/sda1"];
1358        ["pvcreate"; "/dev/sda2"];
1359        ["pvcreate"; "/dev/sda3"];
1360        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1361        ["vgcreate"; "VG2"; "/dev/sda3"];
1362        ["vgs"]], ["VG1"; "VG2"])],
1363    "create an LVM volume group",
1364    "\
1365 This creates an LVM volume group called C<volgroup>
1366 from the non-empty list of physical volumes C<physvols>.");
1367
1368   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1369    [InitEmpty, Always, TestOutputList (
1370       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1371        ["pvcreate"; "/dev/sda1"];
1372        ["pvcreate"; "/dev/sda2"];
1373        ["pvcreate"; "/dev/sda3"];
1374        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1375        ["vgcreate"; "VG2"; "/dev/sda3"];
1376        ["lvcreate"; "LV1"; "VG1"; "50"];
1377        ["lvcreate"; "LV2"; "VG1"; "50"];
1378        ["lvcreate"; "LV3"; "VG2"; "50"];
1379        ["lvcreate"; "LV4"; "VG2"; "50"];
1380        ["lvcreate"; "LV5"; "VG2"; "50"];
1381        ["lvs"]],
1382       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1383        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1384    "create an LVM volume group",
1385    "\
1386 This creates an LVM volume group called C<logvol>
1387 on the volume group C<volgroup>, with C<size> megabytes.");
1388
1389   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1390    [InitEmpty, Always, TestOutput (
1391       [["sfdiskM"; "/dev/sda"; ","];
1392        ["mkfs"; "ext2"; "/dev/sda1"];
1393        ["mount"; "/dev/sda1"; "/"];
1394        ["write_file"; "/new"; "new file contents"; "0"];
1395        ["cat"; "/new"]], "new file contents")],
1396    "make a filesystem",
1397    "\
1398 This creates a filesystem on C<device> (usually a partition
1399 or LVM logical volume).  The filesystem type is C<fstype>, for
1400 example C<ext3>.");
1401
1402   ("sfdisk", (RErr, [Device "device";
1403                      Int "cyls"; Int "heads"; Int "sectors";
1404                      StringList "lines"]), 43, [DangerWillRobinson],
1405    [],
1406    "create partitions on a block device",
1407    "\
1408 This is a direct interface to the L<sfdisk(8)> program for creating
1409 partitions on block devices.
1410
1411 C<device> should be a block device, for example C</dev/sda>.
1412
1413 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1414 and sectors on the device, which are passed directly to sfdisk as
1415 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1416 of these, then the corresponding parameter is omitted.  Usually for
1417 'large' disks, you can just pass C<0> for these, but for small
1418 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1419 out the right geometry and you will need to tell it.
1420
1421 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1422 information refer to the L<sfdisk(8)> manpage.
1423
1424 To create a single partition occupying the whole disk, you would
1425 pass C<lines> as a single element list, when the single element being
1426 the string C<,> (comma).
1427
1428 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1429
1430   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1431    [InitBasicFS, Always, TestOutput (
1432       [["write_file"; "/new"; "new file contents"; "0"];
1433        ["cat"; "/new"]], "new file contents");
1434     InitBasicFS, Always, TestOutput (
1435       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1436        ["cat"; "/new"]], "\nnew file contents\n");
1437     InitBasicFS, Always, TestOutput (
1438       [["write_file"; "/new"; "\n\n"; "0"];
1439        ["cat"; "/new"]], "\n\n");
1440     InitBasicFS, Always, TestOutput (
1441       [["write_file"; "/new"; ""; "0"];
1442        ["cat"; "/new"]], "");
1443     InitBasicFS, Always, TestOutput (
1444       [["write_file"; "/new"; "\n\n\n"; "0"];
1445        ["cat"; "/new"]], "\n\n\n");
1446     InitBasicFS, Always, TestOutput (
1447       [["write_file"; "/new"; "\n"; "0"];
1448        ["cat"; "/new"]], "\n")],
1449    "create a file",
1450    "\
1451 This call creates a file called C<path>.  The contents of the
1452 file is the string C<content> (which can contain any 8 bit data),
1453 with length C<size>.
1454
1455 As a special case, if C<size> is C<0>
1456 then the length is calculated using C<strlen> (so in this case
1457 the content cannot contain embedded ASCII NULs).
1458
1459 I<NB.> Owing to a bug, writing content containing ASCII NUL
1460 characters does I<not> work, even if the length is specified.
1461 We hope to resolve this bug in a future version.  In the meantime
1462 use C<guestfs_upload>.");
1463
1464   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1465    [InitEmpty, Always, TestOutputListOfDevices (
1466       [["sfdiskM"; "/dev/sda"; ","];
1467        ["mkfs"; "ext2"; "/dev/sda1"];
1468        ["mount"; "/dev/sda1"; "/"];
1469        ["mounts"]], ["/dev/sda1"]);
1470     InitEmpty, Always, TestOutputList (
1471       [["sfdiskM"; "/dev/sda"; ","];
1472        ["mkfs"; "ext2"; "/dev/sda1"];
1473        ["mount"; "/dev/sda1"; "/"];
1474        ["umount"; "/"];
1475        ["mounts"]], [])],
1476    "unmount a filesystem",
1477    "\
1478 This unmounts the given filesystem.  The filesystem may be
1479 specified either by its mountpoint (path) or the device which
1480 contains the filesystem.");
1481
1482   ("mounts", (RStringList "devices", []), 46, [],
1483    [InitBasicFS, Always, TestOutputListOfDevices (
1484       [["mounts"]], ["/dev/sda1"])],
1485    "show mounted filesystems",
1486    "\
1487 This returns the list of currently mounted filesystems.  It returns
1488 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1489
1490 Some internal mounts are not shown.
1491
1492 See also: C<guestfs_mountpoints>");
1493
1494   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1495    [InitBasicFS, Always, TestOutputList (
1496       [["umount_all"];
1497        ["mounts"]], []);
1498     (* check that umount_all can unmount nested mounts correctly: *)
1499     InitEmpty, Always, TestOutputList (
1500       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mkfs"; "ext2"; "/dev/sda2"];
1503        ["mkfs"; "ext2"; "/dev/sda3"];
1504        ["mount"; "/dev/sda1"; "/"];
1505        ["mkdir"; "/mp1"];
1506        ["mount"; "/dev/sda2"; "/mp1"];
1507        ["mkdir"; "/mp1/mp2"];
1508        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1509        ["mkdir"; "/mp1/mp2/mp3"];
1510        ["umount_all"];
1511        ["mounts"]], [])],
1512    "unmount all filesystems",
1513    "\
1514 This unmounts all mounted filesystems.
1515
1516 Some internal mounts are not unmounted by this call.");
1517
1518   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1519    [],
1520    "remove all LVM LVs, VGs and PVs",
1521    "\
1522 This command removes all LVM logical volumes, volume groups
1523 and physical volumes.");
1524
1525   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1526    [InitISOFS, Always, TestOutput (
1527       [["file"; "/empty"]], "empty");
1528     InitISOFS, Always, TestOutput (
1529       [["file"; "/known-1"]], "ASCII text");
1530     InitISOFS, Always, TestLastFail (
1531       [["file"; "/notexists"]])],
1532    "determine file type",
1533    "\
1534 This call uses the standard L<file(1)> command to determine
1535 the type or contents of the file.  This also works on devices,
1536 for example to find out whether a partition contains a filesystem.
1537
1538 This call will also transparently look inside various types
1539 of compressed file.
1540
1541 The exact command which runs is C<file -zbsL path>.  Note in
1542 particular that the filename is not prepended to the output
1543 (the C<-b> option).");
1544
1545   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1546    [InitBasicFS, Always, TestOutput (
1547       [["upload"; "test-command"; "/test-command"];
1548        ["chmod"; "0o755"; "/test-command"];
1549        ["command"; "/test-command 1"]], "Result1");
1550     InitBasicFS, Always, TestOutput (
1551       [["upload"; "test-command"; "/test-command"];
1552        ["chmod"; "0o755"; "/test-command"];
1553        ["command"; "/test-command 2"]], "Result2\n");
1554     InitBasicFS, Always, TestOutput (
1555       [["upload"; "test-command"; "/test-command"];
1556        ["chmod"; "0o755"; "/test-command"];
1557        ["command"; "/test-command 3"]], "\nResult3");
1558     InitBasicFS, Always, TestOutput (
1559       [["upload"; "test-command"; "/test-command"];
1560        ["chmod"; "0o755"; "/test-command"];
1561        ["command"; "/test-command 4"]], "\nResult4\n");
1562     InitBasicFS, Always, TestOutput (
1563       [["upload"; "test-command"; "/test-command"];
1564        ["chmod"; "0o755"; "/test-command"];
1565        ["command"; "/test-command 5"]], "\nResult5\n\n");
1566     InitBasicFS, Always, TestOutput (
1567       [["upload"; "test-command"; "/test-command"];
1568        ["chmod"; "0o755"; "/test-command"];
1569        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1570     InitBasicFS, Always, TestOutput (
1571       [["upload"; "test-command"; "/test-command"];
1572        ["chmod"; "0o755"; "/test-command"];
1573        ["command"; "/test-command 7"]], "");
1574     InitBasicFS, Always, TestOutput (
1575       [["upload"; "test-command"; "/test-command"];
1576        ["chmod"; "0o755"; "/test-command"];
1577        ["command"; "/test-command 8"]], "\n");
1578     InitBasicFS, Always, TestOutput (
1579       [["upload"; "test-command"; "/test-command"];
1580        ["chmod"; "0o755"; "/test-command"];
1581        ["command"; "/test-command 9"]], "\n\n");
1582     InitBasicFS, Always, TestOutput (
1583       [["upload"; "test-command"; "/test-command"];
1584        ["chmod"; "0o755"; "/test-command"];
1585        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1586     InitBasicFS, Always, TestOutput (
1587       [["upload"; "test-command"; "/test-command"];
1588        ["chmod"; "0o755"; "/test-command"];
1589        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1590     InitBasicFS, Always, TestLastFail (
1591       [["upload"; "test-command"; "/test-command"];
1592        ["chmod"; "0o755"; "/test-command"];
1593        ["command"; "/test-command"]])],
1594    "run a command from the guest filesystem",
1595    "\
1596 This call runs a command from the guest filesystem.  The
1597 filesystem must be mounted, and must contain a compatible
1598 operating system (ie. something Linux, with the same
1599 or compatible processor architecture).
1600
1601 The single parameter is an argv-style list of arguments.
1602 The first element is the name of the program to run.
1603 Subsequent elements are parameters.  The list must be
1604 non-empty (ie. must contain a program name).  Note that
1605 the command runs directly, and is I<not> invoked via
1606 the shell (see C<guestfs_sh>).
1607
1608 The return value is anything printed to I<stdout> by
1609 the command.
1610
1611 If the command returns a non-zero exit status, then
1612 this function returns an error message.  The error message
1613 string is the content of I<stderr> from the command.
1614
1615 The C<$PATH> environment variable will contain at least
1616 C</usr/bin> and C</bin>.  If you require a program from
1617 another location, you should provide the full path in the
1618 first parameter.
1619
1620 Shared libraries and data files required by the program
1621 must be available on filesystems which are mounted in the
1622 correct places.  It is the caller's responsibility to ensure
1623 all filesystems that are needed are mounted at the right
1624 locations.");
1625
1626   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1627    [InitBasicFS, Always, TestOutputList (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command_lines"; "/test-command 1"]], ["Result1"]);
1631     InitBasicFS, Always, TestOutputList (
1632       [["upload"; "test-command"; "/test-command"];
1633        ["chmod"; "0o755"; "/test-command"];
1634        ["command_lines"; "/test-command 2"]], ["Result2"]);
1635     InitBasicFS, Always, TestOutputList (
1636       [["upload"; "test-command"; "/test-command"];
1637        ["chmod"; "0o755"; "/test-command"];
1638        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1639     InitBasicFS, Always, TestOutputList (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1643     InitBasicFS, Always, TestOutputList (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1647     InitBasicFS, Always, TestOutputList (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1651     InitBasicFS, Always, TestOutputList (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command_lines"; "/test-command 7"]], []);
1655     InitBasicFS, Always, TestOutputList (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command_lines"; "/test-command 8"]], [""]);
1659     InitBasicFS, Always, TestOutputList (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command_lines"; "/test-command 9"]], ["";""]);
1663     InitBasicFS, Always, TestOutputList (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1667     InitBasicFS, Always, TestOutputList (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1671    "run a command, returning lines",
1672    "\
1673 This is the same as C<guestfs_command>, but splits the
1674 result into a list of lines.
1675
1676 See also: C<guestfs_sh_lines>");
1677
1678   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1679    [InitISOFS, Always, TestOutputStruct (
1680       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1681    "get file information",
1682    "\
1683 Returns file information for the given C<path>.
1684
1685 This is the same as the C<stat(2)> system call.");
1686
1687   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1688    [InitISOFS, Always, TestOutputStruct (
1689       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1690    "get file information for a symbolic link",
1691    "\
1692 Returns file information for the given C<path>.
1693
1694 This is the same as C<guestfs_stat> except that if C<path>
1695 is a symbolic link, then the link is stat-ed, not the file it
1696 refers to.
1697
1698 This is the same as the C<lstat(2)> system call.");
1699
1700   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1701    [InitISOFS, Always, TestOutputStruct (
1702       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1703    "get file system statistics",
1704    "\
1705 Returns file system statistics for any mounted file system.
1706 C<path> should be a file or directory in the mounted file system
1707 (typically it is the mount point itself, but it doesn't need to be).
1708
1709 This is the same as the C<statvfs(2)> system call.");
1710
1711   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1712    [], (* XXX test *)
1713    "get ext2/ext3/ext4 superblock details",
1714    "\
1715 This returns the contents of the ext2, ext3 or ext4 filesystem
1716 superblock on C<device>.
1717
1718 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1719 manpage for more details.  The list of fields returned isn't
1720 clearly defined, and depends on both the version of C<tune2fs>
1721 that libguestfs was built against, and the filesystem itself.");
1722
1723   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1724    [InitEmpty, Always, TestOutputTrue (
1725       [["blockdev_setro"; "/dev/sda"];
1726        ["blockdev_getro"; "/dev/sda"]])],
1727    "set block device to read-only",
1728    "\
1729 Sets the block device named C<device> to read-only.
1730
1731 This uses the L<blockdev(8)> command.");
1732
1733   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1734    [InitEmpty, Always, TestOutputFalse (
1735       [["blockdev_setrw"; "/dev/sda"];
1736        ["blockdev_getro"; "/dev/sda"]])],
1737    "set block device to read-write",
1738    "\
1739 Sets the block device named C<device> to read-write.
1740
1741 This uses the L<blockdev(8)> command.");
1742
1743   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1744    [InitEmpty, Always, TestOutputTrue (
1745       [["blockdev_setro"; "/dev/sda"];
1746        ["blockdev_getro"; "/dev/sda"]])],
1747    "is block device set to read-only",
1748    "\
1749 Returns a boolean indicating if the block device is read-only
1750 (true if read-only, false if not).
1751
1752 This uses the L<blockdev(8)> command.");
1753
1754   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1755    [InitEmpty, Always, TestOutputInt (
1756       [["blockdev_getss"; "/dev/sda"]], 512)],
1757    "get sectorsize of block device",
1758    "\
1759 This returns the size of sectors on a block device.
1760 Usually 512, but can be larger for modern devices.
1761
1762 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1763 for that).
1764
1765 This uses the L<blockdev(8)> command.");
1766
1767   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1768    [InitEmpty, Always, TestOutputInt (
1769       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1770    "get blocksize of block device",
1771    "\
1772 This returns the block size of a device.
1773
1774 (Note this is different from both I<size in blocks> and
1775 I<filesystem block size>).
1776
1777 This uses the L<blockdev(8)> command.");
1778
1779   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1780    [], (* XXX test *)
1781    "set blocksize of block device",
1782    "\
1783 This sets the block size of a device.
1784
1785 (Note this is different from both I<size in blocks> and
1786 I<filesystem block size>).
1787
1788 This uses the L<blockdev(8)> command.");
1789
1790   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1791    [InitEmpty, Always, TestOutputInt (
1792       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1793    "get total size of device in 512-byte sectors",
1794    "\
1795 This returns the size of the device in units of 512-byte sectors
1796 (even if the sectorsize isn't 512 bytes ... weird).
1797
1798 See also C<guestfs_blockdev_getss> for the real sector size of
1799 the device, and C<guestfs_blockdev_getsize64> for the more
1800 useful I<size in bytes>.
1801
1802 This uses the L<blockdev(8)> command.");
1803
1804   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1805    [InitEmpty, Always, TestOutputInt (
1806       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1807    "get total size of device in bytes",
1808    "\
1809 This returns the size of the device in bytes.
1810
1811 See also C<guestfs_blockdev_getsz>.
1812
1813 This uses the L<blockdev(8)> command.");
1814
1815   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1816    [InitEmpty, Always, TestRun
1817       [["blockdev_flushbufs"; "/dev/sda"]]],
1818    "flush device buffers",
1819    "\
1820 This tells the kernel to flush internal buffers associated
1821 with C<device>.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1826    [InitEmpty, Always, TestRun
1827       [["blockdev_rereadpt"; "/dev/sda"]]],
1828    "reread partition table",
1829    "\
1830 Reread the partition table on C<device>.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1835    [InitBasicFS, Always, TestOutput (
1836       (* Pick a file from cwd which isn't likely to change. *)
1837       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1838        ["checksum"; "md5"; "/COPYING.LIB"]],
1839         Digest.to_hex (Digest.file "COPYING.LIB"))],
1840    "upload a file from the local machine",
1841    "\
1842 Upload local file C<filename> to C<remotefilename> on the
1843 filesystem.
1844
1845 C<filename> can also be a named pipe.
1846
1847 See also C<guestfs_download>.");
1848
1849   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1850    [InitBasicFS, Always, TestOutput (
1851       (* Pick a file from cwd which isn't likely to change. *)
1852       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1853        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1854        ["upload"; "testdownload.tmp"; "/upload"];
1855        ["checksum"; "md5"; "/upload"]],
1856         Digest.to_hex (Digest.file "COPYING.LIB"))],
1857    "download a file to the local machine",
1858    "\
1859 Download file C<remotefilename> and save it as C<filename>
1860 on the local machine.
1861
1862 C<filename> can also be a named pipe.
1863
1864 See also C<guestfs_upload>, C<guestfs_cat>.");
1865
1866   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1867    [InitISOFS, Always, TestOutput (
1868       [["checksum"; "crc"; "/known-3"]], "2891671662");
1869     InitISOFS, Always, TestLastFail (
1870       [["checksum"; "crc"; "/notexists"]]);
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1879     InitISOFS, Always, TestOutput (
1880       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1881     InitISOFS, Always, TestOutput (
1882       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1883    "compute MD5, SHAx or CRC checksum of file",
1884    "\
1885 This call computes the MD5, SHAx or CRC checksum of the
1886 file named C<path>.
1887
1888 The type of checksum to compute is given by the C<csumtype>
1889 parameter which must have one of the following values:
1890
1891 =over 4
1892
1893 =item C<crc>
1894
1895 Compute the cyclic redundancy check (CRC) specified by POSIX
1896 for the C<cksum> command.
1897
1898 =item C<md5>
1899
1900 Compute the MD5 hash (using the C<md5sum> program).
1901
1902 =item C<sha1>
1903
1904 Compute the SHA1 hash (using the C<sha1sum> program).
1905
1906 =item C<sha224>
1907
1908 Compute the SHA224 hash (using the C<sha224sum> program).
1909
1910 =item C<sha256>
1911
1912 Compute the SHA256 hash (using the C<sha256sum> program).
1913
1914 =item C<sha384>
1915
1916 Compute the SHA384 hash (using the C<sha384sum> program).
1917
1918 =item C<sha512>
1919
1920 Compute the SHA512 hash (using the C<sha512sum> program).
1921
1922 =back
1923
1924 The checksum is returned as a printable string.");
1925
1926   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1927    [InitBasicFS, Always, TestOutput (
1928       [["tar_in"; "../images/helloworld.tar"; "/"];
1929        ["cat"; "/hello"]], "hello\n")],
1930    "unpack tarfile to directory",
1931    "\
1932 This command uploads and unpacks local file C<tarfile> (an
1933 I<uncompressed> tar file) into C<directory>.
1934
1935 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1936
1937   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1938    [],
1939    "pack directory into tarfile",
1940    "\
1941 This command packs the contents of C<directory> and downloads
1942 it to local file C<tarfile>.
1943
1944 To download a compressed tarball, use C<guestfs_tgz_out>.");
1945
1946   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1947    [InitBasicFS, Always, TestOutput (
1948       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1949        ["cat"; "/hello"]], "hello\n")],
1950    "unpack compressed tarball to directory",
1951    "\
1952 This command uploads and unpacks local file C<tarball> (a
1953 I<gzip compressed> tar file) into C<directory>.
1954
1955 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1956
1957   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1958    [],
1959    "pack directory into compressed tarball",
1960    "\
1961 This command packs the contents of C<directory> and downloads
1962 it to local file C<tarball>.
1963
1964 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1965
1966   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1967    [InitBasicFS, Always, TestLastFail (
1968       [["umount"; "/"];
1969        ["mount_ro"; "/dev/sda1"; "/"];
1970        ["touch"; "/new"]]);
1971     InitBasicFS, Always, TestOutput (
1972       [["write_file"; "/new"; "data"; "0"];
1973        ["umount"; "/"];
1974        ["mount_ro"; "/dev/sda1"; "/"];
1975        ["cat"; "/new"]], "data")],
1976    "mount a guest disk, read-only",
1977    "\
1978 This is the same as the C<guestfs_mount> command, but it
1979 mounts the filesystem with the read-only (I<-o ro>) flag.");
1980
1981   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1982    [],
1983    "mount a guest disk with mount options",
1984    "\
1985 This is the same as the C<guestfs_mount> command, but it
1986 allows you to set the mount options as for the
1987 L<mount(8)> I<-o> flag.");
1988
1989   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1990    [],
1991    "mount a guest disk with mount options and vfstype",
1992    "\
1993 This is the same as the C<guestfs_mount> command, but it
1994 allows you to set both the mount options and the vfstype
1995 as for the L<mount(8)> I<-o> and I<-t> flags.");
1996
1997   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1998    [],
1999    "debugging and internals",
2000    "\
2001 The C<guestfs_debug> command exposes some internals of
2002 C<guestfsd> (the guestfs daemon) that runs inside the
2003 qemu subprocess.
2004
2005 There is no comprehensive help for this command.  You have
2006 to look at the file C<daemon/debug.c> in the libguestfs source
2007 to find out what you can do.");
2008
2009   ("lvremove", (RErr, [Device "device"]), 77, [],
2010    [InitEmpty, Always, TestOutputList (
2011       [["sfdiskM"; "/dev/sda"; ","];
2012        ["pvcreate"; "/dev/sda1"];
2013        ["vgcreate"; "VG"; "/dev/sda1"];
2014        ["lvcreate"; "LV1"; "VG"; "50"];
2015        ["lvcreate"; "LV2"; "VG"; "50"];
2016        ["lvremove"; "/dev/VG/LV1"];
2017        ["lvs"]], ["/dev/VG/LV2"]);
2018     InitEmpty, Always, TestOutputList (
2019       [["sfdiskM"; "/dev/sda"; ","];
2020        ["pvcreate"; "/dev/sda1"];
2021        ["vgcreate"; "VG"; "/dev/sda1"];
2022        ["lvcreate"; "LV1"; "VG"; "50"];
2023        ["lvcreate"; "LV2"; "VG"; "50"];
2024        ["lvremove"; "/dev/VG"];
2025        ["lvs"]], []);
2026     InitEmpty, Always, TestOutputList (
2027       [["sfdiskM"; "/dev/sda"; ","];
2028        ["pvcreate"; "/dev/sda1"];
2029        ["vgcreate"; "VG"; "/dev/sda1"];
2030        ["lvcreate"; "LV1"; "VG"; "50"];
2031        ["lvcreate"; "LV2"; "VG"; "50"];
2032        ["lvremove"; "/dev/VG"];
2033        ["vgs"]], ["VG"])],
2034    "remove an LVM logical volume",
2035    "\
2036 Remove an LVM logical volume C<device>, where C<device> is
2037 the path to the LV, such as C</dev/VG/LV>.
2038
2039 You can also remove all LVs in a volume group by specifying
2040 the VG name, C</dev/VG>.");
2041
2042   ("vgremove", (RErr, [String "vgname"]), 78, [],
2043    [InitEmpty, Always, TestOutputList (
2044       [["sfdiskM"; "/dev/sda"; ","];
2045        ["pvcreate"; "/dev/sda1"];
2046        ["vgcreate"; "VG"; "/dev/sda1"];
2047        ["lvcreate"; "LV1"; "VG"; "50"];
2048        ["lvcreate"; "LV2"; "VG"; "50"];
2049        ["vgremove"; "VG"];
2050        ["lvs"]], []);
2051     InitEmpty, Always, TestOutputList (
2052       [["sfdiskM"; "/dev/sda"; ","];
2053        ["pvcreate"; "/dev/sda1"];
2054        ["vgcreate"; "VG"; "/dev/sda1"];
2055        ["lvcreate"; "LV1"; "VG"; "50"];
2056        ["lvcreate"; "LV2"; "VG"; "50"];
2057        ["vgremove"; "VG"];
2058        ["vgs"]], [])],
2059    "remove an LVM volume group",
2060    "\
2061 Remove an LVM volume group C<vgname>, (for example C<VG>).
2062
2063 This also forcibly removes all logical volumes in the volume
2064 group (if any).");
2065
2066   ("pvremove", (RErr, [Device "device"]), 79, [],
2067    [InitEmpty, Always, TestOutputListOfDevices (
2068       [["sfdiskM"; "/dev/sda"; ","];
2069        ["pvcreate"; "/dev/sda1"];
2070        ["vgcreate"; "VG"; "/dev/sda1"];
2071        ["lvcreate"; "LV1"; "VG"; "50"];
2072        ["lvcreate"; "LV2"; "VG"; "50"];
2073        ["vgremove"; "VG"];
2074        ["pvremove"; "/dev/sda1"];
2075        ["lvs"]], []);
2076     InitEmpty, Always, TestOutputListOfDevices (
2077       [["sfdiskM"; "/dev/sda"; ","];
2078        ["pvcreate"; "/dev/sda1"];
2079        ["vgcreate"; "VG"; "/dev/sda1"];
2080        ["lvcreate"; "LV1"; "VG"; "50"];
2081        ["lvcreate"; "LV2"; "VG"; "50"];
2082        ["vgremove"; "VG"];
2083        ["pvremove"; "/dev/sda1"];
2084        ["vgs"]], []);
2085     InitEmpty, Always, TestOutputListOfDevices (
2086       [["sfdiskM"; "/dev/sda"; ","];
2087        ["pvcreate"; "/dev/sda1"];
2088        ["vgcreate"; "VG"; "/dev/sda1"];
2089        ["lvcreate"; "LV1"; "VG"; "50"];
2090        ["lvcreate"; "LV2"; "VG"; "50"];
2091        ["vgremove"; "VG"];
2092        ["pvremove"; "/dev/sda1"];
2093        ["pvs"]], [])],
2094    "remove an LVM physical volume",
2095    "\
2096 This wipes a physical volume C<device> so that LVM will no longer
2097 recognise it.
2098
2099 The implementation uses the C<pvremove> command which refuses to
2100 wipe physical volumes that contain any volume groups, so you have
2101 to remove those first.");
2102
2103   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2104    [InitBasicFS, Always, TestOutput (
2105       [["set_e2label"; "/dev/sda1"; "testlabel"];
2106        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2107    "set the ext2/3/4 filesystem label",
2108    "\
2109 This sets the ext2/3/4 filesystem label of the filesystem on
2110 C<device> to C<label>.  Filesystem labels are limited to
2111 16 characters.
2112
2113 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2114 to return the existing label on a filesystem.");
2115
2116   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2117    [],
2118    "get the ext2/3/4 filesystem label",
2119    "\
2120 This returns the ext2/3/4 filesystem label of the filesystem on
2121 C<device>.");
2122
2123   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2124    (let uuid = uuidgen () in
2125     [InitBasicFS, Always, TestOutput (
2126        [["set_e2uuid"; "/dev/sda1"; uuid];
2127         ["get_e2uuid"; "/dev/sda1"]], uuid);
2128      InitBasicFS, Always, TestOutput (
2129        [["set_e2uuid"; "/dev/sda1"; "clear"];
2130         ["get_e2uuid"; "/dev/sda1"]], "");
2131      (* We can't predict what UUIDs will be, so just check the commands run. *)
2132      InitBasicFS, Always, TestRun (
2133        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2134      InitBasicFS, Always, TestRun (
2135        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2136    "set the ext2/3/4 filesystem UUID",
2137    "\
2138 This sets the ext2/3/4 filesystem UUID of the filesystem on
2139 C<device> to C<uuid>.  The format of the UUID and alternatives
2140 such as C<clear>, C<random> and C<time> are described in the
2141 L<tune2fs(8)> manpage.
2142
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2144 to return the existing UUID of a filesystem.");
2145
2146   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2147    [],
2148    "get the ext2/3/4 filesystem UUID",
2149    "\
2150 This returns the ext2/3/4 filesystem UUID of the filesystem on
2151 C<device>.");
2152
2153   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2154    [InitBasicFS, Always, TestOutputInt (
2155       [["umount"; "/dev/sda1"];
2156        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2157     InitBasicFS, Always, TestOutputInt (
2158       [["umount"; "/dev/sda1"];
2159        ["zero"; "/dev/sda1"];
2160        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2161    "run the filesystem checker",
2162    "\
2163 This runs the filesystem checker (fsck) on C<device> which
2164 should have filesystem type C<fstype>.
2165
2166 The returned integer is the status.  See L<fsck(8)> for the
2167 list of status codes from C<fsck>.
2168
2169 Notes:
2170
2171 =over 4
2172
2173 =item *
2174
2175 Multiple status codes can be summed together.
2176
2177 =item *
2178
2179 A non-zero return code can mean \"success\", for example if
2180 errors have been corrected on the filesystem.
2181
2182 =item *
2183
2184 Checking or repairing NTFS volumes is not supported
2185 (by linux-ntfs).
2186
2187 =back
2188
2189 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2190
2191   ("zero", (RErr, [Device "device"]), 85, [],
2192    [InitBasicFS, Always, TestOutput (
2193       [["umount"; "/dev/sda1"];
2194        ["zero"; "/dev/sda1"];
2195        ["file"; "/dev/sda1"]], "data")],
2196    "write zeroes to the device",
2197    "\
2198 This command writes zeroes over the first few blocks of C<device>.
2199
2200 How many blocks are zeroed isn't specified (but it's I<not> enough
2201 to securely wipe the device).  It should be sufficient to remove
2202 any partition tables, filesystem superblocks and so on.
2203
2204 See also: C<guestfs_scrub_device>.");
2205
2206   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2207    (* Test disabled because grub-install incompatible with virtio-blk driver.
2208     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2209     *)
2210    [InitBasicFS, Disabled, TestOutputTrue (
2211       [["grub_install"; "/"; "/dev/sda1"];
2212        ["is_dir"; "/boot"]])],
2213    "install GRUB",
2214    "\
2215 This command installs GRUB (the Grand Unified Bootloader) on
2216 C<device>, with the root directory being C<root>.");
2217
2218   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2219    [InitBasicFS, Always, TestOutput (
2220       [["write_file"; "/old"; "file content"; "0"];
2221        ["cp"; "/old"; "/new"];
2222        ["cat"; "/new"]], "file content");
2223     InitBasicFS, Always, TestOutputTrue (
2224       [["write_file"; "/old"; "file content"; "0"];
2225        ["cp"; "/old"; "/new"];
2226        ["is_file"; "/old"]]);
2227     InitBasicFS, Always, TestOutput (
2228       [["write_file"; "/old"; "file content"; "0"];
2229        ["mkdir"; "/dir"];
2230        ["cp"; "/old"; "/dir/new"];
2231        ["cat"; "/dir/new"]], "file content")],
2232    "copy a file",
2233    "\
2234 This copies a file from C<src> to C<dest> where C<dest> is
2235 either a destination filename or destination directory.");
2236
2237   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2238    [InitBasicFS, Always, TestOutput (
2239       [["mkdir"; "/olddir"];
2240        ["mkdir"; "/newdir"];
2241        ["write_file"; "/olddir/file"; "file content"; "0"];
2242        ["cp_a"; "/olddir"; "/newdir"];
2243        ["cat"; "/newdir/olddir/file"]], "file content")],
2244    "copy a file or directory recursively",
2245    "\
2246 This copies a file or directory from C<src> to C<dest>
2247 recursively using the C<cp -a> command.");
2248
2249   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2250    [InitBasicFS, Always, TestOutput (
2251       [["write_file"; "/old"; "file content"; "0"];
2252        ["mv"; "/old"; "/new"];
2253        ["cat"; "/new"]], "file content");
2254     InitBasicFS, Always, TestOutputFalse (
2255       [["write_file"; "/old"; "file content"; "0"];
2256        ["mv"; "/old"; "/new"];
2257        ["is_file"; "/old"]])],
2258    "move a file",
2259    "\
2260 This moves a file from C<src> to C<dest> where C<dest> is
2261 either a destination filename or destination directory.");
2262
2263   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2264    [InitEmpty, Always, TestRun (
2265       [["drop_caches"; "3"]])],
2266    "drop kernel page cache, dentries and inodes",
2267    "\
2268 This instructs the guest kernel to drop its page cache,
2269 and/or dentries and inode caches.  The parameter C<whattodrop>
2270 tells the kernel what precisely to drop, see
2271 L<http://linux-mm.org/Drop_Caches>
2272
2273 Setting C<whattodrop> to 3 should drop everything.
2274
2275 This automatically calls L<sync(2)> before the operation,
2276 so that the maximum guest memory is freed.");
2277
2278   ("dmesg", (RString "kmsgs", []), 91, [],
2279    [InitEmpty, Always, TestRun (
2280       [["dmesg"]])],
2281    "return kernel messages",
2282    "\
2283 This returns the kernel messages (C<dmesg> output) from
2284 the guest kernel.  This is sometimes useful for extended
2285 debugging of problems.
2286
2287 Another way to get the same information is to enable
2288 verbose messages with C<guestfs_set_verbose> or by setting
2289 the environment variable C<LIBGUESTFS_DEBUG=1> before
2290 running the program.");
2291
2292   ("ping_daemon", (RErr, []), 92, [],
2293    [InitEmpty, Always, TestRun (
2294       [["ping_daemon"]])],
2295    "ping the guest daemon",
2296    "\
2297 This is a test probe into the guestfs daemon running inside
2298 the qemu subprocess.  Calling this function checks that the
2299 daemon responds to the ping message, without affecting the daemon
2300 or attached block device(s) in any other way.");
2301
2302   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2303    [InitBasicFS, Always, TestOutputTrue (
2304       [["write_file"; "/file1"; "contents of a file"; "0"];
2305        ["cp"; "/file1"; "/file2"];
2306        ["equal"; "/file1"; "/file2"]]);
2307     InitBasicFS, Always, TestOutputFalse (
2308       [["write_file"; "/file1"; "contents of a file"; "0"];
2309        ["write_file"; "/file2"; "contents of another file"; "0"];
2310        ["equal"; "/file1"; "/file2"]]);
2311     InitBasicFS, Always, TestLastFail (
2312       [["equal"; "/file1"; "/file2"]])],
2313    "test if two files have equal contents",
2314    "\
2315 This compares the two files C<file1> and C<file2> and returns
2316 true if their content is exactly equal, or false otherwise.
2317
2318 The external L<cmp(1)> program is used for the comparison.");
2319
2320   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2321    [InitISOFS, Always, TestOutputList (
2322       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2323     InitISOFS, Always, TestOutputList (
2324       [["strings"; "/empty"]], [])],
2325    "print the printable strings in a file",
2326    "\
2327 This runs the L<strings(1)> command on a file and returns
2328 the list of printable strings found.");
2329
2330   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2331    [InitISOFS, Always, TestOutputList (
2332       [["strings_e"; "b"; "/known-5"]], []);
2333     InitBasicFS, Disabled, TestOutputList (
2334       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2335        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2336    "print the printable strings in a file",
2337    "\
2338 This is like the C<guestfs_strings> command, but allows you to
2339 specify the encoding.
2340
2341 See the L<strings(1)> manpage for the full list of encodings.
2342
2343 Commonly useful encodings are C<l> (lower case L) which will
2344 show strings inside Windows/x86 files.
2345
2346 The returned strings are transcoded to UTF-8.");
2347
2348   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2349    [InitISOFS, Always, TestOutput (
2350       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2351     (* Test for RHBZ#501888c2 regression which caused large hexdump
2352      * commands to segfault.
2353      *)
2354     InitISOFS, Always, TestRun (
2355       [["hexdump"; "/100krandom"]])],
2356    "dump a file in hexadecimal",
2357    "\
2358 This runs C<hexdump -C> on the given C<path>.  The result is
2359 the human-readable, canonical hex dump of the file.");
2360
2361   ("zerofree", (RErr, [Device "device"]), 97, [],
2362    [InitNone, Always, TestOutput (
2363       [["sfdiskM"; "/dev/sda"; ","];
2364        ["mkfs"; "ext3"; "/dev/sda1"];
2365        ["mount"; "/dev/sda1"; "/"];
2366        ["write_file"; "/new"; "test file"; "0"];
2367        ["umount"; "/dev/sda1"];
2368        ["zerofree"; "/dev/sda1"];
2369        ["mount"; "/dev/sda1"; "/"];
2370        ["cat"; "/new"]], "test file")],
2371    "zero unused inodes and disk blocks on ext2/3 filesystem",
2372    "\
2373 This runs the I<zerofree> program on C<device>.  This program
2374 claims to zero unused inodes and disk blocks on an ext2/3
2375 filesystem, thus making it possible to compress the filesystem
2376 more effectively.
2377
2378 You should B<not> run this program if the filesystem is
2379 mounted.
2380
2381 It is possible that using this program can damage the filesystem
2382 or data on the filesystem.");
2383
2384   ("pvresize", (RErr, [Device "device"]), 98, [],
2385    [],
2386    "resize an LVM physical volume",
2387    "\
2388 This resizes (expands or shrinks) an existing LVM physical
2389 volume to match the new size of the underlying device.");
2390
2391   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2392                        Int "cyls"; Int "heads"; Int "sectors";
2393                        String "line"]), 99, [DangerWillRobinson],
2394    [],
2395    "modify a single partition on a block device",
2396    "\
2397 This runs L<sfdisk(8)> option to modify just the single
2398 partition C<n> (note: C<n> counts from 1).
2399
2400 For other parameters, see C<guestfs_sfdisk>.  You should usually
2401 pass C<0> for the cyls/heads/sectors parameters.");
2402
2403   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2404    [],
2405    "display the partition table",
2406    "\
2407 This displays the partition table on C<device>, in the
2408 human-readable output of the L<sfdisk(8)> command.  It is
2409 not intended to be parsed.");
2410
2411   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2412    [],
2413    "display the kernel geometry",
2414    "\
2415 This displays the kernel's idea of the geometry of C<device>.
2416
2417 The result is in human-readable format, and not designed to
2418 be parsed.");
2419
2420   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2421    [],
2422    "display the disk geometry from the partition table",
2423    "\
2424 This displays the disk geometry of C<device> read from the
2425 partition table.  Especially in the case where the underlying
2426 block device has been resized, this can be different from the
2427 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2428
2429 The result is in human-readable format, and not designed to
2430 be parsed.");
2431
2432   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2433    [],
2434    "activate or deactivate all volume groups",
2435    "\
2436 This command activates or (if C<activate> is false) deactivates
2437 all logical volumes in all volume groups.
2438 If activated, then they are made known to the
2439 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2440 then those devices disappear.
2441
2442 This command is the same as running C<vgchange -a y|n>");
2443
2444   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2445    [],
2446    "activate or deactivate some volume groups",
2447    "\
2448 This command activates or (if C<activate> is false) deactivates
2449 all logical volumes in the listed volume groups C<volgroups>.
2450 If activated, then they are made known to the
2451 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2452 then those devices disappear.
2453
2454 This command is the same as running C<vgchange -a y|n volgroups...>
2455
2456 Note that if C<volgroups> is an empty list then B<all> volume groups
2457 are activated or deactivated.");
2458
2459   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2460    [InitNone, Always, TestOutput (
2461       [["sfdiskM"; "/dev/sda"; ","];
2462        ["pvcreate"; "/dev/sda1"];
2463        ["vgcreate"; "VG"; "/dev/sda1"];
2464        ["lvcreate"; "LV"; "VG"; "10"];
2465        ["mkfs"; "ext2"; "/dev/VG/LV"];
2466        ["mount"; "/dev/VG/LV"; "/"];
2467        ["write_file"; "/new"; "test content"; "0"];
2468        ["umount"; "/"];
2469        ["lvresize"; "/dev/VG/LV"; "20"];
2470        ["e2fsck_f"; "/dev/VG/LV"];
2471        ["resize2fs"; "/dev/VG/LV"];
2472        ["mount"; "/dev/VG/LV"; "/"];
2473        ["cat"; "/new"]], "test content")],
2474    "resize an LVM logical volume",
2475    "\
2476 This resizes (expands or shrinks) an existing LVM logical
2477 volume to C<mbytes>.  When reducing, data in the reduced part
2478 is lost.");
2479
2480   ("resize2fs", (RErr, [Device "device"]), 106, [],
2481    [], (* lvresize tests this *)
2482    "resize an ext2/ext3 filesystem",
2483    "\
2484 This resizes an ext2 or ext3 filesystem to match the size of
2485 the underlying device.
2486
2487 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2488 on the C<device> before calling this command.  For unknown reasons
2489 C<resize2fs> sometimes gives an error about this and sometimes not.
2490 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2491 calling this function.");
2492
2493   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2494    [InitBasicFS, Always, TestOutputList (
2495       [["find"; "/"]], ["lost+found"]);
2496     InitBasicFS, Always, TestOutputList (
2497       [["touch"; "/a"];
2498        ["mkdir"; "/b"];
2499        ["touch"; "/b/c"];
2500        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2501     InitBasicFS, Always, TestOutputList (
2502       [["mkdir_p"; "/a/b/c"];
2503        ["touch"; "/a/b/c/d"];
2504        ["find"; "/a/b/"]], ["c"; "c/d"])],
2505    "find all files and directories",
2506    "\
2507 This command lists out all files and directories, recursively,
2508 starting at C<directory>.  It is essentially equivalent to
2509 running the shell command C<find directory -print> but some
2510 post-processing happens on the output, described below.
2511
2512 This returns a list of strings I<without any prefix>.  Thus
2513 if the directory structure was:
2514
2515  /tmp/a
2516  /tmp/b
2517  /tmp/c/d
2518
2519 then the returned list from C<guestfs_find> C</tmp> would be
2520 4 elements:
2521
2522  a
2523  b
2524  c
2525  c/d
2526
2527 If C<directory> is not a directory, then this command returns
2528 an error.
2529
2530 The returned list is sorted.
2531
2532 See also C<guestfs_find0>.");
2533
2534   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2535    [], (* lvresize tests this *)
2536    "check an ext2/ext3 filesystem",
2537    "\
2538 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2539 filesystem checker on C<device>, noninteractively (C<-p>),
2540 even if the filesystem appears to be clean (C<-f>).
2541
2542 This command is only needed because of C<guestfs_resize2fs>
2543 (q.v.).  Normally you should use C<guestfs_fsck>.");
2544
2545   ("sleep", (RErr, [Int "secs"]), 109, [],
2546    [InitNone, Always, TestRun (
2547       [["sleep"; "1"]])],
2548    "sleep for some seconds",
2549    "\
2550 Sleep for C<secs> seconds.");
2551
2552   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2553    [InitNone, Always, TestOutputInt (
2554       [["sfdiskM"; "/dev/sda"; ","];
2555        ["mkfs"; "ntfs"; "/dev/sda1"];
2556        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2557     InitNone, Always, TestOutputInt (
2558       [["sfdiskM"; "/dev/sda"; ","];
2559        ["mkfs"; "ext2"; "/dev/sda1"];
2560        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2561    "probe NTFS volume",
2562    "\
2563 This command runs the L<ntfs-3g.probe(8)> command which probes
2564 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2565 be mounted read-write, and some cannot be mounted at all).
2566
2567 C<rw> is a boolean flag.  Set it to true if you want to test
2568 if the volume can be mounted read-write.  Set it to false if
2569 you want to test if the volume can be mounted read-only.
2570
2571 The return value is an integer which C<0> if the operation
2572 would succeed, or some non-zero value documented in the
2573 L<ntfs-3g.probe(8)> manual page.");
2574
2575   ("sh", (RString "output", [String "command"]), 111, [],
2576    [], (* XXX needs tests *)
2577    "run a command via the shell",
2578    "\
2579 This call runs a command from the guest filesystem via the
2580 guest's C</bin/sh>.
2581
2582 This is like C<guestfs_command>, but passes the command to:
2583
2584  /bin/sh -c \"command\"
2585
2586 Depending on the guest's shell, this usually results in
2587 wildcards being expanded, shell expressions being interpolated
2588 and so on.
2589
2590 All the provisos about C<guestfs_command> apply to this call.");
2591
2592   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2593    [], (* XXX needs tests *)
2594    "run a command via the shell returning lines",
2595    "\
2596 This is the same as C<guestfs_sh>, but splits the result
2597 into a list of lines.
2598
2599 See also: C<guestfs_command_lines>");
2600
2601   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2602    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2603     * code in stubs.c, since all valid glob patterns must start with "/".
2604     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2605     *)
2606    [InitBasicFS, Always, TestOutputList (
2607       [["mkdir_p"; "/a/b/c"];
2608        ["touch"; "/a/b/c/d"];
2609        ["touch"; "/a/b/c/e"];
2610        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2611     InitBasicFS, Always, TestOutputList (
2612       [["mkdir_p"; "/a/b/c"];
2613        ["touch"; "/a/b/c/d"];
2614        ["touch"; "/a/b/c/e"];
2615        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2616     InitBasicFS, Always, TestOutputList (
2617       [["mkdir_p"; "/a/b/c"];
2618        ["touch"; "/a/b/c/d"];
2619        ["touch"; "/a/b/c/e"];
2620        ["glob_expand"; "/a/*/x/*"]], [])],
2621    "expand a wildcard path",
2622    "\
2623 This command searches for all the pathnames matching
2624 C<pattern> according to the wildcard expansion rules
2625 used by the shell.
2626
2627 If no paths match, then this returns an empty list
2628 (note: not an error).
2629
2630 It is just a wrapper around the C L<glob(3)> function
2631 with flags C<GLOB_MARK|GLOB_BRACE>.
2632 See that manual page for more details.");
2633
2634   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2635    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2636       [["scrub_device"; "/dev/sdc"]])],
2637    "scrub (securely wipe) a device",
2638    "\
2639 This command writes patterns over C<device> to make data retrieval
2640 more difficult.
2641
2642 It is an interface to the L<scrub(1)> program.  See that
2643 manual page for more details.");
2644
2645   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2646    [InitBasicFS, Always, TestRun (
2647       [["write_file"; "/file"; "content"; "0"];
2648        ["scrub_file"; "/file"]])],
2649    "scrub (securely wipe) a file",
2650    "\
2651 This command writes patterns over a file to make data retrieval
2652 more difficult.
2653
2654 The file is I<removed> after scrubbing.
2655
2656 It is an interface to the L<scrub(1)> program.  See that
2657 manual page for more details.");
2658
2659   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2660    [], (* XXX needs testing *)
2661    "scrub (securely wipe) free space",
2662    "\
2663 This command creates the directory C<dir> and then fills it
2664 with files until the filesystem is full, and scrubs the files
2665 as for C<guestfs_scrub_file>, and deletes them.
2666 The intention is to scrub any free space on the partition
2667 containing C<dir>.
2668
2669 It is an interface to the L<scrub(1)> program.  See that
2670 manual page for more details.");
2671
2672   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2673    [InitBasicFS, Always, TestRun (
2674       [["mkdir"; "/tmp"];
2675        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2676    "create a temporary directory",
2677    "\
2678 This command creates a temporary directory.  The
2679 C<template> parameter should be a full pathname for the
2680 temporary directory name with the final six characters being
2681 \"XXXXXX\".
2682
2683 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2684 the second one being suitable for Windows filesystems.
2685
2686 The name of the temporary directory that was created
2687 is returned.
2688
2689 The temporary directory is created with mode 0700
2690 and is owned by root.
2691
2692 The caller is responsible for deleting the temporary
2693 directory and its contents after use.
2694
2695 See also: L<mkdtemp(3)>");
2696
2697   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2698    [InitISOFS, Always, TestOutputInt (
2699       [["wc_l"; "/10klines"]], 10000)],
2700    "count lines in a file",
2701    "\
2702 This command counts the lines in a file, using the
2703 C<wc -l> external command.");
2704
2705   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2706    [InitISOFS, Always, TestOutputInt (
2707       [["wc_w"; "/10klines"]], 10000)],
2708    "count words in a file",
2709    "\
2710 This command counts the words in a file, using the
2711 C<wc -w> external command.");
2712
2713   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2714    [InitISOFS, Always, TestOutputInt (
2715       [["wc_c"; "/100kallspaces"]], 102400)],
2716    "count characters in a file",
2717    "\
2718 This command counts the characters in a file, using the
2719 C<wc -c> external command.");
2720
2721   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2722    [InitISOFS, Always, TestOutputList (
2723       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2724    "return first 10 lines of a file",
2725    "\
2726 This command returns up to the first 10 lines of a file as
2727 a list of strings.");
2728
2729   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2730    [InitISOFS, Always, TestOutputList (
2731       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732     InitISOFS, Always, TestOutputList (
2733       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2734     InitISOFS, Always, TestOutputList (
2735       [["head_n"; "0"; "/10klines"]], [])],
2736    "return first N lines of a file",
2737    "\
2738 If the parameter C<nrlines> is a positive number, this returns the first
2739 C<nrlines> lines of the file C<path>.
2740
2741 If the parameter C<nrlines> is a negative number, this returns lines
2742 from the file C<path>, excluding the last C<nrlines> lines.
2743
2744 If the parameter C<nrlines> is zero, this returns an empty list.");
2745
2746   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2747    [InitISOFS, Always, TestOutputList (
2748       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2749    "return last 10 lines of a file",
2750    "\
2751 This command returns up to the last 10 lines of a file as
2752 a list of strings.");
2753
2754   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2755    [InitISOFS, Always, TestOutputList (
2756       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757     InitISOFS, Always, TestOutputList (
2758       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2759     InitISOFS, Always, TestOutputList (
2760       [["tail_n"; "0"; "/10klines"]], [])],
2761    "return last N lines of a file",
2762    "\
2763 If the parameter C<nrlines> is a positive number, this returns the last
2764 C<nrlines> lines of the file C<path>.
2765
2766 If the parameter C<nrlines> is a negative number, this returns lines
2767 from the file C<path>, starting with the C<-nrlines>th line.
2768
2769 If the parameter C<nrlines> is zero, this returns an empty list.");
2770
2771   ("df", (RString "output", []), 125, [],
2772    [], (* XXX Tricky to test because it depends on the exact format
2773         * of the 'df' command and other imponderables.
2774         *)
2775    "report file system disk space usage",
2776    "\
2777 This command runs the C<df> command to report disk space used.
2778
2779 This command is mostly useful for interactive sessions.  It
2780 is I<not> intended that you try to parse the output string.
2781 Use C<statvfs> from programs.");
2782
2783   ("df_h", (RString "output", []), 126, [],
2784    [], (* XXX Tricky to test because it depends on the exact format
2785         * of the 'df' command and other imponderables.
2786         *)
2787    "report file system disk space usage (human readable)",
2788    "\
2789 This command runs the C<df -h> command to report disk space used
2790 in human-readable format.
2791
2792 This command is mostly useful for interactive sessions.  It
2793 is I<not> intended that you try to parse the output string.
2794 Use C<statvfs> from programs.");
2795
2796   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2799    "estimate file space usage",
2800    "\
2801 This command runs the C<du -s> command to estimate file space
2802 usage for C<path>.
2803
2804 C<path> can be a file or a directory.  If C<path> is a directory
2805 then the estimate includes the contents of the directory and all
2806 subdirectories (recursively).
2807
2808 The result is the estimated size in I<kilobytes>
2809 (ie. units of 1024 bytes).");
2810
2811   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2812    [InitISOFS, Always, TestOutputList (
2813       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2814    "list files in an initrd",
2815    "\
2816 This command lists out files contained in an initrd.
2817
2818 The files are listed without any initial C</> character.  The
2819 files are listed in the order they appear (not necessarily
2820 alphabetical).  Directory names are listed as separate items.
2821
2822 Old Linux kernels (2.4 and earlier) used a compressed ext2
2823 filesystem as initrd.  We I<only> support the newer initramfs
2824 format (compressed cpio files).");
2825
2826   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2827    [],
2828    "mount a file using the loop device",
2829    "\
2830 This command lets you mount C<file> (a filesystem image
2831 in a file) on a mount point.  It is entirely equivalent to
2832 the command C<mount -o loop file mountpoint>.");
2833
2834   ("mkswap", (RErr, [Device "device"]), 130, [],
2835    [InitEmpty, Always, TestRun (
2836       [["sfdiskM"; "/dev/sda"; ","];
2837        ["mkswap"; "/dev/sda1"]])],
2838    "create a swap partition",
2839    "\
2840 Create a swap partition on C<device>.");
2841
2842   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2843    [InitEmpty, Always, TestRun (
2844       [["sfdiskM"; "/dev/sda"; ","];
2845        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2846    "create a swap partition with a label",
2847    "\
2848 Create a swap partition on C<device> with label C<label>.
2849
2850 Note that you cannot attach a swap label to a block device
2851 (eg. C</dev/sda>), just to a partition.  This appears to be
2852 a limitation of the kernel or swap tools.");
2853
2854   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2855    (let uuid = uuidgen () in
2856     [InitEmpty, Always, TestRun (
2857        [["sfdiskM"; "/dev/sda"; ","];
2858         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2859    "create a swap partition with an explicit UUID",
2860    "\
2861 Create a swap partition on C<device> with UUID C<uuid>.");
2862
2863   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2864    [InitBasicFS, Always, TestOutputStruct (
2865       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2866        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2867        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2868     InitBasicFS, Always, TestOutputStruct (
2869       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2870        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2871    "make block, character or FIFO devices",
2872    "\
2873 This call creates block or character special devices, or
2874 named pipes (FIFOs).
2875
2876 The C<mode> parameter should be the mode, using the standard
2877 constants.  C<devmajor> and C<devminor> are the
2878 device major and minor numbers, only used when creating block
2879 and character special devices.");
2880
2881   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2882    [InitBasicFS, Always, TestOutputStruct (
2883       [["mkfifo"; "0o777"; "/node"];
2884        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2885    "make FIFO (named pipe)",
2886    "\
2887 This call creates a FIFO (named pipe) called C<path> with
2888 mode C<mode>.  It is just a convenient wrapper around
2889 C<guestfs_mknod>.");
2890
2891   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2892    [InitBasicFS, Always, TestOutputStruct (
2893       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2894        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2895    "make block device node",
2896    "\
2897 This call creates a block device node called C<path> with
2898 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2899 It is just a convenient wrapper around C<guestfs_mknod>.");
2900
2901   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2902    [InitBasicFS, Always, TestOutputStruct (
2903       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2904        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2905    "make char device node",
2906    "\
2907 This call creates a char device node called C<path> with
2908 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2909 It is just a convenient wrapper around C<guestfs_mknod>.");
2910
2911   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2912    [], (* XXX umask is one of those stateful things that we should
2913         * reset between each test.
2914         *)
2915    "set file mode creation mask (umask)",
2916    "\
2917 This function sets the mask used for creating new files and
2918 device nodes to C<mask & 0777>.
2919
2920 Typical umask values would be C<022> which creates new files
2921 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2922 C<002> which creates new files with permissions like
2923 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2924
2925 The default umask is C<022>.  This is important because it
2926 means that directories and device nodes will be created with
2927 C<0644> or C<0755> mode even if you specify C<0777>.
2928
2929 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2930
2931 This call returns the previous umask.");
2932
2933   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2934    [],
2935    "read directories entries",
2936    "\
2937 This returns the list of directory entries in directory C<dir>.
2938
2939 All entries in the directory are returned, including C<.> and
2940 C<..>.  The entries are I<not> sorted, but returned in the same
2941 order as the underlying filesystem.
2942
2943 Also this call returns basic file type information about each
2944 file.  The C<ftyp> field will contain one of the following characters:
2945
2946 =over 4
2947
2948 =item 'b'
2949
2950 Block special
2951
2952 =item 'c'
2953
2954 Char special
2955
2956 =item 'd'
2957
2958 Directory
2959
2960 =item 'f'
2961
2962 FIFO (named pipe)
2963
2964 =item 'l'
2965
2966 Symbolic link
2967
2968 =item 'r'
2969
2970 Regular file
2971
2972 =item 's'
2973
2974 Socket
2975
2976 =item 'u'
2977
2978 Unknown file type
2979
2980 =item '?'
2981
2982 The L<readdir(3)> returned a C<d_type> field with an
2983 unexpected value
2984
2985 =back
2986
2987 This function is primarily intended for use by programs.  To
2988 get a simple list of names, use C<guestfs_ls>.  To get a printable
2989 directory for human consumption, use C<guestfs_ll>.");
2990
2991   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2992    [],
2993    "create partitions on a block device",
2994    "\
2995 This is a simplified interface to the C<guestfs_sfdisk>
2996 command, where partition sizes are specified in megabytes
2997 only (rounded to the nearest cylinder) and you don't need
2998 to specify the cyls, heads and sectors parameters which
2999 were rarely if ever used anyway.
3000
3001 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3002
3003   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3004    [],
3005    "determine file type inside a compressed file",
3006    "\
3007 This command runs C<file> after first decompressing C<path>
3008 using C<method>.
3009
3010 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3011
3012 Since 1.0.63, use C<guestfs_file> instead which can now
3013 process compressed files.");
3014
3015   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3016    [],
3017    "list extended attributes of a file or directory",
3018    "\
3019 This call lists the extended attributes of the file or directory
3020 C<path>.
3021
3022 At the system call level, this is a combination of the
3023 L<listxattr(2)> and L<getxattr(2)> calls.
3024
3025 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3026
3027   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3028    [],
3029    "list extended attributes of a file or directory",
3030    "\
3031 This is the same as C<guestfs_getxattrs>, but if C<path>
3032 is a symbolic link, then it returns the extended attributes
3033 of the link itself.");
3034
3035   ("setxattr", (RErr, [String "xattr";
3036                        String "val"; Int "vallen"; (* will be BufferIn *)
3037                        Pathname "path"]), 143, [],
3038    [],
3039    "set extended attribute of a file or directory",
3040    "\
3041 This call sets the extended attribute named C<xattr>
3042 of the file C<path> to the value C<val> (of length C<vallen>).
3043 The value is arbitrary 8 bit data.
3044
3045 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3046
3047   ("lsetxattr", (RErr, [String "xattr";
3048                         String "val"; Int "vallen"; (* will be BufferIn *)
3049                         Pathname "path"]), 144, [],
3050    [],
3051    "set extended attribute of a file or directory",
3052    "\
3053 This is the same as C<guestfs_setxattr>, but if C<path>
3054 is a symbolic link, then it sets an extended attribute
3055 of the link itself.");
3056
3057   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3058    [],
3059    "remove extended attribute of a file or directory",
3060    "\
3061 This call removes the extended attribute named C<xattr>
3062 of the file C<path>.
3063
3064 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3065
3066   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3067    [],
3068    "remove extended attribute of a file or directory",
3069    "\
3070 This is the same as C<guestfs_removexattr>, but if C<path>
3071 is a symbolic link, then it removes an extended attribute
3072 of the link itself.");
3073
3074   ("mountpoints", (RHashtable "mps", []), 147, [],
3075    [],
3076    "show mountpoints",
3077    "\
3078 This call is similar to C<guestfs_mounts>.  That call returns
3079 a list of devices.  This one returns a hash table (map) of
3080 device name to directory where the device is mounted.");
3081
3082   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3083   (* This is a special case: while you would expect a parameter
3084    * of type "Pathname", that doesn't work, because it implies
3085    * NEED_ROOT in the generated calling code in stubs.c, and
3086    * this function cannot use NEED_ROOT.
3087    *)
3088    [],
3089    "create a mountpoint",
3090    "\
3091 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3092 specialized calls that can be used to create extra mountpoints
3093 before mounting the first filesystem.
3094
3095 These calls are I<only> necessary in some very limited circumstances,
3096 mainly the case where you want to mount a mix of unrelated and/or
3097 read-only filesystems together.
3098
3099 For example, live CDs often contain a \"Russian doll\" nest of
3100 filesystems, an ISO outer layer, with a squashfs image inside, with
3101 an ext2/3 image inside that.  You can unpack this as follows
3102 in guestfish:
3103
3104  add-ro Fedora-11-i686-Live.iso
3105  run
3106  mkmountpoint /cd
3107  mkmountpoint /squash
3108  mkmountpoint /ext3
3109  mount /dev/sda /cd
3110  mount-loop /cd/LiveOS/squashfs.img /squash
3111  mount-loop /squash/LiveOS/ext3fs.img /ext3
3112
3113 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3114
3115   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3116    [],
3117    "remove a mountpoint",
3118    "\
3119 This calls removes a mountpoint that was previously created
3120 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3121 for full details.");
3122
3123   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3124    [InitISOFS, Always, TestOutputBuffer (
3125       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3126    "read a file",
3127    "\
3128 This calls returns the contents of the file C<path> as a
3129 buffer.
3130
3131 Unlike C<guestfs_cat>, this function can correctly
3132 handle files that contain embedded ASCII NUL characters.
3133 However unlike C<guestfs_download>, this function is limited
3134 in the total size of file that can be handled.");
3135
3136   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3137    [InitISOFS, Always, TestOutputList (
3138       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3139     InitISOFS, Always, TestOutputList (
3140       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3141    "return lines matching a pattern",
3142    "\
3143 This calls the external C<grep> program and returns the
3144 matching lines.");
3145
3146   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3147    [InitISOFS, Always, TestOutputList (
3148       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3149    "return lines matching a pattern",
3150    "\
3151 This calls the external C<egrep> program and returns the
3152 matching lines.");
3153
3154   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3155    [InitISOFS, Always, TestOutputList (
3156       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3157    "return lines matching a pattern",
3158    "\
3159 This calls the external C<fgrep> program and returns the
3160 matching lines.");
3161
3162   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3163    [InitISOFS, Always, TestOutputList (
3164       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3165    "return lines matching a pattern",
3166    "\
3167 This calls the external C<grep -i> program and returns the
3168 matching lines.");
3169
3170   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3171    [InitISOFS, Always, TestOutputList (
3172       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3173    "return lines matching a pattern",
3174    "\
3175 This calls the external C<egrep -i> program and returns the
3176 matching lines.");
3177
3178   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3179    [InitISOFS, Always, TestOutputList (
3180       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3181    "return lines matching a pattern",
3182    "\
3183 This calls the external C<fgrep -i> program and returns the
3184 matching lines.");
3185
3186   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3187    [InitISOFS, Always, TestOutputList (
3188       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3189    "return lines matching a pattern",
3190    "\
3191 This calls the external C<zgrep> program and returns the
3192 matching lines.");
3193
3194   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3195    [InitISOFS, Always, TestOutputList (
3196       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3197    "return lines matching a pattern",
3198    "\
3199 This calls the external C<zegrep> program and returns the
3200 matching lines.");
3201
3202   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3203    [InitISOFS, Always, TestOutputList (
3204       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3205    "return lines matching a pattern",
3206    "\
3207 This calls the external C<zfgrep> program and returns the
3208 matching lines.");
3209
3210   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3211    [InitISOFS, Always, TestOutputList (
3212       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3213    "return lines matching a pattern",
3214    "\
3215 This calls the external C<zgrep -i> program and returns the
3216 matching lines.");
3217
3218   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3219    [InitISOFS, Always, TestOutputList (
3220       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3221    "return lines matching a pattern",
3222    "\
3223 This calls the external C<zegrep -i> program and returns the
3224 matching lines.");
3225
3226   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3227    [InitISOFS, Always, TestOutputList (
3228       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3229    "return lines matching a pattern",
3230    "\
3231 This calls the external C<zfgrep -i> program and returns the
3232 matching lines.");
3233
3234   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3235    [InitISOFS, Always, TestOutput (
3236       [["realpath"; "/../directory"]], "/directory")],
3237    "canonicalized absolute pathname",
3238    "\
3239 Return the canonicalized absolute pathname of C<path>.  The
3240 returned path has no C<.>, C<..> or symbolic link path elements.");
3241
3242   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3243    [InitBasicFS, Always, TestOutputStruct (
3244       [["touch"; "/a"];
3245        ["ln"; "/a"; "/b"];
3246        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3247    "create a hard link",
3248    "\
3249 This command creates a hard link using the C<ln> command.");
3250
3251   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3252    [InitBasicFS, Always, TestOutputStruct (
3253       [["touch"; "/a"];
3254        ["touch"; "/b"];
3255        ["ln_f"; "/a"; "/b"];
3256        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3257    "create a hard link",
3258    "\
3259 This command creates a hard link using the C<ln -f> command.
3260 The C<-f> option removes the link (C<linkname>) if it exists already.");
3261
3262   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3263    [InitBasicFS, Always, TestOutputStruct (
3264       [["touch"; "/a"];
3265        ["ln_s"; "a"; "/b"];
3266        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3267    "create a symbolic link",
3268    "\
3269 This command creates a symbolic link using the C<ln -s> command.");
3270
3271   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3272    [InitBasicFS, Always, TestOutput (
3273       [["mkdir_p"; "/a/b"];
3274        ["touch"; "/a/b/c"];
3275        ["ln_sf"; "../d"; "/a/b/c"];
3276        ["readlink"; "/a/b/c"]], "../d")],
3277    "create a symbolic link",
3278    "\
3279 This command creates a symbolic link using the C<ln -sf> command,
3280 The C<-f> option removes the link (C<linkname>) if it exists already.");
3281
3282   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3283    [] (* XXX tested above *),
3284    "read the target of a symbolic link",
3285    "\
3286 This command reads the target of a symbolic link.");
3287
3288   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3289    [InitBasicFS, Always, TestOutputStruct (
3290       [["fallocate"; "/a"; "1000000"];
3291        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3292    "preallocate a file in the guest filesystem",
3293    "\
3294 This command preallocates a file (containing zero bytes) named
3295 C<path> of size C<len> bytes.  If the file exists already, it
3296 is overwritten.
3297
3298 Do not confuse this with the guestfish-specific
3299 C<alloc> command which allocates a file in the host and
3300 attaches it as a device.");
3301
3302   ("swapon_device", (RErr, [Device "device"]), 170, [],
3303    [InitPartition, Always, TestRun (
3304       [["mkswap"; "/dev/sda1"];
3305        ["swapon_device"; "/dev/sda1"];
3306        ["swapoff_device"; "/dev/sda1"]])],
3307    "enable swap on device",
3308    "\
3309 This command enables the libguestfs appliance to use the
3310 swap device or partition named C<device>.  The increased
3311 memory is made available for all commands, for example
3312 those run using C<guestfs_command> or C<guestfs_sh>.
3313
3314 Note that you should not swap to existing guest swap
3315 partitions unless you know what you are doing.  They may
3316 contain hibernation information, or other information that
3317 the guest doesn't want you to trash.  You also risk leaking
3318 information about the host to the guest this way.  Instead,
3319 attach a new host device to the guest and swap on that.");
3320
3321   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3322    [], (* XXX tested by swapon_device *)
3323    "disable swap on device",
3324    "\
3325 This command disables the libguestfs appliance swap
3326 device or partition named C<device>.
3327 See C<guestfs_swapon_device>.");
3328
3329   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3330    [InitBasicFS, Always, TestRun (
3331       [["fallocate"; "/swap"; "8388608"];
3332        ["mkswap_file"; "/swap"];
3333        ["swapon_file"; "/swap"];
3334        ["swapoff_file"; "/swap"]])],
3335    "enable swap on file",
3336    "\
3337 This command enables swap to a file.
3338 See C<guestfs_swapon_device> for other notes.");
3339
3340   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3341    [], (* XXX tested by swapon_file *)
3342    "disable swap on file",
3343    "\
3344 This command disables the libguestfs appliance swap on file.");
3345
3346   ("swapon_label", (RErr, [String "label"]), 174, [],
3347    [InitEmpty, Always, TestRun (
3348       [["sfdiskM"; "/dev/sdb"; ","];
3349        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3350        ["swapon_label"; "swapit"];
3351        ["swapoff_label"; "swapit"];
3352        ["zero"; "/dev/sdb"];
3353        ["blockdev_rereadpt"; "/dev/sdb"]])],
3354    "enable swap on labeled swap partition",
3355    "\
3356 This command enables swap to a labeled swap partition.
3357 See C<guestfs_swapon_device> for other notes.");
3358
3359   ("swapoff_label", (RErr, [String "label"]), 175, [],
3360    [], (* XXX tested by swapon_label *)
3361    "disable swap on labeled swap partition",
3362    "\
3363 This command disables the libguestfs appliance swap on
3364 labeled swap partition.");
3365
3366   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3367    (let uuid = uuidgen () in
3368     [InitEmpty, Always, TestRun (
3369        [["mkswap_U"; uuid; "/dev/sdb"];
3370         ["swapon_uuid"; uuid];
3371         ["swapoff_uuid"; uuid]])]),
3372    "enable swap on swap partition by UUID",
3373    "\
3374 This command enables swap to a swap partition with the given UUID.
3375 See C<guestfs_swapon_device> for other notes.");
3376
3377   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3378    [], (* XXX tested by swapon_uuid *)
3379    "disable swap on swap partition by UUID",
3380    "\
3381 This command disables the libguestfs appliance swap partition
3382 with the given UUID.");
3383
3384   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3385    [InitBasicFS, Always, TestRun (
3386       [["fallocate"; "/swap"; "8388608"];
3387        ["mkswap_file"; "/swap"]])],
3388    "create a swap file",
3389    "\
3390 Create a swap file.
3391
3392 This command just writes a swap file signature to an existing
3393 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3394
3395   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3396    [InitISOFS, Always, TestRun (
3397       [["inotify_init"; "0"]])],
3398    "create an inotify handle",
3399    "\
3400 This command creates a new inotify handle.
3401 The inotify subsystem can be used to notify events which happen to
3402 objects in the guest filesystem.
3403
3404 C<maxevents> is the maximum number of events which will be
3405 queued up between calls to C<guestfs_inotify_read> or
3406 C<guestfs_inotify_files>.
3407 If this is passed as C<0>, then the kernel (or previously set)
3408 default is used.  For Linux 2.6.29 the default was 16384 events.
3409 Beyond this limit, the kernel throws away events, but records
3410 the fact that it threw them away by setting a flag
3411 C<IN_Q_OVERFLOW> in the returned structure list (see
3412 C<guestfs_inotify_read>).
3413
3414 Before any events are generated, you have to add some
3415 watches to the internal watch list.  See:
3416 C<guestfs_inotify_add_watch>,
3417 C<guestfs_inotify_rm_watch> and
3418 C<guestfs_inotify_watch_all>.
3419
3420 Queued up events should be read periodically by calling
3421 C<guestfs_inotify_read>
3422 (or C<guestfs_inotify_files> which is just a helpful
3423 wrapper around C<guestfs_inotify_read>).  If you don't
3424 read the events out often enough then you risk the internal
3425 queue overflowing.
3426
3427 The handle should be closed after use by calling
3428 C<guestfs_inotify_close>.  This also removes any
3429 watches automatically.
3430
3431 See also L<inotify(7)> for an overview of the inotify interface
3432 as exposed by the Linux kernel, which is roughly what we expose
3433 via libguestfs.  Note that there is one global inotify handle
3434 per libguestfs instance.");
3435
3436   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3437    [InitBasicFS, Always, TestOutputList (
3438       [["inotify_init"; "0"];
3439        ["inotify_add_watch"; "/"; "1073741823"];
3440        ["touch"; "/a"];
3441        ["touch"; "/b"];
3442        ["inotify_files"]], ["a"; "b"])],
3443    "add an inotify watch",
3444    "\
3445 Watch C<path> for the events listed in C<mask>.
3446
3447 Note that if C<path> is a directory then events within that
3448 directory are watched, but this does I<not> happen recursively
3449 (in subdirectories).
3450
3451 Note for non-C or non-Linux callers: the inotify events are
3452 defined by the Linux kernel ABI and are listed in
3453 C</usr/include/sys/inotify.h>.");
3454
3455   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3456    [],
3457    "remove an inotify watch",
3458    "\
3459 Remove a previously defined inotify watch.
3460 See C<guestfs_inotify_add_watch>.");
3461
3462   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3463    [],
3464    "return list of inotify events",
3465    "\
3466 Return the complete queue of events that have happened
3467 since the previous read call.
3468
3469 If no events have happened, this returns an empty list.
3470
3471 I<Note>: In order to make sure that all events have been
3472 read, you must call this function repeatedly until it
3473 returns an empty list.  The reason is that the call will
3474 read events up to the maximum appliance-to-host message
3475 size and leave remaining events in the queue.");
3476
3477   ("inotify_files", (RStringList "paths", []), 183, [],
3478    [],
3479    "return list of watched files that had events",
3480    "\
3481 This function is a helpful wrapper around C<guestfs_inotify_read>
3482 which just returns a list of pathnames of objects that were
3483 touched.  The returned pathnames are sorted and deduplicated.");
3484
3485   ("inotify_close", (RErr, []), 184, [],
3486    [],
3487    "close the inotify handle",
3488    "\
3489 This closes the inotify handle which was previously
3490 opened by inotify_init.  It removes all watches, throws
3491 away any pending events, and deallocates all resources.");
3492
3493   ("setcon", (RErr, [String "context"]), 185, [],
3494    [],
3495    "set SELinux security context",
3496    "\
3497 This sets the SELinux security context of the daemon
3498 to the string C<context>.
3499
3500 See the documentation about SELINUX in L<guestfs(3)>.");
3501
3502   ("getcon", (RString "context", []), 186, [],
3503    [],
3504    "get SELinux security context",
3505    "\
3506 This gets the SELinux security context of the daemon.
3507
3508 See the documentation about SELINUX in L<guestfs(3)>,
3509 and C<guestfs_setcon>");
3510
3511   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3512    [InitEmpty, Always, TestOutput (
3513       [["sfdiskM"; "/dev/sda"; ","];
3514        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3515        ["mount"; "/dev/sda1"; "/"];
3516        ["write_file"; "/new"; "new file contents"; "0"];
3517        ["cat"; "/new"]], "new file contents")],
3518    "make a filesystem with block size",
3519    "\
3520 This call is similar to C<guestfs_mkfs>, but it allows you to
3521 control the block size of the resulting filesystem.  Supported
3522 block sizes depend on the filesystem type, but typically they
3523 are C<1024>, C<2048> or C<4096> only.");
3524
3525   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3526    [InitEmpty, Always, TestOutput (
3527       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3528        ["mke2journal"; "4096"; "/dev/sda1"];
3529        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3530        ["mount"; "/dev/sda2"; "/"];
3531        ["write_file"; "/new"; "new file contents"; "0"];
3532        ["cat"; "/new"]], "new file contents")],
3533    "make ext2/3/4 external journal",
3534    "\
3535 This creates an ext2 external journal on C<device>.  It is equivalent
3536 to the command:
3537
3538  mke2fs -O journal_dev -b blocksize device");
3539
3540   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3541    [InitEmpty, Always, TestOutput (
3542       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3543        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3544        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3545        ["mount"; "/dev/sda2"; "/"];
3546        ["write_file"; "/new"; "new file contents"; "0"];
3547        ["cat"; "/new"]], "new file contents")],
3548    "make ext2/3/4 external journal with label",
3549    "\
3550 This creates an ext2 external journal on C<device> with label C<label>.");
3551
3552   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3553    (let uuid = uuidgen () in
3554     [InitEmpty, Always, TestOutput (
3555        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3556         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3557         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3558         ["mount"; "/dev/sda2"; "/"];
3559         ["write_file"; "/new"; "new file contents"; "0"];
3560         ["cat"; "/new"]], "new file contents")]),
3561    "make ext2/3/4 external journal with UUID",
3562    "\
3563 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3564
3565   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3566    [],
3567    "make ext2/3/4 filesystem with external journal",
3568    "\
3569 This creates an ext2/3/4 filesystem on C<device> with
3570 an external journal on C<journal>.  It is equivalent
3571 to the command:
3572
3573  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3574
3575 See also C<guestfs_mke2journal>.");
3576
3577   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3578    [],
3579    "make ext2/3/4 filesystem with external journal",
3580    "\
3581 This creates an ext2/3/4 filesystem on C<device> with
3582 an external journal on the journal labeled C<label>.
3583
3584 See also C<guestfs_mke2journal_L>.");
3585
3586   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3587    [],
3588    "make ext2/3/4 filesystem with external journal",
3589    "\
3590 This creates an ext2/3/4 filesystem on C<device> with
3591 an external journal on the journal with UUID C<uuid>.
3592
3593 See also C<guestfs_mke2journal_U>.");
3594
3595   ("modprobe", (RErr, [String "modulename"]), 194, [],
3596    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3597    "load a kernel module",
3598    "\
3599 This loads a kernel module in the appliance.
3600
3601 The kernel module must have been whitelisted when libguestfs
3602 was built (see C<appliance/kmod.whitelist.in> in the source).");
3603
3604   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3605    [InitNone, Always, TestOutput (
3606      [["echo_daemon"; "This is a test"]], "This is a test"
3607    )],
3608    "echo arguments back to the client",
3609    "\
3610 This command concatenate the list of C<words> passed with single spaces between
3611 them and returns the resulting string.
3612
3613 You can use this command to test the connection through to the daemon.
3614
3615 See also C<guestfs_ping_daemon>.");
3616
3617   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3618    [], (* There is a regression test for this. *)
3619    "find all files and directories, returning NUL-separated list",
3620    "\
3621 This command lists out all files and directories, recursively,
3622 starting at C<directory>, placing the resulting list in the
3623 external file called C<files>.
3624
3625 This command works the same way as C<guestfs_find> with the
3626 following exceptions:
3627
3628 =over 4
3629
3630 =item *
3631
3632 The resulting list is written to an external file.
3633
3634 =item *
3635
3636 Items (filenames) in the result are separated
3637 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3638
3639 =item *
3640
3641 This command is not limited in the number of names that it
3642 can return.
3643
3644 =item *
3645
3646 The result list is not sorted.
3647
3648 =back");
3649
3650   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3651    [InitISOFS, Always, TestOutput (
3652       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3653     InitISOFS, Always, TestOutput (
3654       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3655     InitISOFS, Always, TestOutput (
3656       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3657     InitISOFS, Always, TestLastFail (
3658       [["case_sensitive_path"; "/Known-1/"]]);
3659     InitBasicFS, Always, TestOutput (
3660       [["mkdir"; "/a"];
3661        ["mkdir"; "/a/bbb"];
3662        ["touch"; "/a/bbb/c"];
3663        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3664     InitBasicFS, Always, TestOutput (
3665       [["mkdir"; "/a"];
3666        ["mkdir"; "/a/bbb"];
3667        ["touch"; "/a/bbb/c"];
3668        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3669     InitBasicFS, Always, TestLastFail (
3670       [["mkdir"; "/a"];
3671        ["mkdir"; "/a/bbb"];
3672        ["touch"; "/a/bbb/c"];
3673        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3674    "return true path on case-insensitive filesystem",
3675    "\
3676 This can be used to resolve case insensitive paths on
3677 a filesystem which is case sensitive.  The use case is
3678 to resolve paths which you have read from Windows configuration
3679 files or the Windows Registry, to the true path.
3680
3681 The command handles a peculiarity of the Linux ntfs-3g
3682 filesystem driver (and probably others), which is that although
3683 the underlying filesystem is case-insensitive, the driver
3684 exports the filesystem to Linux as case-sensitive.
3685
3686 One consequence of this is that special directories such
3687 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3688 (or other things) depending on the precise details of how
3689 they were created.  In Windows itself this would not be
3690 a problem.
3691
3692 Bug or feature?  You decide:
3693 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3694
3695 This function resolves the true case of each element in the
3696 path and returns the case-sensitive path.
3697
3698 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3699 might return C<\"/WINDOWS/system32\"> (the exact return value
3700 would depend on details of how the directories were originally
3701 created under Windows).
3702
3703 I<Note>:
3704 This function does not handle drive names, backslashes etc.
3705
3706 See also C<guestfs_realpath>.");
3707
3708   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3709    [InitBasicFS, Always, TestOutput (
3710       [["vfs_type"; "/dev/sda1"]], "ext2")],
3711    "get the Linux VFS type corresponding to a mounted device",
3712    "\
3713 This command gets the block device type corresponding to
3714 a mounted device called C<device>.
3715
3716 Usually the result is the name of the Linux VFS module that
3717 is used to mount this device (probably determined automatically
3718 if you used the C<guestfs_mount> call).");
3719
3720   ("truncate", (RErr, [Pathname "path"]), 199, [],
3721    [InitBasicFS, Always, TestOutputStruct (
3722       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3723        ["truncate"; "/test"];
3724        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3725    "truncate a file to zero size",
3726    "\
3727 This command truncates C<path> to a zero-length file.  The
3728 file must exist already.");
3729
3730   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3731    [InitBasicFS, Always, TestOutputStruct (
3732       [["touch"; "/test"];
3733        ["truncate_size"; "/test"; "1000"];
3734        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3735    "truncate a file to a particular size",
3736    "\
3737 This command truncates C<path> to size C<size> bytes.  The file
3738 must exist already.  If the file is smaller than C<size> then
3739 the file is extended to the required size with null bytes.");
3740
3741   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3742    [InitBasicFS, Always, TestOutputStruct (
3743       [["touch"; "/test"];
3744        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3745        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3746    "set timestamp of a file with nanosecond precision",
3747    "\
3748 This command sets the timestamps of a file with nanosecond
3749 precision.
3750
3751 C<atsecs, atnsecs> are the last access time (atime) in secs and
3752 nanoseconds from the epoch.
3753
3754 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3755 secs and nanoseconds from the epoch.
3756
3757 If the C<*nsecs> field contains the special value C<-1> then
3758 the corresponding timestamp is set to the current time.  (The
3759 C<*secs> field is ignored in this case).
3760
3761 If the C<*nsecs> field contains the special value C<-2> then
3762 the corresponding timestamp is left unchanged.  (The
3763 C<*secs> field is ignored in this case).");
3764
3765   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3766    [InitBasicFS, Always, TestOutputStruct (
3767       [["mkdir_mode"; "/test"; "0o111"];
3768        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3769    "create a directory with a particular mode",
3770    "\
3771 This command creates a directory, setting the initial permissions
3772 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3773
3774   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3775    [], (* XXX *)
3776    "change file owner and group",
3777    "\
3778 Change the file owner to C<owner> and group to C<group>.
3779 This is like C<guestfs_chown> but if C<path> is a symlink then
3780 the link itself is changed, not the target.
3781
3782 Only numeric uid and gid are supported.  If you want to use
3783 names, you will need to locate and parse the password file
3784 yourself (Augeas support makes this relatively easy).");
3785
3786 ]
3787
3788 let all_functions = non_daemon_functions @ daemon_functions
3789
3790 (* In some places we want the functions to be displayed sorted
3791  * alphabetically, so this is useful:
3792  *)
3793 let all_functions_sorted =
3794   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3795                compare n1 n2) all_functions
3796
3797 (* Field types for structures. *)
3798 type field =
3799   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3800   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3801   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3802   | FUInt32
3803   | FInt32
3804   | FUInt64
3805   | FInt64
3806   | FBytes                      (* Any int measure that counts bytes. *)
3807   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3808   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3809
3810 (* Because we generate extra parsing code for LVM command line tools,
3811  * we have to pull out the LVM columns separately here.
3812  *)
3813 let lvm_pv_cols = [
3814   "pv_name", FString;
3815   "pv_uuid", FUUID;
3816   "pv_fmt", FString;
3817   "pv_size", FBytes;
3818   "dev_size", FBytes;
3819   "pv_free", FBytes;
3820   "pv_used", FBytes;
3821   "pv_attr", FString (* XXX *);
3822   "pv_pe_count", FInt64;
3823   "pv_pe_alloc_count", FInt64;
3824   "pv_tags", FString;
3825   "pe_start", FBytes;
3826   "pv_mda_count", FInt64;
3827   "pv_mda_free", FBytes;
3828   (* Not in Fedora 10:
3829      "pv_mda_size", FBytes;
3830   *)
3831 ]
3832 let lvm_vg_cols = [
3833   "vg_name", FString;
3834   "vg_uuid", FUUID;
3835   "vg_fmt", FString;
3836   "vg_attr", FString (* XXX *);
3837   "vg_size", FBytes;
3838   "vg_free", FBytes;
3839   "vg_sysid", FString;
3840   "vg_extent_size", FBytes;
3841   "vg_extent_count", FInt64;
3842   "vg_free_count", FInt64;
3843   "max_lv", FInt64;
3844   "max_pv", FInt64;
3845   "pv_count", FInt64;
3846   "lv_count", FInt64;
3847   "snap_count", FInt64;
3848   "vg_seqno", FInt64;
3849   "vg_tags", FString;
3850   "vg_mda_count", FInt64;
3851   "vg_mda_free", FBytes;
3852   (* Not in Fedora 10:
3853      "vg_mda_size", FBytes;
3854   *)
3855 ]
3856 let lvm_lv_cols = [
3857   "lv_name", FString;
3858   "lv_uuid", FUUID;
3859   "lv_attr", FString (* XXX *);
3860   "lv_major", FInt64;
3861   "lv_minor", FInt64;
3862   "lv_kernel_major", FInt64;
3863   "lv_kernel_minor", FInt64;
3864   "lv_size", FBytes;
3865   "seg_count", FInt64;
3866   "origin", FString;
3867   "snap_percent", FOptPercent;
3868   "copy_percent", FOptPercent;
3869   "move_pv", FString;
3870   "lv_tags", FString;
3871   "mirror_log", FString;
3872   "modules", FString;
3873 ]
3874
3875 (* Names and fields in all structures (in RStruct and RStructList)
3876  * that we support.
3877  *)
3878 let structs = [
3879   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3880    * not use this struct in any new code.
3881    *)
3882   "int_bool", [
3883     "i", FInt32;                (* for historical compatibility *)
3884     "b", FInt32;                (* for historical compatibility *)
3885   ];
3886
3887   (* LVM PVs, VGs, LVs. *)
3888   "lvm_pv", lvm_pv_cols;
3889   "lvm_vg", lvm_vg_cols;
3890   "lvm_lv", lvm_lv_cols;
3891
3892   (* Column names and types from stat structures.
3893    * NB. Can't use things like 'st_atime' because glibc header files
3894    * define some of these as macros.  Ugh.
3895    *)
3896   "stat", [
3897     "dev", FInt64;
3898     "ino", FInt64;
3899     "mode", FInt64;
3900     "nlink", FInt64;
3901     "uid", FInt64;
3902     "gid", FInt64;
3903     "rdev", FInt64;
3904     "size", FInt64;
3905     "blksize", FInt64;
3906     "blocks", FInt64;
3907     "atime", FInt64;
3908     "mtime", FInt64;
3909     "ctime", FInt64;
3910   ];
3911   "statvfs", [
3912     "bsize", FInt64;
3913     "frsize", FInt64;
3914     "blocks", FInt64;
3915     "bfree", FInt64;
3916     "bavail", FInt64;
3917     "files", FInt64;
3918     "ffree", FInt64;
3919     "favail", FInt64;
3920     "fsid", FInt64;
3921     "flag", FInt64;
3922     "namemax", FInt64;
3923   ];
3924
3925   (* Column names in dirent structure. *)
3926   "dirent", [
3927     "ino", FInt64;
3928     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3929     "ftyp", FChar;
3930     "name", FString;
3931   ];
3932
3933   (* Version numbers. *)
3934   "version", [
3935     "major", FInt64;
3936     "minor", FInt64;
3937     "release", FInt64;
3938     "extra", FString;
3939   ];
3940
3941   (* Extended attribute. *)
3942   "xattr", [
3943     "attrname", FString;
3944     "attrval", FBuffer;
3945   ];
3946
3947   (* Inotify events. *)
3948   "inotify_event", [
3949     "in_wd", FInt64;
3950     "in_mask", FUInt32;
3951     "in_cookie", FUInt32;
3952     "in_name", FString;
3953   ];
3954 ] (* end of structs *)
3955
3956 (* Ugh, Java has to be different ..
3957  * These names are also used by the Haskell bindings.
3958  *)
3959 let java_structs = [
3960   "int_bool", "IntBool";
3961   "lvm_pv", "PV";
3962   "lvm_vg", "VG";
3963   "lvm_lv", "LV";
3964   "stat", "Stat";
3965   "statvfs", "StatVFS";
3966   "dirent", "Dirent";
3967   "version", "Version";
3968   "xattr", "XAttr";
3969   "inotify_event", "INotifyEvent";
3970 ]
3971
3972 (* What structs are actually returned. *)
3973 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3974
3975 (* Returns a list of RStruct/RStructList structs that are returned
3976  * by any function.  Each element of returned list is a pair:
3977  *
3978  * (structname, RStructOnly)
3979  *    == there exists function which returns RStruct (_, structname)
3980  * (structname, RStructListOnly)
3981  *    == there exists function which returns RStructList (_, structname)
3982  * (structname, RStructAndList)
3983  *    == there are functions returning both RStruct (_, structname)
3984  *                                      and RStructList (_, structname)
3985  *)
3986 let rstructs_used_by functions =
3987   (* ||| is a "logical OR" for rstructs_used_t *)
3988   let (|||) a b =
3989     match a, b with
3990     | RStructAndList, _
3991     | _, RStructAndList -> RStructAndList
3992     | RStructOnly, RStructListOnly
3993     | RStructListOnly, RStructOnly -> RStructAndList
3994     | RStructOnly, RStructOnly -> RStructOnly
3995     | RStructListOnly, RStructListOnly -> RStructListOnly
3996   in
3997
3998   let h = Hashtbl.create 13 in
3999
4000   (* if elem->oldv exists, update entry using ||| operator,
4001    * else just add elem->newv to the hash
4002    *)
4003   let update elem newv =
4004     try  let oldv = Hashtbl.find h elem in
4005          Hashtbl.replace h elem (newv ||| oldv)
4006     with Not_found -> Hashtbl.add h elem newv
4007   in
4008
4009   List.iter (
4010     fun (_, style, _, _, _, _, _) ->
4011       match fst style with
4012       | RStruct (_, structname) -> update structname RStructOnly
4013       | RStructList (_, structname) -> update structname RStructListOnly
4014       | _ -> ()
4015   ) functions;
4016
4017   (* return key->values as a list of (key,value) *)
4018   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4019
4020 (* Used for testing language bindings. *)
4021 type callt =
4022   | CallString of string
4023   | CallOptString of string option
4024   | CallStringList of string list
4025   | CallInt of int
4026   | CallInt64 of int64
4027   | CallBool of bool
4028
4029 (* Used to memoize the result of pod2text. *)
4030 let pod2text_memo_filename = "src/.pod2text.data"
4031 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4032   try
4033     let chan = open_in pod2text_memo_filename in
4034     let v = input_value chan in
4035     close_in chan;
4036     v
4037   with
4038     _ -> Hashtbl.create 13
4039 let pod2text_memo_updated () =
4040   let chan = open_out pod2text_memo_filename in
4041   output_value chan pod2text_memo;
4042   close_out chan
4043
4044 (* Useful functions.
4045  * Note we don't want to use any external OCaml libraries which
4046  * makes this a bit harder than it should be.
4047  *)
4048 let failwithf fs = ksprintf failwith fs
4049
4050 let replace_char s c1 c2 =
4051   let s2 = String.copy s in
4052   let r = ref false in
4053   for i = 0 to String.length s2 - 1 do
4054     if String.unsafe_get s2 i = c1 then (
4055       String.unsafe_set s2 i c2;
4056       r := true
4057     )
4058   done;
4059   if not !r then s else s2
4060
4061 let isspace c =
4062   c = ' '
4063   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4064
4065 let triml ?(test = isspace) str =
4066   let i = ref 0 in
4067   let n = ref (String.length str) in
4068   while !n > 0 && test str.[!i]; do
4069     decr n;
4070     incr i
4071   done;
4072   if !i = 0 then str
4073   else String.sub str !i !n
4074
4075 let trimr ?(test = isspace) str =
4076   let n = ref (String.length str) in
4077   while !n > 0 && test str.[!n-1]; do
4078     decr n
4079   done;
4080   if !n = String.length str then str
4081   else String.sub str 0 !n
4082
4083 let trim ?(test = isspace) str =
4084   trimr ~test (triml ~test str)
4085
4086 let rec find s sub =
4087   let len = String.length s in
4088   let sublen = String.length sub in
4089   let rec loop i =
4090     if i <= len-sublen then (
4091       let rec loop2 j =
4092         if j < sublen then (
4093           if s.[i+j] = sub.[j] then loop2 (j+1)
4094           else -1
4095         ) else
4096           i (* found *)
4097       in
4098       let r = loop2 0 in
4099       if r = -1 then loop (i+1) else r
4100     ) else
4101       -1 (* not found *)
4102   in
4103   loop 0
4104
4105 let rec replace_str s s1 s2 =
4106   let len = String.length s in
4107   let sublen = String.length s1 in
4108   let i = find s s1 in
4109   if i = -1 then s
4110   else (
4111     let s' = String.sub s 0 i in
4112     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4113     s' ^ s2 ^ replace_str s'' s1 s2
4114   )
4115
4116 let rec string_split sep str =
4117   let len = String.length str in
4118   let seplen = String.length sep in
4119   let i = find str sep in
4120   if i = -1 then [str]
4121   else (
4122     let s' = String.sub str 0 i in
4123     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4124     s' :: string_split sep s''
4125   )
4126
4127 let files_equal n1 n2 =
4128   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4129   match Sys.command cmd with
4130   | 0 -> true
4131   | 1 -> false
4132   | i -> failwithf "%s: failed with error code %d" cmd i
4133
4134 let rec filter_map f = function
4135   | [] -> []
4136   | x :: xs ->
4137       match f x with
4138       | Some y -> y :: filter_map f xs
4139       | None -> filter_map f xs
4140
4141 let rec find_map f = function
4142   | [] -> raise Not_found
4143   | x :: xs ->
4144       match f x with
4145       | Some y -> y
4146       | None -> find_map f xs
4147
4148 let iteri f xs =
4149   let rec loop i = function
4150     | [] -> ()
4151     | x :: xs -> f i x; loop (i+1) xs
4152   in
4153   loop 0 xs
4154
4155 let mapi f xs =
4156   let rec loop i = function
4157     | [] -> []
4158     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4159   in
4160   loop 0 xs
4161
4162 let name_of_argt = function
4163   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4164   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4165   | FileIn n | FileOut n -> n
4166
4167 let java_name_of_struct typ =
4168   try List.assoc typ java_structs
4169   with Not_found ->
4170     failwithf
4171       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4172
4173 let cols_of_struct typ =
4174   try List.assoc typ structs
4175   with Not_found ->
4176     failwithf "cols_of_struct: unknown struct %s" typ
4177
4178 let seq_of_test = function
4179   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4180   | TestOutputListOfDevices (s, _)
4181   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4182   | TestOutputTrue s | TestOutputFalse s
4183   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4184   | TestOutputStruct (s, _)
4185   | TestLastFail s -> s
4186
4187 (* Handling for function flags. *)
4188 let protocol_limit_warning =
4189   "Because of the message protocol, there is a transfer limit
4190 of somewhere between 2MB and 4MB.  To transfer large files you should use
4191 FTP."
4192
4193 let danger_will_robinson =
4194   "B<This command is dangerous.  Without careful use you
4195 can easily destroy all your data>."
4196
4197 let deprecation_notice flags =
4198   try
4199     let alt =
4200       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4201     let txt =
4202       sprintf "This function is deprecated.
4203 In new code, use the C<%s> call instead.
4204
4205 Deprecated functions will not be removed from the API, but the
4206 fact that they are deprecated indicates that there are problems
4207 with correct use of these functions." alt in
4208     Some txt
4209   with
4210     Not_found -> None
4211
4212 (* Check function names etc. for consistency. *)
4213 let check_functions () =
4214   let contains_uppercase str =
4215     let len = String.length str in
4216     let rec loop i =
4217       if i >= len then false
4218       else (
4219         let c = str.[i] in
4220         if c >= 'A' && c <= 'Z' then true
4221         else loop (i+1)
4222       )
4223     in
4224     loop 0
4225   in
4226
4227   (* Check function names. *)
4228   List.iter (
4229     fun (name, _, _, _, _, _, _) ->
4230       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4231         failwithf "function name %s does not need 'guestfs' prefix" name;
4232       if name = "" then
4233         failwithf "function name is empty";
4234       if name.[0] < 'a' || name.[0] > 'z' then
4235         failwithf "function name %s must start with lowercase a-z" name;
4236       if String.contains name '-' then
4237         failwithf "function name %s should not contain '-', use '_' instead."
4238           name
4239   ) all_functions;
4240
4241   (* Check function parameter/return names. *)
4242   List.iter (
4243     fun (name, style, _, _, _, _, _) ->
4244       let check_arg_ret_name n =
4245         if contains_uppercase n then
4246           failwithf "%s param/ret %s should not contain uppercase chars"
4247             name n;
4248         if String.contains n '-' || String.contains n '_' then
4249           failwithf "%s param/ret %s should not contain '-' or '_'"
4250             name n;
4251         if n = "value" then
4252           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;
4253         if n = "int" || n = "char" || n = "short" || n = "long" then
4254           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4255         if n = "i" || n = "n" then
4256           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4257         if n = "argv" || n = "args" then
4258           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4259
4260         (* List Haskell, OCaml and C keywords here.
4261          * http://www.haskell.org/haskellwiki/Keywords
4262          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4263          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4264          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4265          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4266          * Omitting _-containing words, since they're handled above.
4267          * Omitting the OCaml reserved word, "val", is ok,
4268          * and saves us from renaming several parameters.
4269          *)
4270         let reserved = [
4271           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4272           "char"; "class"; "const"; "constraint"; "continue"; "data";
4273           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4274           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4275           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4276           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4277           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4278           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4279           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4280           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4281           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4282           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4283           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4284           "volatile"; "when"; "where"; "while";
4285           ] in
4286         if List.mem n reserved then
4287           failwithf "%s has param/ret using reserved word %s" name n;
4288       in
4289
4290       (match fst style with
4291        | RErr -> ()
4292        | RInt n | RInt64 n | RBool n
4293        | RConstString n | RConstOptString n | RString n
4294        | RStringList n | RStruct (n, _) | RStructList (n, _)
4295        | RHashtable n | RBufferOut n ->
4296            check_arg_ret_name n
4297       );
4298       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4299   ) all_functions;
4300
4301   (* Check short descriptions. *)
4302   List.iter (
4303     fun (name, _, _, _, _, shortdesc, _) ->
4304       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4305         failwithf "short description of %s should begin with lowercase." name;
4306       let c = shortdesc.[String.length shortdesc-1] in
4307       if c = '\n' || c = '.' then
4308         failwithf "short description of %s should not end with . or \\n." name
4309   ) all_functions;
4310
4311   (* Check long dscriptions. *)
4312   List.iter (
4313     fun (name, _, _, _, _, _, longdesc) ->
4314       if longdesc.[String.length longdesc-1] = '\n' then
4315         failwithf "long description of %s should not end with \\n." name
4316   ) all_functions;
4317
4318   (* Check proc_nrs. *)
4319   List.iter (
4320     fun (name, _, proc_nr, _, _, _, _) ->
4321       if proc_nr <= 0 then
4322         failwithf "daemon function %s should have proc_nr > 0" name
4323   ) daemon_functions;
4324
4325   List.iter (
4326     fun (name, _, proc_nr, _, _, _, _) ->
4327       if proc_nr <> -1 then
4328         failwithf "non-daemon function %s should have proc_nr -1" name
4329   ) non_daemon_functions;
4330
4331   let proc_nrs =
4332     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4333       daemon_functions in
4334   let proc_nrs =
4335     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4336   let rec loop = function
4337     | [] -> ()
4338     | [_] -> ()
4339     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4340         loop rest
4341     | (name1,nr1) :: (name2,nr2) :: _ ->
4342         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4343           name1 name2 nr1 nr2
4344   in
4345   loop proc_nrs;
4346
4347   (* Check tests. *)
4348   List.iter (
4349     function
4350       (* Ignore functions that have no tests.  We generate a
4351        * warning when the user does 'make check' instead.
4352        *)
4353     | name, _, _, _, [], _, _ -> ()
4354     | name, _, _, _, tests, _, _ ->
4355         let funcs =
4356           List.map (
4357             fun (_, _, test) ->
4358               match seq_of_test test with
4359               | [] ->
4360                   failwithf "%s has a test containing an empty sequence" name
4361               | cmds -> List.map List.hd cmds
4362           ) tests in
4363         let funcs = List.flatten funcs in
4364
4365         let tested = List.mem name funcs in
4366
4367         if not tested then
4368           failwithf "function %s has tests but does not test itself" name
4369   ) all_functions
4370
4371 (* 'pr' prints to the current output file. *)
4372 let chan = ref stdout
4373 let pr fs = ksprintf (output_string !chan) fs
4374
4375 (* Generate a header block in a number of standard styles. *)
4376 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4377 type license = GPLv2 | LGPLv2
4378
4379 let generate_header comment license =
4380   let c = match comment with
4381     | CStyle ->     pr "/* "; " *"
4382     | HashStyle ->  pr "# ";  "#"
4383     | OCamlStyle -> pr "(* "; " *"
4384     | HaskellStyle -> pr "{- "; "  " in
4385   pr "libguestfs generated file\n";
4386   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4387   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4388   pr "%s\n" c;
4389   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4390   pr "%s\n" c;
4391   (match license with
4392    | GPLv2 ->
4393        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4394        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4395        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4396        pr "%s (at your option) any later version.\n" c;
4397        pr "%s\n" c;
4398        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4399        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4400        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4401        pr "%s GNU General Public License for more details.\n" c;
4402        pr "%s\n" c;
4403        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4404        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4405        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4406
4407    | LGPLv2 ->
4408        pr "%s This library is free software; you can redistribute it and/or\n" c;
4409        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4410        pr "%s License as published by the Free Software Foundation; either\n" c;
4411        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4412        pr "%s\n" c;
4413        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4414        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4415        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4416        pr "%s Lesser General Public License for more details.\n" c;
4417        pr "%s\n" c;
4418        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4419        pr "%s License along with this library; if not, write to the Free Software\n" c;
4420        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4421   );
4422   (match comment with
4423    | CStyle -> pr " */\n"
4424    | HashStyle -> ()
4425    | OCamlStyle -> pr " *)\n"
4426    | HaskellStyle -> pr "-}\n"
4427   );
4428   pr "\n"
4429
4430 (* Start of main code generation functions below this line. *)
4431
4432 (* Generate the pod documentation for the C API. *)
4433 let rec generate_actions_pod () =
4434   List.iter (
4435     fun (shortname, style, _, flags, _, _, longdesc) ->
4436       if not (List.mem NotInDocs flags) then (
4437         let name = "guestfs_" ^ shortname in
4438         pr "=head2 %s\n\n" name;
4439         pr " ";
4440         generate_prototype ~extern:false ~handle:"handle" name style;
4441         pr "\n\n";
4442         pr "%s\n\n" longdesc;
4443         (match fst style with
4444          | RErr ->
4445              pr "This function returns 0 on success or -1 on error.\n\n"
4446          | RInt _ ->
4447              pr "On error this function returns -1.\n\n"
4448          | RInt64 _ ->
4449              pr "On error this function returns -1.\n\n"
4450          | RBool _ ->
4451              pr "This function returns a C truth value on success or -1 on error.\n\n"
4452          | RConstString _ ->
4453              pr "This function returns a string, or NULL on error.
4454 The string is owned by the guest handle and must I<not> be freed.\n\n"
4455          | RConstOptString _ ->
4456              pr "This function returns a string which may be NULL.
4457 There is way to return an error from this function.
4458 The string is owned by the guest handle and must I<not> be freed.\n\n"
4459          | RString _ ->
4460              pr "This function returns a string, or NULL on error.
4461 I<The caller must free the returned string after use>.\n\n"
4462          | RStringList _ ->
4463              pr "This function returns a NULL-terminated array of strings
4464 (like L<environ(3)>), or NULL if there was an error.
4465 I<The caller must free the strings and the array after use>.\n\n"
4466          | RStruct (_, typ) ->
4467              pr "This function returns a C<struct guestfs_%s *>,
4468 or NULL if there was an error.
4469 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4470          | RStructList (_, typ) ->
4471              pr "This function returns a C<struct guestfs_%s_list *>
4472 (see E<lt>guestfs-structs.hE<gt>),
4473 or NULL if there was an error.
4474 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4475          | RHashtable _ ->
4476              pr "This function returns a NULL-terminated array of
4477 strings, or NULL if there was an error.
4478 The array of strings will always have length C<2n+1>, where
4479 C<n> keys and values alternate, followed by the trailing NULL entry.
4480 I<The caller must free the strings and the array after use>.\n\n"
4481          | RBufferOut _ ->
4482              pr "This function returns a buffer, or NULL on error.
4483 The size of the returned buffer is written to C<*size_r>.
4484 I<The caller must free the returned buffer after use>.\n\n"
4485         );
4486         if List.mem ProtocolLimitWarning flags then
4487           pr "%s\n\n" protocol_limit_warning;
4488         if List.mem DangerWillRobinson flags then
4489           pr "%s\n\n" danger_will_robinson;
4490         match deprecation_notice flags with
4491         | None -> ()
4492         | Some txt -> pr "%s\n\n" txt
4493       )
4494   ) all_functions_sorted
4495
4496 and generate_structs_pod () =
4497   (* Structs documentation. *)
4498   List.iter (
4499     fun (typ, cols) ->
4500       pr "=head2 guestfs_%s\n" typ;
4501       pr "\n";
4502       pr " struct guestfs_%s {\n" typ;
4503       List.iter (
4504         function
4505         | name, FChar -> pr "   char %s;\n" name
4506         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4507         | name, FInt32 -> pr "   int32_t %s;\n" name
4508         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4509         | name, FInt64 -> pr "   int64_t %s;\n" name
4510         | name, FString -> pr "   char *%s;\n" name
4511         | name, FBuffer ->
4512             pr "   /* The next two fields describe a byte array. */\n";
4513             pr "   uint32_t %s_len;\n" name;
4514             pr "   char *%s;\n" name
4515         | name, FUUID ->
4516             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4517             pr "   char %s[32];\n" name
4518         | name, FOptPercent ->
4519             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4520             pr "   float %s;\n" name
4521       ) cols;
4522       pr " };\n";
4523       pr " \n";
4524       pr " struct guestfs_%s_list {\n" typ;
4525       pr "   uint32_t len; /* Number of elements in list. */\n";
4526       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4527       pr " };\n";
4528       pr " \n";
4529       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4530       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4531         typ typ;
4532       pr "\n"
4533   ) structs
4534
4535 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4536  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4537  *
4538  * We have to use an underscore instead of a dash because otherwise
4539  * rpcgen generates incorrect code.
4540  *
4541  * This header is NOT exported to clients, but see also generate_structs_h.
4542  *)
4543 and generate_xdr () =
4544   generate_header CStyle LGPLv2;
4545
4546   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4547   pr "typedef string str<>;\n";
4548   pr "\n";
4549
4550   (* Internal structures. *)
4551   List.iter (
4552     function
4553     | typ, cols ->
4554         pr "struct guestfs_int_%s {\n" typ;
4555         List.iter (function
4556                    | name, FChar -> pr "  char %s;\n" name
4557                    | name, FString -> pr "  string %s<>;\n" name
4558                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4559                    | name, FUUID -> pr "  opaque %s[32];\n" name
4560                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4561                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4562                    | name, FOptPercent -> pr "  float %s;\n" name
4563                   ) cols;
4564         pr "};\n";
4565         pr "\n";
4566         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4567         pr "\n";
4568   ) structs;
4569
4570   List.iter (
4571     fun (shortname, style, _, _, _, _, _) ->
4572       let name = "guestfs_" ^ shortname in
4573
4574       (match snd style with
4575        | [] -> ()
4576        | args ->
4577            pr "struct %s_args {\n" name;
4578            List.iter (
4579              function
4580              | Pathname n | Device n | Dev_or_Path n | String n ->
4581                  pr "  string %s<>;\n" n
4582              | OptString n -> pr "  str *%s;\n" n
4583              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4584              | Bool n -> pr "  bool %s;\n" n
4585              | Int n -> pr "  int %s;\n" n
4586              | Int64 n -> pr "  hyper %s;\n" n
4587              | FileIn _ | FileOut _ -> ()
4588            ) args;
4589            pr "};\n\n"
4590       );
4591       (match fst style with
4592        | RErr -> ()
4593        | RInt n ->
4594            pr "struct %s_ret {\n" name;
4595            pr "  int %s;\n" n;
4596            pr "};\n\n"
4597        | RInt64 n ->
4598            pr "struct %s_ret {\n" name;
4599            pr "  hyper %s;\n" n;
4600            pr "};\n\n"
4601        | RBool n ->
4602            pr "struct %s_ret {\n" name;
4603            pr "  bool %s;\n" n;
4604            pr "};\n\n"
4605        | RConstString _ | RConstOptString _ ->
4606            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4607        | RString n ->
4608            pr "struct %s_ret {\n" name;
4609            pr "  string %s<>;\n" n;
4610            pr "};\n\n"
4611        | RStringList n ->
4612            pr "struct %s_ret {\n" name;
4613            pr "  str %s<>;\n" n;
4614            pr "};\n\n"
4615        | RStruct (n, typ) ->
4616            pr "struct %s_ret {\n" name;
4617            pr "  guestfs_int_%s %s;\n" typ n;
4618            pr "};\n\n"
4619        | RStructList (n, typ) ->
4620            pr "struct %s_ret {\n" name;
4621            pr "  guestfs_int_%s_list %s;\n" typ n;
4622            pr "};\n\n"
4623        | RHashtable n ->
4624            pr "struct %s_ret {\n" name;
4625            pr "  str %s<>;\n" n;
4626            pr "};\n\n"
4627        | RBufferOut n ->
4628            pr "struct %s_ret {\n" name;
4629            pr "  opaque %s<>;\n" n;
4630            pr "};\n\n"
4631       );
4632   ) daemon_functions;
4633
4634   (* Table of procedure numbers. *)
4635   pr "enum guestfs_procedure {\n";
4636   List.iter (
4637     fun (shortname, _, proc_nr, _, _, _, _) ->
4638       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4639   ) daemon_functions;
4640   pr "  GUESTFS_PROC_NR_PROCS\n";
4641   pr "};\n";
4642   pr "\n";
4643
4644   (* Having to choose a maximum message size is annoying for several
4645    * reasons (it limits what we can do in the API), but it (a) makes
4646    * the protocol a lot simpler, and (b) provides a bound on the size
4647    * of the daemon which operates in limited memory space.  For large
4648    * file transfers you should use FTP.
4649    *)
4650   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4651   pr "\n";
4652
4653   (* Message header, etc. *)
4654   pr "\
4655 /* The communication protocol is now documented in the guestfs(3)
4656  * manpage.
4657  */
4658
4659 const GUESTFS_PROGRAM = 0x2000F5F5;
4660 const GUESTFS_PROTOCOL_VERSION = 1;
4661
4662 /* These constants must be larger than any possible message length. */
4663 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4664 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4665
4666 enum guestfs_message_direction {
4667   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4668   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4669 };
4670
4671 enum guestfs_message_status {
4672   GUESTFS_STATUS_OK = 0,
4673   GUESTFS_STATUS_ERROR = 1
4674 };
4675
4676 const GUESTFS_ERROR_LEN = 256;
4677
4678 struct guestfs_message_error {
4679   string error_message<GUESTFS_ERROR_LEN>;
4680 };
4681
4682 struct guestfs_message_header {
4683   unsigned prog;                     /* GUESTFS_PROGRAM */
4684   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4685   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4686   guestfs_message_direction direction;
4687   unsigned serial;                   /* message serial number */
4688   guestfs_message_status status;
4689 };
4690
4691 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4692
4693 struct guestfs_chunk {
4694   int cancel;                        /* if non-zero, transfer is cancelled */
4695   /* data size is 0 bytes if the transfer has finished successfully */
4696   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4697 };
4698 "
4699
4700 (* Generate the guestfs-structs.h file. *)
4701 and generate_structs_h () =
4702   generate_header CStyle LGPLv2;
4703
4704   (* This is a public exported header file containing various
4705    * structures.  The structures are carefully written to have
4706    * exactly the same in-memory format as the XDR structures that
4707    * we use on the wire to the daemon.  The reason for creating
4708    * copies of these structures here is just so we don't have to
4709    * export the whole of guestfs_protocol.h (which includes much
4710    * unrelated and XDR-dependent stuff that we don't want to be
4711    * public, or required by clients).
4712    *
4713    * To reiterate, we will pass these structures to and from the
4714    * client with a simple assignment or memcpy, so the format
4715    * must be identical to what rpcgen / the RFC defines.
4716    *)
4717
4718   (* Public structures. *)
4719   List.iter (
4720     fun (typ, cols) ->
4721       pr "struct guestfs_%s {\n" typ;
4722       List.iter (
4723         function
4724         | name, FChar -> pr "  char %s;\n" name
4725         | name, FString -> pr "  char *%s;\n" name
4726         | name, FBuffer ->
4727             pr "  uint32_t %s_len;\n" name;
4728             pr "  char *%s;\n" name
4729         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4730         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4731         | name, FInt32 -> pr "  int32_t %s;\n" name
4732         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4733         | name, FInt64 -> pr "  int64_t %s;\n" name
4734         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4735       ) cols;
4736       pr "};\n";
4737       pr "\n";
4738       pr "struct guestfs_%s_list {\n" typ;
4739       pr "  uint32_t len;\n";
4740       pr "  struct guestfs_%s *val;\n" typ;
4741       pr "};\n";
4742       pr "\n";
4743       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4744       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4745       pr "\n"
4746   ) structs
4747
4748 (* Generate the guestfs-actions.h file. *)
4749 and generate_actions_h () =
4750   generate_header CStyle LGPLv2;
4751   List.iter (
4752     fun (shortname, style, _, _, _, _, _) ->
4753       let name = "guestfs_" ^ shortname in
4754       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4755         name style
4756   ) all_functions
4757
4758 (* Generate the guestfs-internal-actions.h file. *)
4759 and generate_internal_actions_h () =
4760   generate_header CStyle LGPLv2;
4761   List.iter (
4762     fun (shortname, style, _, _, _, _, _) ->
4763       let name = "guestfs__" ^ shortname in
4764       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4765         name style
4766   ) non_daemon_functions
4767
4768 (* Generate the client-side dispatch stubs. *)
4769 and generate_client_actions () =
4770   generate_header CStyle LGPLv2;
4771
4772   pr "\
4773 #include <stdio.h>
4774 #include <stdlib.h>
4775 #include <stdint.h>
4776 #include <inttypes.h>
4777
4778 #include \"guestfs.h\"
4779 #include \"guestfs-internal-actions.h\"
4780 #include \"guestfs_protocol.h\"
4781
4782 #define error guestfs_error
4783 //#define perrorf guestfs_perrorf
4784 //#define safe_malloc guestfs_safe_malloc
4785 #define safe_realloc guestfs_safe_realloc
4786 //#define safe_strdup guestfs_safe_strdup
4787 #define safe_memdup guestfs_safe_memdup
4788
4789 /* Check the return message from a call for validity. */
4790 static int
4791 check_reply_header (guestfs_h *g,
4792                     const struct guestfs_message_header *hdr,
4793                     unsigned int proc_nr, unsigned int serial)
4794 {
4795   if (hdr->prog != GUESTFS_PROGRAM) {
4796     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4797     return -1;
4798   }
4799   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4800     error (g, \"wrong protocol version (%%d/%%d)\",
4801            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4802     return -1;
4803   }
4804   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4805     error (g, \"unexpected message direction (%%d/%%d)\",
4806            hdr->direction, GUESTFS_DIRECTION_REPLY);
4807     return -1;
4808   }
4809   if (hdr->proc != proc_nr) {
4810     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4811     return -1;
4812   }
4813   if (hdr->serial != serial) {
4814     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4815     return -1;
4816   }
4817
4818   return 0;
4819 }
4820
4821 /* Check we are in the right state to run a high-level action. */
4822 static int
4823 check_state (guestfs_h *g, const char *caller)
4824 {
4825   if (!guestfs__is_ready (g)) {
4826     if (guestfs__is_config (g) || guestfs__is_launching (g))
4827       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4828         caller);
4829     else
4830       error (g, \"%%s called from the wrong state, %%d != READY\",
4831         caller, guestfs__get_state (g));
4832     return -1;
4833   }
4834   return 0;
4835 }
4836
4837 ";
4838
4839   (* Generate code to generate guestfish call traces. *)
4840   let trace_call shortname style =
4841     pr "  if (guestfs__get_trace (g)) {\n";
4842
4843     let needs_i =
4844       List.exists (function
4845                    | StringList _ | DeviceList _ -> true
4846                    | _ -> false) (snd style) in
4847     if needs_i then (
4848       pr "    int i;\n";
4849       pr "\n"
4850     );
4851
4852     pr "    printf (\"%s\");\n" shortname;
4853     List.iter (
4854       function
4855       | String n                        (* strings *)
4856       | Device n
4857       | Pathname n
4858       | Dev_or_Path n
4859       | FileIn n
4860       | FileOut n ->
4861           (* guestfish doesn't support string escaping, so neither do we *)
4862           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4863       | OptString n ->                  (* string option *)
4864           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4865           pr "    else printf (\" null\");\n"
4866       | StringList n
4867       | DeviceList n ->                 (* string list *)
4868           pr "    putchar (' ');\n";
4869           pr "    putchar ('\"');\n";
4870           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4871           pr "      if (i > 0) putchar (' ');\n";
4872           pr "      fputs (%s[i], stdout);\n" n;
4873           pr "    }\n";
4874           pr "    putchar ('\"');\n";
4875       | Bool n ->                       (* boolean *)
4876           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4877       | Int n ->                        (* int *)
4878           pr "    printf (\" %%d\", %s);\n" n
4879       | Int64 n ->
4880           pr "    printf (\" %%\" PRIi64, %s);\n" n
4881     ) (snd style);
4882     pr "    putchar ('\\n');\n";
4883     pr "  }\n";
4884     pr "\n";
4885   in
4886
4887   (* For non-daemon functions, generate a wrapper around each function. *)
4888   List.iter (
4889     fun (shortname, style, _, _, _, _, _) ->
4890       let name = "guestfs_" ^ shortname in
4891
4892       generate_prototype ~extern:false ~semicolon:false ~newline:true
4893         ~handle:"g" name style;
4894       pr "{\n";
4895       trace_call shortname style;
4896       pr "  return guestfs__%s " shortname;
4897       generate_c_call_args ~handle:"g" style;
4898       pr ";\n";
4899       pr "}\n";
4900       pr "\n"
4901   ) non_daemon_functions;
4902
4903   (* Client-side stubs for each function. *)
4904   List.iter (
4905     fun (shortname, style, _, _, _, _, _) ->
4906       let name = "guestfs_" ^ shortname in
4907
4908       (* Generate the action stub. *)
4909       generate_prototype ~extern:false ~semicolon:false ~newline:true
4910         ~handle:"g" name style;
4911
4912       let error_code =
4913         match fst style with
4914         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4915         | RConstString _ | RConstOptString _ ->
4916             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4917         | RString _ | RStringList _
4918         | RStruct _ | RStructList _
4919         | RHashtable _ | RBufferOut _ ->
4920             "NULL" in
4921
4922       pr "{\n";
4923
4924       (match snd style with
4925        | [] -> ()
4926        | _ -> pr "  struct %s_args args;\n" name
4927       );
4928
4929       pr "  guestfs_message_header hdr;\n";
4930       pr "  guestfs_message_error err;\n";
4931       let has_ret =
4932         match fst style with
4933         | RErr -> false
4934         | RConstString _ | RConstOptString _ ->
4935             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4936         | RInt _ | RInt64 _
4937         | RBool _ | RString _ | RStringList _
4938         | RStruct _ | RStructList _
4939         | RHashtable _ | RBufferOut _ ->
4940             pr "  struct %s_ret ret;\n" name;
4941             true in
4942
4943       pr "  int serial;\n";
4944       pr "  int r;\n";
4945       pr "\n";
4946       trace_call shortname style;
4947       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4948       pr "  guestfs___set_busy (g);\n";
4949       pr "\n";
4950
4951       (* Send the main header and arguments. *)
4952       (match snd style with
4953        | [] ->
4954            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4955              (String.uppercase shortname)
4956        | args ->
4957            List.iter (
4958              function
4959              | Pathname n | Device n | Dev_or_Path n | String n ->
4960                  pr "  args.%s = (char *) %s;\n" n n
4961              | OptString n ->
4962                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4963              | StringList n | DeviceList n ->
4964                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4965                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4966              | Bool n ->
4967                  pr "  args.%s = %s;\n" n n
4968              | Int n ->
4969                  pr "  args.%s = %s;\n" n n
4970              | Int64 n ->
4971                  pr "  args.%s = %s;\n" n n
4972              | FileIn _ | FileOut _ -> ()
4973            ) args;
4974            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4975              (String.uppercase shortname);
4976            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4977              name;
4978       );
4979       pr "  if (serial == -1) {\n";
4980       pr "    guestfs___end_busy (g);\n";
4981       pr "    return %s;\n" error_code;
4982       pr "  }\n";
4983       pr "\n";
4984
4985       (* Send any additional files (FileIn) requested. *)
4986       let need_read_reply_label = ref false in
4987       List.iter (
4988         function
4989         | FileIn n ->
4990             pr "  r = guestfs___send_file (g, %s);\n" n;
4991             pr "  if (r == -1) {\n";
4992             pr "    guestfs___end_busy (g);\n";
4993             pr "    return %s;\n" error_code;
4994             pr "  }\n";
4995             pr "  if (r == -2) /* daemon cancelled */\n";
4996             pr "    goto read_reply;\n";
4997             need_read_reply_label := true;
4998             pr "\n";
4999         | _ -> ()
5000       ) (snd style);
5001
5002       (* Wait for the reply from the remote end. *)
5003       if !need_read_reply_label then pr " read_reply:\n";
5004       pr "  memset (&hdr, 0, sizeof hdr);\n";
5005       pr "  memset (&err, 0, sizeof err);\n";
5006       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5007       pr "\n";
5008       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5009       if not has_ret then
5010         pr "NULL, NULL"
5011       else
5012         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5013       pr ");\n";
5014
5015       pr "  if (r == -1) {\n";
5016       pr "    guestfs___end_busy (g);\n";
5017       pr "    return %s;\n" error_code;
5018       pr "  }\n";
5019       pr "\n";
5020
5021       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5022         (String.uppercase shortname);
5023       pr "    guestfs___end_busy (g);\n";
5024       pr "    return %s;\n" error_code;
5025       pr "  }\n";
5026       pr "\n";
5027
5028       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5029       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5030       pr "    free (err.error_message);\n";
5031       pr "    guestfs___end_busy (g);\n";
5032       pr "    return %s;\n" error_code;
5033       pr "  }\n";
5034       pr "\n";
5035
5036       (* Expecting to receive further files (FileOut)? *)
5037       List.iter (
5038         function
5039         | FileOut n ->
5040             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5041             pr "    guestfs___end_busy (g);\n";
5042             pr "    return %s;\n" error_code;
5043             pr "  }\n";
5044             pr "\n";
5045         | _ -> ()
5046       ) (snd style);
5047
5048       pr "  guestfs___end_busy (g);\n";
5049
5050       (match fst style with
5051        | RErr -> pr "  return 0;\n"
5052        | RInt n | RInt64 n | RBool n ->
5053            pr "  return ret.%s;\n" n
5054        | RConstString _ | RConstOptString _ ->
5055            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5056        | RString n ->
5057            pr "  return ret.%s; /* caller will free */\n" n
5058        | RStringList n | RHashtable n ->
5059            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5060            pr "  ret.%s.%s_val =\n" n n;
5061            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5062            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5063              n n;
5064            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5065            pr "  return ret.%s.%s_val;\n" n n
5066        | RStruct (n, _) ->
5067            pr "  /* caller will free this */\n";
5068            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5069        | RStructList (n, _) ->
5070            pr "  /* caller will free this */\n";
5071            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5072        | RBufferOut n ->
5073            pr "  *size_r = ret.%s.%s_len;\n" n n;
5074            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
5075       );
5076
5077       pr "}\n\n"
5078   ) daemon_functions;
5079
5080   (* Functions to free structures. *)
5081   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5082   pr " * structure format is identical to the XDR format.  See note in\n";
5083   pr " * generator.ml.\n";
5084   pr " */\n";
5085   pr "\n";
5086
5087   List.iter (
5088     fun (typ, _) ->
5089       pr "void\n";
5090       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5091       pr "{\n";
5092       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5093       pr "  free (x);\n";
5094       pr "}\n";
5095       pr "\n";
5096
5097       pr "void\n";
5098       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5099       pr "{\n";
5100       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5101       pr "  free (x);\n";
5102       pr "}\n";
5103       pr "\n";
5104
5105   ) structs;
5106
5107 (* Generate daemon/actions.h. *)
5108 and generate_daemon_actions_h () =
5109   generate_header CStyle GPLv2;
5110
5111   pr "#include \"../src/guestfs_protocol.h\"\n";
5112   pr "\n";
5113
5114   List.iter (
5115     fun (name, style, _, _, _, _, _) ->
5116       generate_prototype
5117         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5118         name style;
5119   ) daemon_functions
5120
5121 (* Generate the server-side stubs. *)
5122 and generate_daemon_actions () =
5123   generate_header CStyle GPLv2;
5124
5125   pr "#include <config.h>\n";
5126   pr "\n";
5127   pr "#include <stdio.h>\n";
5128   pr "#include <stdlib.h>\n";
5129   pr "#include <string.h>\n";
5130   pr "#include <inttypes.h>\n";
5131   pr "#include <rpc/types.h>\n";
5132   pr "#include <rpc/xdr.h>\n";
5133   pr "\n";
5134   pr "#include \"daemon.h\"\n";
5135   pr "#include \"c-ctype.h\"\n";
5136   pr "#include \"../src/guestfs_protocol.h\"\n";
5137   pr "#include \"actions.h\"\n";
5138   pr "\n";
5139
5140   List.iter (
5141     fun (name, style, _, _, _, _, _) ->
5142       (* Generate server-side stubs. *)
5143       pr "static void %s_stub (XDR *xdr_in)\n" name;
5144       pr "{\n";
5145       let error_code =
5146         match fst style with
5147         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5148         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5149         | RBool _ -> pr "  int r;\n"; "-1"
5150         | RConstString _ | RConstOptString _ ->
5151             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5152         | RString _ -> pr "  char *r;\n"; "NULL"
5153         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5154         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5155         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5156         | RBufferOut _ ->
5157             pr "  size_t size;\n";
5158             pr "  char *r;\n";
5159             "NULL" in
5160
5161       (match snd style with
5162        | [] -> ()
5163        | args ->
5164            pr "  struct guestfs_%s_args args;\n" name;
5165            List.iter (
5166              function
5167              | Device n | Dev_or_Path n
5168              | Pathname n
5169              | String n -> ()
5170              | OptString n -> pr "  char *%s;\n" n
5171              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5172              | Bool n -> pr "  int %s;\n" n
5173              | Int n -> pr "  int %s;\n" n
5174              | Int64 n -> pr "  int64_t %s;\n" n
5175              | FileIn _ | FileOut _ -> ()
5176            ) args
5177       );
5178       pr "\n";
5179
5180       (match snd style with
5181        | [] -> ()
5182        | args ->
5183            pr "  memset (&args, 0, sizeof args);\n";
5184            pr "\n";
5185            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5186            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5187            pr "    return;\n";
5188            pr "  }\n";
5189            let pr_args n =
5190              pr "  char *%s = args.%s;\n" n n
5191            in
5192            let pr_list_handling_code n =
5193              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5194              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5195              pr "  if (%s == NULL) {\n" n;
5196              pr "    reply_with_perror (\"realloc\");\n";
5197              pr "    goto done;\n";
5198              pr "  }\n";
5199              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5200              pr "  args.%s.%s_val = %s;\n" n n n;
5201            in
5202            List.iter (
5203              function
5204              | Pathname n ->
5205                  pr_args n;
5206                  pr "  ABS_PATH (%s, goto done);\n" n;
5207              | Device n ->
5208                  pr_args n;
5209                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5210              | Dev_or_Path n ->
5211                  pr_args n;
5212                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5213              | String n -> pr_args n
5214              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5215              | StringList n ->
5216                  pr_list_handling_code n;
5217              | DeviceList n ->
5218                  pr_list_handling_code n;
5219                  pr "  /* Ensure that each is a device,\n";
5220                  pr "   * and perform device name translation. */\n";
5221                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5222                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5223                  pr "  }\n";
5224              | Bool n -> pr "  %s = args.%s;\n" n n
5225              | Int n -> pr "  %s = args.%s;\n" n n
5226              | Int64 n -> pr "  %s = args.%s;\n" n n
5227              | FileIn _ | FileOut _ -> ()
5228            ) args;
5229            pr "\n"
5230       );
5231
5232
5233       (* this is used at least for do_equal *)
5234       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5235         (* Emit NEED_ROOT just once, even when there are two or
5236            more Pathname args *)
5237         pr "  NEED_ROOT (goto done);\n";
5238       );
5239
5240       (* Don't want to call the impl with any FileIn or FileOut
5241        * parameters, since these go "outside" the RPC protocol.
5242        *)
5243       let args' =
5244         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5245           (snd style) in
5246       pr "  r = do_%s " name;
5247       generate_c_call_args (fst style, args');
5248       pr ";\n";
5249
5250       pr "  if (r == %s)\n" error_code;
5251       pr "    /* do_%s has already called reply_with_error */\n" name;
5252       pr "    goto done;\n";
5253       pr "\n";
5254
5255       (* If there are any FileOut parameters, then the impl must
5256        * send its own reply.
5257        *)
5258       let no_reply =
5259         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5260       if no_reply then
5261         pr "  /* do_%s has already sent a reply */\n" name
5262       else (
5263         match fst style with
5264         | RErr -> pr "  reply (NULL, NULL);\n"
5265         | RInt n | RInt64 n | RBool n ->
5266             pr "  struct guestfs_%s_ret ret;\n" name;
5267             pr "  ret.%s = r;\n" n;
5268             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5269               name
5270         | RConstString _ | RConstOptString _ ->
5271             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5272         | RString n ->
5273             pr "  struct guestfs_%s_ret ret;\n" name;
5274             pr "  ret.%s = r;\n" n;
5275             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5276               name;
5277             pr "  free (r);\n"
5278         | RStringList n | RHashtable n ->
5279             pr "  struct guestfs_%s_ret ret;\n" name;
5280             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5281             pr "  ret.%s.%s_val = r;\n" n n;
5282             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5283               name;
5284             pr "  free_strings (r);\n"
5285         | RStruct (n, _) ->
5286             pr "  struct guestfs_%s_ret ret;\n" name;
5287             pr "  ret.%s = *r;\n" n;
5288             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5289               name;
5290             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5291               name
5292         | RStructList (n, _) ->
5293             pr "  struct guestfs_%s_ret ret;\n" name;
5294             pr "  ret.%s = *r;\n" n;
5295             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5296               name;
5297             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5298               name
5299         | RBufferOut n ->
5300             pr "  struct guestfs_%s_ret ret;\n" name;
5301             pr "  ret.%s.%s_val = r;\n" n n;
5302             pr "  ret.%s.%s_len = size;\n" n n;
5303             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5304               name;
5305             pr "  free (r);\n"
5306       );
5307
5308       (* Free the args. *)
5309       (match snd style with
5310        | [] ->
5311            pr "done: ;\n";
5312        | _ ->
5313            pr "done:\n";
5314            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5315              name
5316       );
5317
5318       pr "}\n\n";
5319   ) daemon_functions;
5320
5321   (* Dispatch function. *)
5322   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5323   pr "{\n";
5324   pr "  switch (proc_nr) {\n";
5325
5326   List.iter (
5327     fun (name, style, _, _, _, _, _) ->
5328       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5329       pr "      %s_stub (xdr_in);\n" name;
5330       pr "      break;\n"
5331   ) daemon_functions;
5332
5333   pr "    default:\n";
5334   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";
5335   pr "  }\n";
5336   pr "}\n";
5337   pr "\n";
5338
5339   (* LVM columns and tokenization functions. *)
5340   (* XXX This generates crap code.  We should rethink how we
5341    * do this parsing.
5342    *)
5343   List.iter (
5344     function
5345     | typ, cols ->
5346         pr "static const char *lvm_%s_cols = \"%s\";\n"
5347           typ (String.concat "," (List.map fst cols));
5348         pr "\n";
5349
5350         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5351         pr "{\n";
5352         pr "  char *tok, *p, *next;\n";
5353         pr "  int i, j;\n";
5354         pr "\n";
5355         (*
5356           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5357           pr "\n";
5358         *)
5359         pr "  if (!str) {\n";
5360         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5361         pr "    return -1;\n";
5362         pr "  }\n";
5363         pr "  if (!*str || c_isspace (*str)) {\n";
5364         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5365         pr "    return -1;\n";
5366         pr "  }\n";
5367         pr "  tok = str;\n";
5368         List.iter (
5369           fun (name, coltype) ->
5370             pr "  if (!tok) {\n";
5371             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5372             pr "    return -1;\n";
5373             pr "  }\n";
5374             pr "  p = strchrnul (tok, ',');\n";
5375             pr "  if (*p) next = p+1; else next = NULL;\n";
5376             pr "  *p = '\\0';\n";
5377             (match coltype with
5378              | FString ->
5379                  pr "  r->%s = strdup (tok);\n" name;
5380                  pr "  if (r->%s == NULL) {\n" name;
5381                  pr "    perror (\"strdup\");\n";
5382                  pr "    return -1;\n";
5383                  pr "  }\n"
5384              | FUUID ->
5385                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5386                  pr "    if (tok[j] == '\\0') {\n";
5387                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5388                  pr "      return -1;\n";
5389                  pr "    } else if (tok[j] != '-')\n";
5390                  pr "      r->%s[i++] = tok[j];\n" name;
5391                  pr "  }\n";
5392              | FBytes ->
5393                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5394                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5395                  pr "    return -1;\n";
5396                  pr "  }\n";
5397              | FInt64 ->
5398                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5399                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5400                  pr "    return -1;\n";
5401                  pr "  }\n";
5402              | FOptPercent ->
5403                  pr "  if (tok[0] == '\\0')\n";
5404                  pr "    r->%s = -1;\n" name;
5405                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5406                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5407                  pr "    return -1;\n";
5408                  pr "  }\n";
5409              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5410                  assert false (* can never be an LVM column *)
5411             );
5412             pr "  tok = next;\n";
5413         ) cols;
5414
5415         pr "  if (tok != NULL) {\n";
5416         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5417         pr "    return -1;\n";
5418         pr "  }\n";
5419         pr "  return 0;\n";
5420         pr "}\n";
5421         pr "\n";
5422
5423         pr "guestfs_int_lvm_%s_list *\n" typ;
5424         pr "parse_command_line_%ss (void)\n" typ;
5425         pr "{\n";
5426         pr "  char *out, *err;\n";
5427         pr "  char *p, *pend;\n";
5428         pr "  int r, i;\n";
5429         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5430         pr "  void *newp;\n";
5431         pr "\n";
5432         pr "  ret = malloc (sizeof *ret);\n";
5433         pr "  if (!ret) {\n";
5434         pr "    reply_with_perror (\"malloc\");\n";
5435         pr "    return NULL;\n";
5436         pr "  }\n";
5437         pr "\n";
5438         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5439         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5440         pr "\n";
5441         pr "  r = command (&out, &err,\n";
5442         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5443         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5444         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5445         pr "  if (r == -1) {\n";
5446         pr "    reply_with_error (\"%%s\", err);\n";
5447         pr "    free (out);\n";
5448         pr "    free (err);\n";
5449         pr "    free (ret);\n";
5450         pr "    return NULL;\n";
5451         pr "  }\n";
5452         pr "\n";
5453         pr "  free (err);\n";
5454         pr "\n";
5455         pr "  /* Tokenize each line of the output. */\n";
5456         pr "  p = out;\n";
5457         pr "  i = 0;\n";
5458         pr "  while (p) {\n";
5459         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5460         pr "    if (pend) {\n";
5461         pr "      *pend = '\\0';\n";
5462         pr "      pend++;\n";
5463         pr "    }\n";
5464         pr "\n";
5465         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5466         pr "      p++;\n";
5467         pr "\n";
5468         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5469         pr "      p = pend;\n";
5470         pr "      continue;\n";
5471         pr "    }\n";
5472         pr "\n";
5473         pr "    /* Allocate some space to store this next entry. */\n";
5474         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5475         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5476         pr "    if (newp == NULL) {\n";
5477         pr "      reply_with_perror (\"realloc\");\n";
5478         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5479         pr "      free (ret);\n";
5480         pr "      free (out);\n";
5481         pr "      return NULL;\n";
5482         pr "    }\n";
5483         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5484         pr "\n";
5485         pr "    /* Tokenize the next entry. */\n";
5486         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5487         pr "    if (r == -1) {\n";
5488         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5489         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5490         pr "      free (ret);\n";
5491         pr "      free (out);\n";
5492         pr "      return NULL;\n";
5493         pr "    }\n";
5494         pr "\n";
5495         pr "    ++i;\n";
5496         pr "    p = pend;\n";
5497         pr "  }\n";
5498         pr "\n";
5499         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5500         pr "\n";
5501         pr "  free (out);\n";
5502         pr "  return ret;\n";
5503         pr "}\n"
5504
5505   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5506
5507 (* Generate a list of function names, for debugging in the daemon.. *)
5508 and generate_daemon_names () =
5509   generate_header CStyle GPLv2;
5510
5511   pr "#include <config.h>\n";
5512   pr "\n";
5513   pr "#include \"daemon.h\"\n";
5514   pr "\n";
5515
5516   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5517   pr "const char *function_names[] = {\n";
5518   List.iter (
5519     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5520   ) daemon_functions;
5521   pr "};\n";
5522
5523 (* Generate the tests. *)
5524 and generate_tests () =
5525   generate_header CStyle GPLv2;
5526
5527   pr "\
5528 #include <stdio.h>
5529 #include <stdlib.h>
5530 #include <string.h>
5531 #include <unistd.h>
5532 #include <sys/types.h>
5533 #include <fcntl.h>
5534
5535 #include \"guestfs.h\"
5536
5537 static guestfs_h *g;
5538 static int suppress_error = 0;
5539
5540 static void print_error (guestfs_h *g, void *data, const char *msg)
5541 {
5542   if (!suppress_error)
5543     fprintf (stderr, \"%%s\\n\", msg);
5544 }
5545
5546 /* FIXME: nearly identical code appears in fish.c */
5547 static void print_strings (char *const *argv)
5548 {
5549   int argc;
5550
5551   for (argc = 0; argv[argc] != NULL; ++argc)
5552     printf (\"\\t%%s\\n\", argv[argc]);
5553 }
5554
5555 /*
5556 static void print_table (char const *const *argv)
5557 {
5558   int i;
5559
5560   for (i = 0; argv[i] != NULL; i += 2)
5561     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5562 }
5563 */
5564
5565 ";
5566
5567   (* Generate a list of commands which are not tested anywhere. *)
5568   pr "static void no_test_warnings (void)\n";
5569   pr "{\n";
5570
5571   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5572   List.iter (
5573     fun (_, _, _, _, tests, _, _) ->
5574       let tests = filter_map (
5575         function
5576         | (_, (Always|If _|Unless _), test) -> Some test
5577         | (_, Disabled, _) -> None
5578       ) tests in
5579       let seq = List.concat (List.map seq_of_test tests) in
5580       let cmds_tested = List.map List.hd seq in
5581       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5582   ) all_functions;
5583
5584   List.iter (
5585     fun (name, _, _, _, _, _, _) ->
5586       if not (Hashtbl.mem hash name) then
5587         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5588   ) all_functions;
5589
5590   pr "}\n";
5591   pr "\n";
5592
5593   (* Generate the actual tests.  Note that we generate the tests
5594    * in reverse order, deliberately, so that (in general) the
5595    * newest tests run first.  This makes it quicker and easier to
5596    * debug them.
5597    *)
5598   let test_names =
5599     List.map (
5600       fun (name, _, _, _, tests, _, _) ->
5601         mapi (generate_one_test name) tests
5602     ) (List.rev all_functions) in
5603   let test_names = List.concat test_names in
5604   let nr_tests = List.length test_names in
5605
5606   pr "\
5607 int main (int argc, char *argv[])
5608 {
5609   char c = 0;
5610   unsigned long int n_failed = 0;
5611   const char *filename;
5612   int fd;
5613   int nr_tests, test_num = 0;
5614
5615   setbuf (stdout, NULL);
5616
5617   no_test_warnings ();
5618
5619   g = guestfs_create ();
5620   if (g == NULL) {
5621     printf (\"guestfs_create FAILED\\n\");
5622     exit (1);
5623   }
5624
5625   guestfs_set_error_handler (g, print_error, NULL);
5626
5627   guestfs_set_path (g, \"../appliance\");
5628
5629   filename = \"test1.img\";
5630   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5631   if (fd == -1) {
5632     perror (filename);
5633     exit (1);
5634   }
5635   if (lseek (fd, %d, SEEK_SET) == -1) {
5636     perror (\"lseek\");
5637     close (fd);
5638     unlink (filename);
5639     exit (1);
5640   }
5641   if (write (fd, &c, 1) == -1) {
5642     perror (\"write\");
5643     close (fd);
5644     unlink (filename);
5645     exit (1);
5646   }
5647   if (close (fd) == -1) {
5648     perror (filename);
5649     unlink (filename);
5650     exit (1);
5651   }
5652   if (guestfs_add_drive (g, filename) == -1) {
5653     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5654     exit (1);
5655   }
5656
5657   filename = \"test2.img\";
5658   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5659   if (fd == -1) {
5660     perror (filename);
5661     exit (1);
5662   }
5663   if (lseek (fd, %d, SEEK_SET) == -1) {
5664     perror (\"lseek\");
5665     close (fd);
5666     unlink (filename);
5667     exit (1);
5668   }
5669   if (write (fd, &c, 1) == -1) {
5670     perror (\"write\");
5671     close (fd);
5672     unlink (filename);
5673     exit (1);
5674   }
5675   if (close (fd) == -1) {
5676     perror (filename);
5677     unlink (filename);
5678     exit (1);
5679   }
5680   if (guestfs_add_drive (g, filename) == -1) {
5681     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5682     exit (1);
5683   }
5684
5685   filename = \"test3.img\";
5686   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5687   if (fd == -1) {
5688     perror (filename);
5689     exit (1);
5690   }
5691   if (lseek (fd, %d, SEEK_SET) == -1) {
5692     perror (\"lseek\");
5693     close (fd);
5694     unlink (filename);
5695     exit (1);
5696   }
5697   if (write (fd, &c, 1) == -1) {
5698     perror (\"write\");
5699     close (fd);
5700     unlink (filename);
5701     exit (1);
5702   }
5703   if (close (fd) == -1) {
5704     perror (filename);
5705     unlink (filename);
5706     exit (1);
5707   }
5708   if (guestfs_add_drive (g, filename) == -1) {
5709     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5710     exit (1);
5711   }
5712
5713   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5714     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5715     exit (1);
5716   }
5717
5718   if (guestfs_launch (g) == -1) {
5719     printf (\"guestfs_launch FAILED\\n\");
5720     exit (1);
5721   }
5722
5723   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5724   alarm (600);
5725
5726   /* Cancel previous alarm. */
5727   alarm (0);
5728
5729   nr_tests = %d;
5730
5731 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5732
5733   iteri (
5734     fun i test_name ->
5735       pr "  test_num++;\n";
5736       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5737       pr "  if (%s () == -1) {\n" test_name;
5738       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5739       pr "    n_failed++;\n";
5740       pr "  }\n";
5741   ) test_names;
5742   pr "\n";
5743
5744   pr "  guestfs_close (g);\n";
5745   pr "  unlink (\"test1.img\");\n";
5746   pr "  unlink (\"test2.img\");\n";
5747   pr "  unlink (\"test3.img\");\n";
5748   pr "\n";
5749
5750   pr "  if (n_failed > 0) {\n";
5751   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5752   pr "    exit (1);\n";
5753   pr "  }\n";
5754   pr "\n";
5755
5756   pr "  exit (0);\n";
5757   pr "}\n"
5758
5759 and generate_one_test name i (init, prereq, test) =
5760   let test_name = sprintf "test_%s_%d" name i in
5761
5762   pr "\
5763 static int %s_skip (void)
5764 {
5765   const char *str;
5766
5767   str = getenv (\"TEST_ONLY\");
5768   if (str)
5769     return strstr (str, \"%s\") == NULL;
5770   str = getenv (\"SKIP_%s\");
5771   if (str && strcmp (str, \"1\") == 0) return 1;
5772   str = getenv (\"SKIP_TEST_%s\");
5773   if (str && strcmp (str, \"1\") == 0) return 1;
5774   return 0;
5775 }
5776
5777 " test_name name (String.uppercase test_name) (String.uppercase name);
5778
5779   (match prereq with
5780    | Disabled | Always -> ()
5781    | If code | Unless code ->
5782        pr "static int %s_prereq (void)\n" test_name;
5783        pr "{\n";
5784        pr "  %s\n" code;
5785        pr "}\n";
5786        pr "\n";
5787   );
5788
5789   pr "\
5790 static int %s (void)
5791 {
5792   if (%s_skip ()) {
5793     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5794     return 0;
5795   }
5796
5797 " test_name test_name test_name;
5798
5799   (match prereq with
5800    | Disabled ->
5801        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5802    | If _ ->
5803        pr "  if (! %s_prereq ()) {\n" test_name;
5804        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5805        pr "    return 0;\n";
5806        pr "  }\n";
5807        pr "\n";
5808        generate_one_test_body name i test_name init test;
5809    | Unless _ ->
5810        pr "  if (%s_prereq ()) {\n" test_name;
5811        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5812        pr "    return 0;\n";
5813        pr "  }\n";
5814        pr "\n";
5815        generate_one_test_body name i test_name init test;
5816    | Always ->
5817        generate_one_test_body name i test_name init test
5818   );
5819
5820   pr "  return 0;\n";
5821   pr "}\n";
5822   pr "\n";
5823   test_name
5824
5825 and generate_one_test_body name i test_name init test =
5826   (match init with
5827    | InitNone (* XXX at some point, InitNone and InitEmpty became
5828                * folded together as the same thing.  Really we should
5829                * make InitNone do nothing at all, but the tests may
5830                * need to be checked to make sure this is OK.
5831                *)
5832    | InitEmpty ->
5833        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5834        List.iter (generate_test_command_call test_name)
5835          [["blockdev_setrw"; "/dev/sda"];
5836           ["umount_all"];
5837           ["lvm_remove_all"]]
5838    | InitPartition ->
5839        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5840        List.iter (generate_test_command_call test_name)
5841          [["blockdev_setrw"; "/dev/sda"];
5842           ["umount_all"];
5843           ["lvm_remove_all"];
5844           ["sfdiskM"; "/dev/sda"; ","]]
5845    | InitBasicFS ->
5846        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5847        List.iter (generate_test_command_call test_name)
5848          [["blockdev_setrw"; "/dev/sda"];
5849           ["umount_all"];
5850           ["lvm_remove_all"];
5851           ["sfdiskM"; "/dev/sda"; ","];
5852           ["mkfs"; "ext2"; "/dev/sda1"];
5853           ["mount"; "/dev/sda1"; "/"]]
5854    | InitBasicFSonLVM ->
5855        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5856          test_name;
5857        List.iter (generate_test_command_call test_name)
5858          [["blockdev_setrw"; "/dev/sda"];
5859           ["umount_all"];
5860           ["lvm_remove_all"];
5861           ["sfdiskM"; "/dev/sda"; ","];
5862           ["pvcreate"; "/dev/sda1"];
5863           ["vgcreate"; "VG"; "/dev/sda1"];
5864           ["lvcreate"; "LV"; "VG"; "8"];
5865           ["mkfs"; "ext2"; "/dev/VG/LV"];
5866           ["mount"; "/dev/VG/LV"; "/"]]
5867    | InitISOFS ->
5868        pr "  /* InitISOFS for %s */\n" test_name;
5869        List.iter (generate_test_command_call test_name)
5870          [["blockdev_setrw"; "/dev/sda"];
5871           ["umount_all"];
5872           ["lvm_remove_all"];
5873           ["mount_ro"; "/dev/sdd"; "/"]]
5874   );
5875
5876   let get_seq_last = function
5877     | [] ->
5878         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5879           test_name
5880     | seq ->
5881         let seq = List.rev seq in
5882         List.rev (List.tl seq), List.hd seq
5883   in
5884
5885   match test with
5886   | TestRun seq ->
5887       pr "  /* TestRun for %s (%d) */\n" name i;
5888       List.iter (generate_test_command_call test_name) seq
5889   | TestOutput (seq, expected) ->
5890       pr "  /* TestOutput for %s (%d) */\n" name i;
5891       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5892       let seq, last = get_seq_last seq in
5893       let test () =
5894         pr "    if (strcmp (r, expected) != 0) {\n";
5895         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5896         pr "      return -1;\n";
5897         pr "    }\n"
5898       in
5899       List.iter (generate_test_command_call test_name) seq;
5900       generate_test_command_call ~test test_name last
5901   | TestOutputList (seq, expected) ->
5902       pr "  /* TestOutputList for %s (%d) */\n" name i;
5903       let seq, last = get_seq_last seq in
5904       let test () =
5905         iteri (
5906           fun i str ->
5907             pr "    if (!r[%d]) {\n" i;
5908             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5909             pr "      print_strings (r);\n";
5910             pr "      return -1;\n";
5911             pr "    }\n";
5912             pr "    {\n";
5913             pr "      const char *expected = \"%s\";\n" (c_quote str);
5914             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5915             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5916             pr "        return -1;\n";
5917             pr "      }\n";
5918             pr "    }\n"
5919         ) expected;
5920         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5921         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5922           test_name;
5923         pr "      print_strings (r);\n";
5924         pr "      return -1;\n";
5925         pr "    }\n"
5926       in
5927       List.iter (generate_test_command_call test_name) seq;
5928       generate_test_command_call ~test test_name last
5929   | TestOutputListOfDevices (seq, expected) ->
5930       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5931       let seq, last = get_seq_last seq in
5932       let test () =
5933         iteri (
5934           fun i str ->
5935             pr "    if (!r[%d]) {\n" i;
5936             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5937             pr "      print_strings (r);\n";
5938             pr "      return -1;\n";
5939             pr "    }\n";
5940             pr "    {\n";
5941             pr "      const char *expected = \"%s\";\n" (c_quote str);
5942             pr "      r[%d][5] = 's';\n" i;
5943             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5944             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5945             pr "        return -1;\n";
5946             pr "      }\n";
5947             pr "    }\n"
5948         ) expected;
5949         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5950         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5951           test_name;
5952         pr "      print_strings (r);\n";
5953         pr "      return -1;\n";
5954         pr "    }\n"
5955       in
5956       List.iter (generate_test_command_call test_name) seq;
5957       generate_test_command_call ~test test_name last
5958   | TestOutputInt (seq, expected) ->
5959       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5960       let seq, last = get_seq_last seq in
5961       let test () =
5962         pr "    if (r != %d) {\n" expected;
5963         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5964           test_name expected;
5965         pr "               (int) r);\n";
5966         pr "      return -1;\n";
5967         pr "    }\n"
5968       in
5969       List.iter (generate_test_command_call test_name) seq;
5970       generate_test_command_call ~test test_name last
5971   | TestOutputIntOp (seq, op, expected) ->
5972       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5973       let seq, last = get_seq_last seq in
5974       let test () =
5975         pr "    if (! (r %s %d)) {\n" op expected;
5976         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5977           test_name op expected;
5978         pr "               (int) r);\n";
5979         pr "      return -1;\n";
5980         pr "    }\n"
5981       in
5982       List.iter (generate_test_command_call test_name) seq;
5983       generate_test_command_call ~test test_name last
5984   | TestOutputTrue seq ->
5985       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5986       let seq, last = get_seq_last seq in
5987       let test () =
5988         pr "    if (!r) {\n";
5989         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5990           test_name;
5991         pr "      return -1;\n";
5992         pr "    }\n"
5993       in
5994       List.iter (generate_test_command_call test_name) seq;
5995       generate_test_command_call ~test test_name last
5996   | TestOutputFalse seq ->
5997       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5998       let seq, last = get_seq_last seq in
5999       let test () =
6000         pr "    if (r) {\n";
6001         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6002           test_name;
6003         pr "      return -1;\n";
6004         pr "    }\n"
6005       in
6006       List.iter (generate_test_command_call test_name) seq;
6007       generate_test_command_call ~test test_name last
6008   | TestOutputLength (seq, expected) ->
6009       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6010       let seq, last = get_seq_last seq in
6011       let test () =
6012         pr "    int j;\n";
6013         pr "    for (j = 0; j < %d; ++j)\n" expected;
6014         pr "      if (r[j] == NULL) {\n";
6015         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6016           test_name;
6017         pr "        print_strings (r);\n";
6018         pr "        return -1;\n";
6019         pr "      }\n";
6020         pr "    if (r[j] != NULL) {\n";
6021         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6022           test_name;
6023         pr "      print_strings (r);\n";
6024         pr "      return -1;\n";
6025         pr "    }\n"
6026       in
6027       List.iter (generate_test_command_call test_name) seq;
6028       generate_test_command_call ~test test_name last
6029   | TestOutputBuffer (seq, expected) ->
6030       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6031       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6032       let seq, last = get_seq_last seq in
6033       let len = String.length expected in
6034       let test () =
6035         pr "    if (size != %d) {\n" len;
6036         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6037         pr "      return -1;\n";
6038         pr "    }\n";
6039         pr "    if (strncmp (r, expected, size) != 0) {\n";
6040         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6041         pr "      return -1;\n";
6042         pr "    }\n"
6043       in
6044       List.iter (generate_test_command_call test_name) seq;
6045       generate_test_command_call ~test test_name last
6046   | TestOutputStruct (seq, checks) ->
6047       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6048       let seq, last = get_seq_last seq in
6049       let test () =
6050         List.iter (
6051           function
6052           | CompareWithInt (field, expected) ->
6053               pr "    if (r->%s != %d) {\n" field expected;
6054               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6055                 test_name field expected;
6056               pr "               (int) r->%s);\n" field;
6057               pr "      return -1;\n";
6058               pr "    }\n"
6059           | CompareWithIntOp (field, op, expected) ->
6060               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6061               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6062                 test_name field op expected;
6063               pr "               (int) r->%s);\n" field;
6064               pr "      return -1;\n";
6065               pr "    }\n"
6066           | CompareWithString (field, expected) ->
6067               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
6068               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6069                 test_name field expected;
6070               pr "               r->%s);\n" field;
6071               pr "      return -1;\n";
6072               pr "    }\n"
6073           | CompareFieldsIntEq (field1, field2) ->
6074               pr "    if (r->%s != r->%s) {\n" field1 field2;
6075               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6076                 test_name field1 field2;
6077               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6078               pr "      return -1;\n";
6079               pr "    }\n"
6080           | CompareFieldsStrEq (field1, field2) ->
6081               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
6082               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6083                 test_name field1 field2;
6084               pr "               r->%s, r->%s);\n" field1 field2;
6085               pr "      return -1;\n";
6086               pr "    }\n"
6087         ) checks
6088       in
6089       List.iter (generate_test_command_call test_name) seq;
6090       generate_test_command_call ~test test_name last
6091   | TestLastFail seq ->
6092       pr "  /* TestLastFail for %s (%d) */\n" name i;
6093       let seq, last = get_seq_last seq in
6094       List.iter (generate_test_command_call test_name) seq;
6095       generate_test_command_call test_name ~expect_error:true last
6096
6097 (* Generate the code to run a command, leaving the result in 'r'.
6098  * If you expect to get an error then you should set expect_error:true.
6099  *)
6100 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6101   match cmd with
6102   | [] -> assert false
6103   | name :: args ->
6104       (* Look up the command to find out what args/ret it has. *)
6105       let style =
6106         try
6107           let _, style, _, _, _, _, _ =
6108             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6109           style
6110         with Not_found ->
6111           failwithf "%s: in test, command %s was not found" test_name name in
6112
6113       if List.length (snd style) <> List.length args then
6114         failwithf "%s: in test, wrong number of args given to %s"
6115           test_name name;
6116
6117       pr "  {\n";
6118
6119       List.iter (
6120         function
6121         | OptString n, "NULL" -> ()
6122         | Pathname n, arg
6123         | Device n, arg
6124         | Dev_or_Path n, arg
6125         | String n, arg
6126         | OptString n, arg ->
6127             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6128         | Int _, _
6129         | Int64 _, _
6130         | Bool _, _
6131         | FileIn _, _ | FileOut _, _ -> ()
6132         | StringList n, arg | DeviceList n, arg ->
6133             let strs = string_split " " arg in
6134             iteri (
6135               fun i str ->
6136                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6137             ) strs;
6138             pr "    const char *const %s[] = {\n" n;
6139             iteri (
6140               fun i _ -> pr "      %s_%d,\n" n i
6141             ) strs;
6142             pr "      NULL\n";
6143             pr "    };\n";
6144       ) (List.combine (snd style) args);
6145
6146       let error_code =
6147         match fst style with
6148         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6149         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6150         | RConstString _ | RConstOptString _ ->
6151             pr "    const char *r;\n"; "NULL"
6152         | RString _ -> pr "    char *r;\n"; "NULL"
6153         | RStringList _ | RHashtable _ ->
6154             pr "    char **r;\n";
6155             pr "    int i;\n";
6156             "NULL"
6157         | RStruct (_, typ) ->
6158             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6159         | RStructList (_, typ) ->
6160             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6161         | RBufferOut _ ->
6162             pr "    char *r;\n";
6163             pr "    size_t size;\n";
6164             "NULL" in
6165
6166       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6167       pr "    r = guestfs_%s (g" name;
6168
6169       (* Generate the parameters. *)
6170       List.iter (
6171         function
6172         | OptString _, "NULL" -> pr ", NULL"
6173         | Pathname n, _
6174         | Device n, _ | Dev_or_Path n, _
6175         | String n, _
6176         | OptString n, _ ->
6177             pr ", %s" n
6178         | FileIn _, arg | FileOut _, arg ->
6179             pr ", \"%s\"" (c_quote arg)
6180         | StringList n, _ | DeviceList n, _ ->
6181             pr ", (char **) %s" n
6182         | Int _, arg ->
6183             let i =
6184               try int_of_string arg
6185               with Failure "int_of_string" ->
6186                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6187             pr ", %d" i
6188         | Int64 _, arg ->
6189             let i =
6190               try Int64.of_string arg
6191               with Failure "int_of_string" ->
6192                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6193             pr ", %Ld" i
6194         | Bool _, arg ->
6195             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6196       ) (List.combine (snd style) args);
6197
6198       (match fst style with
6199        | RBufferOut _ -> pr ", &size"
6200        | _ -> ()
6201       );
6202
6203       pr ");\n";
6204
6205       if not expect_error then
6206         pr "    if (r == %s)\n" error_code
6207       else
6208         pr "    if (r != %s)\n" error_code;
6209       pr "      return -1;\n";
6210
6211       (* Insert the test code. *)
6212       (match test with
6213        | None -> ()
6214        | Some f -> f ()
6215       );
6216
6217       (match fst style with
6218        | RErr | RInt _ | RInt64 _ | RBool _
6219        | RConstString _ | RConstOptString _ -> ()
6220        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6221        | RStringList _ | RHashtable _ ->
6222            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6223            pr "      free (r[i]);\n";
6224            pr "    free (r);\n"
6225        | RStruct (_, typ) ->
6226            pr "    guestfs_free_%s (r);\n" typ
6227        | RStructList (_, typ) ->
6228            pr "    guestfs_free_%s_list (r);\n" typ
6229       );
6230
6231       pr "  }\n"
6232
6233 and c_quote str =
6234   let str = replace_str str "\r" "\\r" in
6235   let str = replace_str str "\n" "\\n" in
6236   let str = replace_str str "\t" "\\t" in
6237   let str = replace_str str "\000" "\\0" in
6238   str
6239
6240 (* Generate a lot of different functions for guestfish. *)
6241 and generate_fish_cmds () =
6242   generate_header CStyle GPLv2;
6243
6244   let all_functions =
6245     List.filter (
6246       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6247     ) all_functions in
6248   let all_functions_sorted =
6249     List.filter (
6250       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6251     ) all_functions_sorted in
6252
6253   pr "#include <stdio.h>\n";
6254   pr "#include <stdlib.h>\n";
6255   pr "#include <string.h>\n";
6256   pr "#include <inttypes.h>\n";
6257   pr "\n";
6258   pr "#include <guestfs.h>\n";
6259   pr "#include \"c-ctype.h\"\n";
6260   pr "#include \"fish.h\"\n";
6261   pr "\n";
6262
6263   (* list_commands function, which implements guestfish -h *)
6264   pr "void list_commands (void)\n";
6265   pr "{\n";
6266   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6267   pr "  list_builtin_commands ();\n";
6268   List.iter (
6269     fun (name, _, _, flags, _, shortdesc, _) ->
6270       let name = replace_char name '_' '-' in
6271       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6272         name shortdesc
6273   ) all_functions_sorted;
6274   pr "  printf (\"    %%s\\n\",";
6275   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6276   pr "}\n";
6277   pr "\n";
6278
6279   (* display_command function, which implements guestfish -h cmd *)
6280   pr "void display_command (const char *cmd)\n";
6281   pr "{\n";
6282   List.iter (
6283     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6284       let name2 = replace_char name '_' '-' in
6285       let alias =
6286         try find_map (function FishAlias n -> Some n | _ -> None) flags
6287         with Not_found -> name in
6288       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6289       let synopsis =
6290         match snd style with
6291         | [] -> name2
6292         | args ->
6293             sprintf "%s <%s>"
6294               name2 (String.concat "> <" (List.map name_of_argt args)) in
6295
6296       let warnings =
6297         if List.mem ProtocolLimitWarning flags then
6298           ("\n\n" ^ protocol_limit_warning)
6299         else "" in
6300
6301       (* For DangerWillRobinson commands, we should probably have
6302        * guestfish prompt before allowing you to use them (especially
6303        * in interactive mode). XXX
6304        *)
6305       let warnings =
6306         warnings ^
6307           if List.mem DangerWillRobinson flags then
6308             ("\n\n" ^ danger_will_robinson)
6309           else "" in
6310
6311       let warnings =
6312         warnings ^
6313           match deprecation_notice flags with
6314           | None -> ""
6315           | Some txt -> "\n\n" ^ txt in
6316
6317       let describe_alias =
6318         if name <> alias then
6319           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6320         else "" in
6321
6322       pr "  if (";
6323       pr "strcasecmp (cmd, \"%s\") == 0" name;
6324       if name <> name2 then
6325         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6326       if name <> alias then
6327         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6328       pr ")\n";
6329       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6330         name2 shortdesc
6331         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6332       pr "  else\n"
6333   ) all_functions;
6334   pr "    display_builtin_command (cmd);\n";
6335   pr "}\n";
6336   pr "\n";
6337
6338   let emit_print_list_function typ =
6339     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6340       typ typ typ;
6341     pr "{\n";
6342     pr "  unsigned int i;\n";
6343     pr "\n";
6344     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6345     pr "    printf (\"[%%d] = {\\n\", i);\n";
6346     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6347     pr "    printf (\"}\\n\");\n";
6348     pr "  }\n";
6349     pr "}\n";
6350     pr "\n";
6351   in
6352
6353   (* print_* functions *)
6354   List.iter (
6355     fun (typ, cols) ->
6356       let needs_i =
6357         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6358
6359       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6360       pr "{\n";
6361       if needs_i then (
6362         pr "  unsigned int i;\n";
6363         pr "\n"
6364       );
6365       List.iter (
6366         function
6367         | name, FString ->
6368             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6369         | name, FUUID ->
6370             pr "  printf (\"%%s%s: \", indent);\n" name;
6371             pr "  for (i = 0; i < 32; ++i)\n";
6372             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6373             pr "  printf (\"\\n\");\n"
6374         | name, FBuffer ->
6375             pr "  printf (\"%%s%s: \", indent);\n" name;
6376             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6377             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6378             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6379             pr "    else\n";
6380             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6381             pr "  printf (\"\\n\");\n"
6382         | name, (FUInt64|FBytes) ->
6383             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6384               name typ name
6385         | name, FInt64 ->
6386             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6387               name typ name
6388         | name, FUInt32 ->
6389             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6390               name typ name
6391         | name, FInt32 ->
6392             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6393               name typ name
6394         | name, FChar ->
6395             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6396               name typ name
6397         | name, FOptPercent ->
6398             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6399               typ name name typ name;
6400             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6401       ) cols;
6402       pr "}\n";
6403       pr "\n";
6404   ) structs;
6405
6406   (* Emit a print_TYPE_list function definition only if that function is used. *)
6407   List.iter (
6408     function
6409     | typ, (RStructListOnly | RStructAndList) ->
6410         (* generate the function for typ *)
6411         emit_print_list_function typ
6412     | typ, _ -> () (* empty *)
6413   ) (rstructs_used_by all_functions);
6414
6415   (* Emit a print_TYPE function definition only if that function is used. *)
6416   List.iter (
6417     function
6418     | typ, (RStructOnly | RStructAndList) ->
6419         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6420         pr "{\n";
6421         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6422         pr "}\n";
6423         pr "\n";
6424     | typ, _ -> () (* empty *)
6425   ) (rstructs_used_by all_functions);
6426
6427   (* run_<action> actions *)
6428   List.iter (
6429     fun (name, style, _, flags, _, _, _) ->
6430       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6431       pr "{\n";
6432       (match fst style with
6433        | RErr
6434        | RInt _
6435        | RBool _ -> pr "  int r;\n"
6436        | RInt64 _ -> pr "  int64_t r;\n"
6437        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6438        | RString _ -> pr "  char *r;\n"
6439        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6440        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6441        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6442        | RBufferOut _ ->
6443            pr "  char *r;\n";
6444            pr "  size_t size;\n";
6445       );
6446       List.iter (
6447         function
6448         | Device n
6449         | String n
6450         | OptString n
6451         | FileIn n
6452         | FileOut n -> pr "  const char *%s;\n" n
6453         | Pathname n
6454         | Dev_or_Path n -> pr "  char *%s;\n" n
6455         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6456         | Bool n -> pr "  int %s;\n" n
6457         | Int n -> pr "  int %s;\n" n
6458         | Int64 n -> pr "  int64_t %s;\n" n
6459       ) (snd style);
6460
6461       (* Check and convert parameters. *)
6462       let argc_expected = List.length (snd style) in
6463       pr "  if (argc != %d) {\n" argc_expected;
6464       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6465         argc_expected;
6466       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6467       pr "    return -1;\n";
6468       pr "  }\n";
6469       iteri (
6470         fun i ->
6471           function
6472           | Device name
6473           | String name ->
6474               pr "  %s = argv[%d];\n" name i
6475           | Pathname name
6476           | Dev_or_Path name ->
6477               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6478               pr "  if (%s == NULL) return -1;\n" name
6479           | OptString name ->
6480               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6481                 name i i
6482           | FileIn name ->
6483               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6484                 name i i
6485           | FileOut name ->
6486               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6487                 name i i
6488           | StringList name | DeviceList name ->
6489               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6490               pr "  if (%s == NULL) return -1;\n" name;
6491           | Bool name ->
6492               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6493           | Int name ->
6494               pr "  %s = atoi (argv[%d]);\n" name i
6495           | Int64 name ->
6496               pr "  %s = atoll (argv[%d]);\n" name i
6497       ) (snd style);
6498
6499       (* Call C API function. *)
6500       let fn =
6501         try find_map (function FishAction n -> Some n | _ -> None) flags
6502         with Not_found -> sprintf "guestfs_%s" name in
6503       pr "  r = %s " fn;
6504       generate_c_call_args ~handle:"g" style;
6505       pr ";\n";
6506
6507       List.iter (
6508         function
6509         | Device name | String name
6510         | OptString name | FileIn name | FileOut name | Bool name
6511         | Int name | Int64 name -> ()
6512         | Pathname name | Dev_or_Path name ->
6513             pr "  free (%s);\n" name
6514         | StringList name | DeviceList name ->
6515             pr "  free_strings (%s);\n" name
6516       ) (snd style);
6517
6518       (* Check return value for errors and display command results. *)
6519       (match fst style with
6520        | RErr -> pr "  return r;\n"
6521        | RInt _ ->
6522            pr "  if (r == -1) return -1;\n";
6523            pr "  printf (\"%%d\\n\", r);\n";
6524            pr "  return 0;\n"
6525        | RInt64 _ ->
6526            pr "  if (r == -1) return -1;\n";
6527            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6528            pr "  return 0;\n"
6529        | RBool _ ->
6530            pr "  if (r == -1) return -1;\n";
6531            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6532            pr "  return 0;\n"
6533        | RConstString _ ->
6534            pr "  if (r == NULL) return -1;\n";
6535            pr "  printf (\"%%s\\n\", r);\n";
6536            pr "  return 0;\n"
6537        | RConstOptString _ ->
6538            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6539            pr "  return 0;\n"
6540        | RString _ ->
6541            pr "  if (r == NULL) return -1;\n";
6542            pr "  printf (\"%%s\\n\", r);\n";
6543            pr "  free (r);\n";
6544            pr "  return 0;\n"
6545        | RStringList _ ->
6546            pr "  if (r == NULL) return -1;\n";
6547            pr "  print_strings (r);\n";
6548            pr "  free_strings (r);\n";
6549            pr "  return 0;\n"
6550        | RStruct (_, typ) ->
6551            pr "  if (r == NULL) return -1;\n";
6552            pr "  print_%s (r);\n" typ;
6553            pr "  guestfs_free_%s (r);\n" typ;
6554            pr "  return 0;\n"
6555        | RStructList (_, typ) ->
6556            pr "  if (r == NULL) return -1;\n";
6557            pr "  print_%s_list (r);\n" typ;
6558            pr "  guestfs_free_%s_list (r);\n" typ;
6559            pr "  return 0;\n"
6560        | RHashtable _ ->
6561            pr "  if (r == NULL) return -1;\n";
6562            pr "  print_table (r);\n";
6563            pr "  free_strings (r);\n";
6564            pr "  return 0;\n"
6565        | RBufferOut _ ->
6566            pr "  if (r == NULL) return -1;\n";
6567            pr "  fwrite (r, size, 1, stdout);\n";
6568            pr "  free (r);\n";
6569            pr "  return 0;\n"
6570       );
6571       pr "}\n";
6572       pr "\n"
6573   ) all_functions;
6574
6575   (* run_action function *)
6576   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6577   pr "{\n";
6578   List.iter (
6579     fun (name, _, _, flags, _, _, _) ->
6580       let name2 = replace_char name '_' '-' in
6581       let alias =
6582         try find_map (function FishAlias n -> Some n | _ -> None) flags
6583         with Not_found -> name in
6584       pr "  if (";
6585       pr "strcasecmp (cmd, \"%s\") == 0" name;
6586       if name <> name2 then
6587         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6588       if name <> alias then
6589         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6590       pr ")\n";
6591       pr "    return run_%s (cmd, argc, argv);\n" name;
6592       pr "  else\n";
6593   ) all_functions;
6594   pr "    {\n";
6595   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6596   pr "      return -1;\n";
6597   pr "    }\n";
6598   pr "  return 0;\n";
6599   pr "}\n";
6600   pr "\n"
6601
6602 (* Readline completion for guestfish. *)
6603 and generate_fish_completion () =
6604   generate_header CStyle GPLv2;
6605
6606   let all_functions =
6607     List.filter (
6608       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6609     ) all_functions in
6610
6611   pr "\
6612 #include <config.h>
6613
6614 #include <stdio.h>
6615 #include <stdlib.h>
6616 #include <string.h>
6617
6618 #ifdef HAVE_LIBREADLINE
6619 #include <readline/readline.h>
6620 #endif
6621
6622 #include \"fish.h\"
6623
6624 #ifdef HAVE_LIBREADLINE
6625
6626 static const char *const commands[] = {
6627   BUILTIN_COMMANDS_FOR_COMPLETION,
6628 ";
6629
6630   (* Get the commands, including the aliases.  They don't need to be
6631    * sorted - the generator() function just does a dumb linear search.
6632    *)
6633   let commands =
6634     List.map (
6635       fun (name, _, _, flags, _, _, _) ->
6636         let name2 = replace_char name '_' '-' in
6637         let alias =
6638           try find_map (function FishAlias n -> Some n | _ -> None) flags
6639           with Not_found -> name in
6640
6641         if name <> alias then [name2; alias] else [name2]
6642     ) all_functions in
6643   let commands = List.flatten commands in
6644
6645   List.iter (pr "  \"%s\",\n") commands;
6646
6647   pr "  NULL
6648 };
6649
6650 static char *
6651 generator (const char *text, int state)
6652 {
6653   static int index, len;
6654   const char *name;
6655
6656   if (!state) {
6657     index = 0;
6658     len = strlen (text);
6659   }
6660
6661   rl_attempted_completion_over = 1;
6662
6663   while ((name = commands[index]) != NULL) {
6664     index++;
6665     if (strncasecmp (name, text, len) == 0)
6666       return strdup (name);
6667   }
6668
6669   return NULL;
6670 }
6671
6672 #endif /* HAVE_LIBREADLINE */
6673
6674 char **do_completion (const char *text, int start, int end)
6675 {
6676   char **matches = NULL;
6677
6678 #ifdef HAVE_LIBREADLINE
6679   rl_completion_append_character = ' ';
6680
6681   if (start == 0)
6682     matches = rl_completion_matches (text, generator);
6683   else if (complete_dest_paths)
6684     matches = rl_completion_matches (text, complete_dest_paths_generator);
6685 #endif
6686
6687   return matches;
6688 }
6689 ";
6690
6691 (* Generate the POD documentation for guestfish. *)
6692 and generate_fish_actions_pod () =
6693   let all_functions_sorted =
6694     List.filter (
6695       fun (_, _, _, flags, _, _, _) ->
6696         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6697     ) all_functions_sorted in
6698
6699   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6700
6701   List.iter (
6702     fun (name, style, _, flags, _, _, longdesc) ->
6703       let longdesc =
6704         Str.global_substitute rex (
6705           fun s ->
6706             let sub =
6707               try Str.matched_group 1 s
6708               with Not_found ->
6709                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6710             "C<" ^ replace_char sub '_' '-' ^ ">"
6711         ) longdesc in
6712       let name = replace_char name '_' '-' in
6713       let alias =
6714         try find_map (function FishAlias n -> Some n | _ -> None) flags
6715         with Not_found -> name in
6716
6717       pr "=head2 %s" name;
6718       if name <> alias then
6719         pr " | %s" alias;
6720       pr "\n";
6721       pr "\n";
6722       pr " %s" name;
6723       List.iter (
6724         function
6725         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6726         | OptString n -> pr " %s" n
6727         | StringList n | DeviceList n -> pr " '%s ...'" n
6728         | Bool _ -> pr " true|false"
6729         | Int n -> pr " %s" n
6730         | Int64 n -> pr " %s" n
6731         | FileIn n | FileOut n -> pr " (%s|-)" n
6732       ) (snd style);
6733       pr "\n";
6734       pr "\n";
6735       pr "%s\n\n" longdesc;
6736
6737       if List.exists (function FileIn _ | FileOut _ -> true
6738                       | _ -> false) (snd style) then
6739         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6740
6741       if List.mem ProtocolLimitWarning flags then
6742         pr "%s\n\n" protocol_limit_warning;
6743
6744       if List.mem DangerWillRobinson flags then
6745         pr "%s\n\n" danger_will_robinson;
6746
6747       match deprecation_notice flags with
6748       | None -> ()
6749       | Some txt -> pr "%s\n\n" txt
6750   ) all_functions_sorted
6751
6752 (* Generate a C function prototype. *)
6753 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6754     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6755     ?(prefix = "")
6756     ?handle name style =
6757   if extern then pr "extern ";
6758   if static then pr "static ";
6759   (match fst style with
6760    | RErr -> pr "int "
6761    | RInt _ -> pr "int "
6762    | RInt64 _ -> pr "int64_t "
6763    | RBool _ -> pr "int "
6764    | RConstString _ | RConstOptString _ -> pr "const char *"
6765    | RString _ | RBufferOut _ -> pr "char *"
6766    | RStringList _ | RHashtable _ -> pr "char **"
6767    | RStruct (_, typ) ->
6768        if not in_daemon then pr "struct guestfs_%s *" typ
6769        else pr "guestfs_int_%s *" typ
6770    | RStructList (_, typ) ->
6771        if not in_daemon then pr "struct guestfs_%s_list *" typ
6772        else pr "guestfs_int_%s_list *" typ
6773   );
6774   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6775   pr "%s%s (" prefix name;
6776   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6777     pr "void"
6778   else (
6779     let comma = ref false in
6780     (match handle with
6781      | None -> ()
6782      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6783     );
6784     let next () =
6785       if !comma then (
6786         if single_line then pr ", " else pr ",\n\t\t"
6787       );
6788       comma := true
6789     in
6790     List.iter (
6791       function
6792       | Pathname n
6793       | Device n | Dev_or_Path n
6794       | String n
6795       | OptString n ->
6796           next ();
6797           pr "const char *%s" n
6798       | StringList n | DeviceList n ->
6799           next ();
6800           pr "char *const *%s" n
6801       | Bool n -> next (); pr "int %s" n
6802       | Int n -> next (); pr "int %s" n
6803       | Int64 n -> next (); pr "int64_t %s" n
6804       | FileIn n
6805       | FileOut n ->
6806           if not in_daemon then (next (); pr "const char *%s" n)
6807     ) (snd style);
6808     if is_RBufferOut then (next (); pr "size_t *size_r");
6809   );
6810   pr ")";
6811   if semicolon then pr ";";
6812   if newline then pr "\n"
6813
6814 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6815 and generate_c_call_args ?handle ?(decl = false) style =
6816   pr "(";
6817   let comma = ref false in
6818   let next () =
6819     if !comma then pr ", ";
6820     comma := true
6821   in
6822   (match handle with
6823    | None -> ()
6824    | Some handle -> pr "%s" handle; comma := true
6825   );
6826   List.iter (
6827     fun arg ->
6828       next ();
6829       pr "%s" (name_of_argt arg)
6830   ) (snd style);
6831   (* For RBufferOut calls, add implicit &size parameter. *)
6832   if not decl then (
6833     match fst style with
6834     | RBufferOut _ ->
6835         next ();
6836         pr "&size"
6837     | _ -> ()
6838   );
6839   pr ")"
6840
6841 (* Generate the OCaml bindings interface. *)
6842 and generate_ocaml_mli () =
6843   generate_header OCamlStyle LGPLv2;
6844
6845   pr "\
6846 (** For API documentation you should refer to the C API
6847     in the guestfs(3) manual page.  The OCaml API uses almost
6848     exactly the same calls. *)
6849
6850 type t
6851 (** A [guestfs_h] handle. *)
6852
6853 exception Error of string
6854 (** This exception is raised when there is an error. *)
6855
6856 val create : unit -> t
6857
6858 val close : t -> unit
6859 (** Handles are closed by the garbage collector when they become
6860     unreferenced, but callers can also call this in order to
6861     provide predictable cleanup. *)
6862
6863 ";
6864   generate_ocaml_structure_decls ();
6865
6866   (* The actions. *)
6867   List.iter (
6868     fun (name, style, _, _, _, shortdesc, _) ->
6869       generate_ocaml_prototype name style;
6870       pr "(** %s *)\n" shortdesc;
6871       pr "\n"
6872   ) all_functions
6873
6874 (* Generate the OCaml bindings implementation. *)
6875 and generate_ocaml_ml () =
6876   generate_header OCamlStyle LGPLv2;
6877
6878   pr "\
6879 type t
6880 exception Error of string
6881 external create : unit -> t = \"ocaml_guestfs_create\"
6882 external close : t -> unit = \"ocaml_guestfs_close\"
6883
6884 let () =
6885   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6886
6887 ";
6888
6889   generate_ocaml_structure_decls ();
6890
6891   (* The actions. *)
6892   List.iter (
6893     fun (name, style, _, _, _, shortdesc, _) ->
6894       generate_ocaml_prototype ~is_external:true name style;
6895   ) all_functions
6896
6897 (* Generate the OCaml bindings C implementation. *)
6898 and generate_ocaml_c () =
6899   generate_header CStyle LGPLv2;
6900
6901   pr "\
6902 #include <stdio.h>
6903 #include <stdlib.h>
6904 #include <string.h>
6905
6906 #include <caml/config.h>
6907 #include <caml/alloc.h>
6908 #include <caml/callback.h>
6909 #include <caml/fail.h>
6910 #include <caml/memory.h>
6911 #include <caml/mlvalues.h>
6912 #include <caml/signals.h>
6913
6914 #include <guestfs.h>
6915
6916 #include \"guestfs_c.h\"
6917
6918 /* Copy a hashtable of string pairs into an assoc-list.  We return
6919  * the list in reverse order, but hashtables aren't supposed to be
6920  * ordered anyway.
6921  */
6922 static CAMLprim value
6923 copy_table (char * const * argv)
6924 {
6925   CAMLparam0 ();
6926   CAMLlocal5 (rv, pairv, kv, vv, cons);
6927   int i;
6928
6929   rv = Val_int (0);
6930   for (i = 0; argv[i] != NULL; i += 2) {
6931     kv = caml_copy_string (argv[i]);
6932     vv = caml_copy_string (argv[i+1]);
6933     pairv = caml_alloc (2, 0);
6934     Store_field (pairv, 0, kv);
6935     Store_field (pairv, 1, vv);
6936     cons = caml_alloc (2, 0);
6937     Store_field (cons, 1, rv);
6938     rv = cons;
6939     Store_field (cons, 0, pairv);
6940   }
6941
6942   CAMLreturn (rv);
6943 }
6944
6945 ";
6946
6947   (* Struct copy functions. *)
6948
6949   let emit_ocaml_copy_list_function typ =
6950     pr "static CAMLprim value\n";
6951     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6952     pr "{\n";
6953     pr "  CAMLparam0 ();\n";
6954     pr "  CAMLlocal2 (rv, v);\n";
6955     pr "  unsigned int i;\n";
6956     pr "\n";
6957     pr "  if (%ss->len == 0)\n" typ;
6958     pr "    CAMLreturn (Atom (0));\n";
6959     pr "  else {\n";
6960     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6961     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6962     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6963     pr "      caml_modify (&Field (rv, i), v);\n";
6964     pr "    }\n";
6965     pr "    CAMLreturn (rv);\n";
6966     pr "  }\n";
6967     pr "}\n";
6968     pr "\n";
6969   in
6970
6971   List.iter (
6972     fun (typ, cols) ->
6973       let has_optpercent_col =
6974         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6975
6976       pr "static CAMLprim value\n";
6977       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6978       pr "{\n";
6979       pr "  CAMLparam0 ();\n";
6980       if has_optpercent_col then
6981         pr "  CAMLlocal3 (rv, v, v2);\n"
6982       else
6983         pr "  CAMLlocal2 (rv, v);\n";
6984       pr "\n";
6985       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6986       iteri (
6987         fun i col ->
6988           (match col with
6989            | name, FString ->
6990                pr "  v = caml_copy_string (%s->%s);\n" typ name
6991            | name, FBuffer ->
6992                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6993                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6994                  typ name typ name
6995            | name, FUUID ->
6996                pr "  v = caml_alloc_string (32);\n";
6997                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6998            | name, (FBytes|FInt64|FUInt64) ->
6999                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7000            | name, (FInt32|FUInt32) ->
7001                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7002            | name, FOptPercent ->
7003                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7004                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7005                pr "    v = caml_alloc (1, 0);\n";
7006                pr "    Store_field (v, 0, v2);\n";
7007                pr "  } else /* None */\n";
7008                pr "    v = Val_int (0);\n";
7009            | name, FChar ->
7010                pr "  v = Val_int (%s->%s);\n" typ name
7011           );
7012           pr "  Store_field (rv, %d, v);\n" i
7013       ) cols;
7014       pr "  CAMLreturn (rv);\n";
7015       pr "}\n";
7016       pr "\n";
7017   ) structs;
7018
7019   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7020   List.iter (
7021     function
7022     | typ, (RStructListOnly | RStructAndList) ->
7023         (* generate the function for typ *)
7024         emit_ocaml_copy_list_function typ
7025     | typ, _ -> () (* empty *)
7026   ) (rstructs_used_by all_functions);
7027
7028   (* The wrappers. *)
7029   List.iter (
7030     fun (name, style, _, _, _, _, _) ->
7031       let params =
7032         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7033
7034       let needs_extra_vs =
7035         match fst style with RConstOptString _ -> true | _ -> false in
7036
7037       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7038       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7039       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7040
7041       pr "CAMLprim value\n";
7042       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7043       List.iter (pr ", value %s") (List.tl params);
7044       pr ")\n";
7045       pr "{\n";
7046
7047       (match params with
7048        | [p1; p2; p3; p4; p5] ->
7049            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7050        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7051            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7052            pr "  CAMLxparam%d (%s);\n"
7053              (List.length rest) (String.concat ", " rest)
7054        | ps ->
7055            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7056       );
7057       if not needs_extra_vs then
7058         pr "  CAMLlocal1 (rv);\n"
7059       else
7060         pr "  CAMLlocal3 (rv, v, v2);\n";
7061       pr "\n";
7062
7063       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7064       pr "  if (g == NULL)\n";
7065       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
7066       pr "\n";
7067
7068       List.iter (
7069         function
7070         | Pathname n
7071         | Device n | Dev_or_Path n
7072         | String n
7073         | FileIn n
7074         | FileOut n ->
7075             pr "  const char *%s = String_val (%sv);\n" n n
7076         | OptString n ->
7077             pr "  const char *%s =\n" n;
7078             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7079               n n
7080         | StringList n | DeviceList n ->
7081             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7082         | Bool n ->
7083             pr "  int %s = Bool_val (%sv);\n" n n
7084         | Int n ->
7085             pr "  int %s = Int_val (%sv);\n" n n
7086         | Int64 n ->
7087             pr "  int64_t %s = Int64_val (%sv);\n" n n
7088       ) (snd style);
7089       let error_code =
7090         match fst style with
7091         | RErr -> pr "  int r;\n"; "-1"
7092         | RInt _ -> pr "  int r;\n"; "-1"
7093         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7094         | RBool _ -> pr "  int r;\n"; "-1"
7095         | RConstString _ | RConstOptString _ ->
7096             pr "  const char *r;\n"; "NULL"
7097         | RString _ -> pr "  char *r;\n"; "NULL"
7098         | RStringList _ ->
7099             pr "  int i;\n";
7100             pr "  char **r;\n";
7101             "NULL"
7102         | RStruct (_, typ) ->
7103             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7104         | RStructList (_, typ) ->
7105             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7106         | RHashtable _ ->
7107             pr "  int i;\n";
7108             pr "  char **r;\n";
7109             "NULL"
7110         | RBufferOut _ ->
7111             pr "  char *r;\n";
7112             pr "  size_t size;\n";
7113             "NULL" in
7114       pr "\n";
7115
7116       pr "  caml_enter_blocking_section ();\n";
7117       pr "  r = guestfs_%s " name;
7118       generate_c_call_args ~handle:"g" style;
7119       pr ";\n";
7120       pr "  caml_leave_blocking_section ();\n";
7121
7122       List.iter (
7123         function
7124         | StringList n | DeviceList n ->
7125             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7126         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7127         | Bool _ | Int _ | Int64 _
7128         | FileIn _ | FileOut _ -> ()
7129       ) (snd style);
7130
7131       pr "  if (r == %s)\n" error_code;
7132       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7133       pr "\n";
7134
7135       (match fst style with
7136        | RErr -> pr "  rv = Val_unit;\n"
7137        | RInt _ -> pr "  rv = Val_int (r);\n"
7138        | RInt64 _ ->
7139            pr "  rv = caml_copy_int64 (r);\n"
7140        | RBool _ -> pr "  rv = Val_bool (r);\n"
7141        | RConstString _ ->
7142            pr "  rv = caml_copy_string (r);\n"
7143        | RConstOptString _ ->
7144            pr "  if (r) { /* Some string */\n";
7145            pr "    v = caml_alloc (1, 0);\n";
7146            pr "    v2 = caml_copy_string (r);\n";
7147            pr "    Store_field (v, 0, v2);\n";
7148            pr "  } else /* None */\n";
7149            pr "    v = Val_int (0);\n";
7150        | RString _ ->
7151            pr "  rv = caml_copy_string (r);\n";
7152            pr "  free (r);\n"
7153        | RStringList _ ->
7154            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7155            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7156            pr "  free (r);\n"
7157        | RStruct (_, typ) ->
7158            pr "  rv = copy_%s (r);\n" typ;
7159            pr "  guestfs_free_%s (r);\n" typ;
7160        | RStructList (_, typ) ->
7161            pr "  rv = copy_%s_list (r);\n" typ;
7162            pr "  guestfs_free_%s_list (r);\n" typ;
7163        | RHashtable _ ->
7164            pr "  rv = copy_table (r);\n";
7165            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7166            pr "  free (r);\n";
7167        | RBufferOut _ ->
7168            pr "  rv = caml_alloc_string (size);\n";
7169            pr "  memcpy (String_val (rv), r, size);\n";
7170       );
7171
7172       pr "  CAMLreturn (rv);\n";
7173       pr "}\n";
7174       pr "\n";
7175
7176       if List.length params > 5 then (
7177         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7178         pr "CAMLprim value ";
7179         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7180         pr "CAMLprim value\n";
7181         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7182         pr "{\n";
7183         pr "  return ocaml_guestfs_%s (argv[0]" name;
7184         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7185         pr ");\n";
7186         pr "}\n";
7187         pr "\n"
7188       )
7189   ) all_functions
7190
7191 and generate_ocaml_structure_decls () =
7192   List.iter (
7193     fun (typ, cols) ->
7194       pr "type %s = {\n" typ;
7195       List.iter (
7196         function
7197         | name, FString -> pr "  %s : string;\n" name
7198         | name, FBuffer -> pr "  %s : string;\n" name
7199         | name, FUUID -> pr "  %s : string;\n" name
7200         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7201         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7202         | name, FChar -> pr "  %s : char;\n" name
7203         | name, FOptPercent -> pr "  %s : float option;\n" name
7204       ) cols;
7205       pr "}\n";
7206       pr "\n"
7207   ) structs
7208
7209 and generate_ocaml_prototype ?(is_external = false) name style =
7210   if is_external then pr "external " else pr "val ";
7211   pr "%s : t -> " name;
7212   List.iter (
7213     function
7214     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7215     | OptString _ -> pr "string option -> "
7216     | StringList _ | DeviceList _ -> pr "string array -> "
7217     | Bool _ -> pr "bool -> "
7218     | Int _ -> pr "int -> "
7219     | Int64 _ -> pr "int64 -> "
7220   ) (snd style);
7221   (match fst style with
7222    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7223    | RInt _ -> pr "int"
7224    | RInt64 _ -> pr "int64"
7225    | RBool _ -> pr "bool"
7226    | RConstString _ -> pr "string"
7227    | RConstOptString _ -> pr "string option"
7228    | RString _ | RBufferOut _ -> pr "string"
7229    | RStringList _ -> pr "string array"
7230    | RStruct (_, typ) -> pr "%s" typ
7231    | RStructList (_, typ) -> pr "%s array" typ
7232    | RHashtable _ -> pr "(string * string) list"
7233   );
7234   if is_external then (
7235     pr " = ";
7236     if List.length (snd style) + 1 > 5 then
7237       pr "\"ocaml_guestfs_%s_byte\" " name;
7238     pr "\"ocaml_guestfs_%s\"" name
7239   );
7240   pr "\n"
7241
7242 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7243 and generate_perl_xs () =
7244   generate_header CStyle LGPLv2;
7245
7246   pr "\
7247 #include \"EXTERN.h\"
7248 #include \"perl.h\"
7249 #include \"XSUB.h\"
7250
7251 #include <guestfs.h>
7252
7253 #ifndef PRId64
7254 #define PRId64 \"lld\"
7255 #endif
7256
7257 static SV *
7258 my_newSVll(long long val) {
7259 #ifdef USE_64_BIT_ALL
7260   return newSViv(val);
7261 #else
7262   char buf[100];
7263   int len;
7264   len = snprintf(buf, 100, \"%%\" PRId64, val);
7265   return newSVpv(buf, len);
7266 #endif
7267 }
7268
7269 #ifndef PRIu64
7270 #define PRIu64 \"llu\"
7271 #endif
7272
7273 static SV *
7274 my_newSVull(unsigned long long val) {
7275 #ifdef USE_64_BIT_ALL
7276   return newSVuv(val);
7277 #else
7278   char buf[100];
7279   int len;
7280   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7281   return newSVpv(buf, len);
7282 #endif
7283 }
7284
7285 /* http://www.perlmonks.org/?node_id=680842 */
7286 static char **
7287 XS_unpack_charPtrPtr (SV *arg) {
7288   char **ret;
7289   AV *av;
7290   I32 i;
7291
7292   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7293     croak (\"array reference expected\");
7294
7295   av = (AV *)SvRV (arg);
7296   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7297   if (!ret)
7298     croak (\"malloc failed\");
7299
7300   for (i = 0; i <= av_len (av); i++) {
7301     SV **elem = av_fetch (av, i, 0);
7302
7303     if (!elem || !*elem)
7304       croak (\"missing element in list\");
7305
7306     ret[i] = SvPV_nolen (*elem);
7307   }
7308
7309   ret[i] = NULL;
7310
7311   return ret;
7312 }
7313
7314 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7315
7316 PROTOTYPES: ENABLE
7317
7318 guestfs_h *
7319 _create ()
7320    CODE:
7321       RETVAL = guestfs_create ();
7322       if (!RETVAL)
7323         croak (\"could not create guestfs handle\");
7324       guestfs_set_error_handler (RETVAL, NULL, NULL);
7325  OUTPUT:
7326       RETVAL
7327
7328 void
7329 DESTROY (g)
7330       guestfs_h *g;
7331  PPCODE:
7332       guestfs_close (g);
7333
7334 ";
7335
7336   List.iter (
7337     fun (name, style, _, _, _, _, _) ->
7338       (match fst style with
7339        | RErr -> pr "void\n"
7340        | RInt _ -> pr "SV *\n"
7341        | RInt64 _ -> pr "SV *\n"
7342        | RBool _ -> pr "SV *\n"
7343        | RConstString _ -> pr "SV *\n"
7344        | RConstOptString _ -> pr "SV *\n"
7345        | RString _ -> pr "SV *\n"
7346        | RBufferOut _ -> pr "SV *\n"
7347        | RStringList _
7348        | RStruct _ | RStructList _
7349        | RHashtable _ ->
7350            pr "void\n" (* all lists returned implictly on the stack *)
7351       );
7352       (* Call and arguments. *)
7353       pr "%s " name;
7354       generate_c_call_args ~handle:"g" ~decl:true style;
7355       pr "\n";
7356       pr "      guestfs_h *g;\n";
7357       iteri (
7358         fun i ->
7359           function
7360           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7361               pr "      char *%s;\n" n
7362           | OptString n ->
7363               (* http://www.perlmonks.org/?node_id=554277
7364                * Note that the implicit handle argument means we have
7365                * to add 1 to the ST(x) operator.
7366                *)
7367               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7368           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7369           | Bool n -> pr "      int %s;\n" n
7370           | Int n -> pr "      int %s;\n" n
7371           | Int64 n -> pr "      int64_t %s;\n" n
7372       ) (snd style);
7373
7374       let do_cleanups () =
7375         List.iter (
7376           function
7377           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7378           | Bool _ | Int _ | Int64 _
7379           | FileIn _ | FileOut _ -> ()
7380           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7381         ) (snd style)
7382       in
7383
7384       (* Code. *)
7385       (match fst style with
7386        | RErr ->
7387            pr "PREINIT:\n";
7388            pr "      int r;\n";
7389            pr " PPCODE:\n";
7390            pr "      r = guestfs_%s " name;
7391            generate_c_call_args ~handle:"g" style;
7392            pr ";\n";
7393            do_cleanups ();
7394            pr "      if (r == -1)\n";
7395            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7396        | RInt n
7397        | RBool n ->
7398            pr "PREINIT:\n";
7399            pr "      int %s;\n" n;
7400            pr "   CODE:\n";
7401            pr "      %s = guestfs_%s " n name;
7402            generate_c_call_args ~handle:"g" style;
7403            pr ";\n";
7404            do_cleanups ();
7405            pr "      if (%s == -1)\n" n;
7406            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7407            pr "      RETVAL = newSViv (%s);\n" n;
7408            pr " OUTPUT:\n";
7409            pr "      RETVAL\n"
7410        | RInt64 n ->
7411            pr "PREINIT:\n";
7412            pr "      int64_t %s;\n" n;
7413            pr "   CODE:\n";
7414            pr "      %s = guestfs_%s " n name;
7415            generate_c_call_args ~handle:"g" style;
7416            pr ";\n";
7417            do_cleanups ();
7418            pr "      if (%s == -1)\n" n;
7419            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7420            pr "      RETVAL = my_newSVll (%s);\n" n;
7421            pr " OUTPUT:\n";
7422            pr "      RETVAL\n"
7423        | RConstString n ->
7424            pr "PREINIT:\n";
7425            pr "      const char *%s;\n" n;
7426            pr "   CODE:\n";
7427            pr "      %s = guestfs_%s " n name;
7428            generate_c_call_args ~handle:"g" style;
7429            pr ";\n";
7430            do_cleanups ();
7431            pr "      if (%s == NULL)\n" n;
7432            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7433            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7434            pr " OUTPUT:\n";
7435            pr "      RETVAL\n"
7436        | RConstOptString n ->
7437            pr "PREINIT:\n";
7438            pr "      const char *%s;\n" n;
7439            pr "   CODE:\n";
7440            pr "      %s = guestfs_%s " n name;
7441            generate_c_call_args ~handle:"g" style;
7442            pr ";\n";
7443            do_cleanups ();
7444            pr "      if (%s == NULL)\n" n;
7445            pr "        RETVAL = &PL_sv_undef;\n";
7446            pr "      else\n";
7447            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7448            pr " OUTPUT:\n";
7449            pr "      RETVAL\n"
7450        | RString n ->
7451            pr "PREINIT:\n";
7452            pr "      char *%s;\n" n;
7453            pr "   CODE:\n";
7454            pr "      %s = guestfs_%s " n name;
7455            generate_c_call_args ~handle:"g" style;
7456            pr ";\n";
7457            do_cleanups ();
7458            pr "      if (%s == NULL)\n" n;
7459            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7460            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7461            pr "      free (%s);\n" n;
7462            pr " OUTPUT:\n";
7463            pr "      RETVAL\n"
7464        | RStringList n | RHashtable n ->
7465            pr "PREINIT:\n";
7466            pr "      char **%s;\n" n;
7467            pr "      int i, n;\n";
7468            pr " PPCODE:\n";
7469            pr "      %s = guestfs_%s " n name;
7470            generate_c_call_args ~handle:"g" style;
7471            pr ";\n";
7472            do_cleanups ();
7473            pr "      if (%s == NULL)\n" n;
7474            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7475            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7476            pr "      EXTEND (SP, n);\n";
7477            pr "      for (i = 0; i < n; ++i) {\n";
7478            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7479            pr "        free (%s[i]);\n" n;
7480            pr "      }\n";
7481            pr "      free (%s);\n" n;
7482        | RStruct (n, typ) ->
7483            let cols = cols_of_struct typ in
7484            generate_perl_struct_code typ cols name style n do_cleanups
7485        | RStructList (n, typ) ->
7486            let cols = cols_of_struct typ in
7487            generate_perl_struct_list_code typ cols name style n do_cleanups
7488        | RBufferOut n ->
7489            pr "PREINIT:\n";
7490            pr "      char *%s;\n" n;
7491            pr "      size_t size;\n";
7492            pr "   CODE:\n";
7493            pr "      %s = guestfs_%s " n name;
7494            generate_c_call_args ~handle:"g" style;
7495            pr ";\n";
7496            do_cleanups ();
7497            pr "      if (%s == NULL)\n" n;
7498            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7499            pr "      RETVAL = newSVpv (%s, size);\n" n;
7500            pr "      free (%s);\n" n;
7501            pr " OUTPUT:\n";
7502            pr "      RETVAL\n"
7503       );
7504
7505       pr "\n"
7506   ) all_functions
7507
7508 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7509   pr "PREINIT:\n";
7510   pr "      struct guestfs_%s_list *%s;\n" typ n;
7511   pr "      int i;\n";
7512   pr "      HV *hv;\n";
7513   pr " PPCODE:\n";
7514   pr "      %s = guestfs_%s " n name;
7515   generate_c_call_args ~handle:"g" style;
7516   pr ";\n";
7517   do_cleanups ();
7518   pr "      if (%s == NULL)\n" n;
7519   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7520   pr "      EXTEND (SP, %s->len);\n" n;
7521   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7522   pr "        hv = newHV ();\n";
7523   List.iter (
7524     function
7525     | name, FString ->
7526         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7527           name (String.length name) n name
7528     | name, FUUID ->
7529         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7530           name (String.length name) n name
7531     | name, FBuffer ->
7532         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7533           name (String.length name) n name n name
7534     | name, (FBytes|FUInt64) ->
7535         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7536           name (String.length name) n name
7537     | name, FInt64 ->
7538         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7539           name (String.length name) n name
7540     | name, (FInt32|FUInt32) ->
7541         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7542           name (String.length name) n name
7543     | name, FChar ->
7544         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7545           name (String.length name) n name
7546     | name, FOptPercent ->
7547         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7548           name (String.length name) n name
7549   ) cols;
7550   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7551   pr "      }\n";
7552   pr "      guestfs_free_%s_list (%s);\n" typ n
7553
7554 and generate_perl_struct_code typ cols name style n do_cleanups =
7555   pr "PREINIT:\n";
7556   pr "      struct guestfs_%s *%s;\n" typ n;
7557   pr " PPCODE:\n";
7558   pr "      %s = guestfs_%s " n name;
7559   generate_c_call_args ~handle:"g" style;
7560   pr ";\n";
7561   do_cleanups ();
7562   pr "      if (%s == NULL)\n" n;
7563   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7564   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7565   List.iter (
7566     fun ((name, _) as col) ->
7567       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7568
7569       match col with
7570       | name, FString ->
7571           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7572             n name
7573       | name, FBuffer ->
7574           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7575             n name n name
7576       | name, FUUID ->
7577           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7578             n name
7579       | name, (FBytes|FUInt64) ->
7580           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7581             n name
7582       | name, FInt64 ->
7583           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7584             n name
7585       | name, (FInt32|FUInt32) ->
7586           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7587             n name
7588       | name, FChar ->
7589           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7590             n name
7591       | name, FOptPercent ->
7592           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7593             n name
7594   ) cols;
7595   pr "      free (%s);\n" n
7596
7597 (* Generate Sys/Guestfs.pm. *)
7598 and generate_perl_pm () =
7599   generate_header HashStyle LGPLv2;
7600
7601   pr "\
7602 =pod
7603
7604 =head1 NAME
7605
7606 Sys::Guestfs - Perl bindings for libguestfs
7607
7608 =head1 SYNOPSIS
7609
7610  use Sys::Guestfs;
7611
7612  my $h = Sys::Guestfs->new ();
7613  $h->add_drive ('guest.img');
7614  $h->launch ();
7615  $h->mount ('/dev/sda1', '/');
7616  $h->touch ('/hello');
7617  $h->sync ();
7618
7619 =head1 DESCRIPTION
7620
7621 The C<Sys::Guestfs> module provides a Perl XS binding to the
7622 libguestfs API for examining and modifying virtual machine
7623 disk images.
7624
7625 Amongst the things this is good for: making batch configuration
7626 changes to guests, getting disk used/free statistics (see also:
7627 virt-df), migrating between virtualization systems (see also:
7628 virt-p2v), performing partial backups, performing partial guest
7629 clones, cloning guests and changing registry/UUID/hostname info, and
7630 much else besides.
7631
7632 Libguestfs uses Linux kernel and qemu code, and can access any type of
7633 guest filesystem that Linux and qemu can, including but not limited
7634 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7635 schemes, qcow, qcow2, vmdk.
7636
7637 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7638 LVs, what filesystem is in each LV, etc.).  It can also run commands
7639 in the context of the guest.  Also you can access filesystems over FTP.
7640
7641 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7642 functions for using libguestfs from Perl, including integration
7643 with libvirt.
7644
7645 =head1 ERRORS
7646
7647 All errors turn into calls to C<croak> (see L<Carp(3)>).
7648
7649 =head1 METHODS
7650
7651 =over 4
7652
7653 =cut
7654
7655 package Sys::Guestfs;
7656
7657 use strict;
7658 use warnings;
7659
7660 require XSLoader;
7661 XSLoader::load ('Sys::Guestfs');
7662
7663 =item $h = Sys::Guestfs->new ();
7664
7665 Create a new guestfs handle.
7666
7667 =cut
7668
7669 sub new {
7670   my $proto = shift;
7671   my $class = ref ($proto) || $proto;
7672
7673   my $self = Sys::Guestfs::_create ();
7674   bless $self, $class;
7675   return $self;
7676 }
7677
7678 ";
7679
7680   (* Actions.  We only need to print documentation for these as
7681    * they are pulled in from the XS code automatically.
7682    *)
7683   List.iter (
7684     fun (name, style, _, flags, _, _, longdesc) ->
7685       if not (List.mem NotInDocs flags) then (
7686         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7687         pr "=item ";
7688         generate_perl_prototype name style;
7689         pr "\n\n";
7690         pr "%s\n\n" longdesc;
7691         if List.mem ProtocolLimitWarning flags then
7692           pr "%s\n\n" protocol_limit_warning;
7693         if List.mem DangerWillRobinson flags then
7694           pr "%s\n\n" danger_will_robinson;
7695         match deprecation_notice flags with
7696         | None -> ()
7697         | Some txt -> pr "%s\n\n" txt
7698       )
7699   ) all_functions_sorted;
7700
7701   (* End of file. *)
7702   pr "\
7703 =cut
7704
7705 1;
7706
7707 =back
7708
7709 =head1 COPYRIGHT
7710
7711 Copyright (C) 2009 Red Hat Inc.
7712
7713 =head1 LICENSE
7714
7715 Please see the file COPYING.LIB for the full license.
7716
7717 =head1 SEE ALSO
7718
7719 L<guestfs(3)>,
7720 L<guestfish(1)>,
7721 L<http://libguestfs.org>,
7722 L<Sys::Guestfs::Lib(3)>.
7723
7724 =cut
7725 "
7726
7727 and generate_perl_prototype name style =
7728   (match fst style with
7729    | RErr -> ()
7730    | RBool n
7731    | RInt n
7732    | RInt64 n
7733    | RConstString n
7734    | RConstOptString n
7735    | RString n
7736    | RBufferOut n -> pr "$%s = " n
7737    | RStruct (n,_)
7738    | RHashtable n -> pr "%%%s = " n
7739    | RStringList n
7740    | RStructList (n,_) -> pr "@%s = " n
7741   );
7742   pr "$h->%s (" name;
7743   let comma = ref false in
7744   List.iter (
7745     fun arg ->
7746       if !comma then pr ", ";
7747       comma := true;
7748       match arg with
7749       | Pathname n | Device n | Dev_or_Path n | String n
7750       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
7751           pr "$%s" n
7752       | StringList n | DeviceList n ->
7753           pr "\\@%s" n
7754   ) (snd style);
7755   pr ");"
7756
7757 (* Generate Python C module. *)
7758 and generate_python_c () =
7759   generate_header CStyle LGPLv2;
7760
7761   pr "\
7762 #include <Python.h>
7763
7764 #include <stdio.h>
7765 #include <stdlib.h>
7766 #include <assert.h>
7767
7768 #include \"guestfs.h\"
7769
7770 typedef struct {
7771   PyObject_HEAD
7772   guestfs_h *g;
7773 } Pyguestfs_Object;
7774
7775 static guestfs_h *
7776 get_handle (PyObject *obj)
7777 {
7778   assert (obj);
7779   assert (obj != Py_None);
7780   return ((Pyguestfs_Object *) obj)->g;
7781 }
7782
7783 static PyObject *
7784 put_handle (guestfs_h *g)
7785 {
7786   assert (g);
7787   return
7788     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7789 }
7790
7791 /* This list should be freed (but not the strings) after use. */
7792 static char **
7793 get_string_list (PyObject *obj)
7794 {
7795   int i, len;
7796   char **r;
7797
7798   assert (obj);
7799
7800   if (!PyList_Check (obj)) {
7801     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7802     return NULL;
7803   }
7804
7805   len = PyList_Size (obj);
7806   r = malloc (sizeof (char *) * (len+1));
7807   if (r == NULL) {
7808     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7809     return NULL;
7810   }
7811
7812   for (i = 0; i < len; ++i)
7813     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7814   r[len] = NULL;
7815
7816   return r;
7817 }
7818
7819 static PyObject *
7820 put_string_list (char * const * const argv)
7821 {
7822   PyObject *list;
7823   int argc, i;
7824
7825   for (argc = 0; argv[argc] != NULL; ++argc)
7826     ;
7827
7828   list = PyList_New (argc);
7829   for (i = 0; i < argc; ++i)
7830     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7831
7832   return list;
7833 }
7834
7835 static PyObject *
7836 put_table (char * const * const argv)
7837 {
7838   PyObject *list, *item;
7839   int argc, i;
7840
7841   for (argc = 0; argv[argc] != NULL; ++argc)
7842     ;
7843
7844   list = PyList_New (argc >> 1);
7845   for (i = 0; i < argc; i += 2) {
7846     item = PyTuple_New (2);
7847     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7848     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7849     PyList_SetItem (list, i >> 1, item);
7850   }
7851
7852   return list;
7853 }
7854
7855 static void
7856 free_strings (char **argv)
7857 {
7858   int argc;
7859
7860   for (argc = 0; argv[argc] != NULL; ++argc)
7861     free (argv[argc]);
7862   free (argv);
7863 }
7864
7865 static PyObject *
7866 py_guestfs_create (PyObject *self, PyObject *args)
7867 {
7868   guestfs_h *g;
7869
7870   g = guestfs_create ();
7871   if (g == NULL) {
7872     PyErr_SetString (PyExc_RuntimeError,
7873                      \"guestfs.create: failed to allocate handle\");
7874     return NULL;
7875   }
7876   guestfs_set_error_handler (g, NULL, NULL);
7877   return put_handle (g);
7878 }
7879
7880 static PyObject *
7881 py_guestfs_close (PyObject *self, PyObject *args)
7882 {
7883   PyObject *py_g;
7884   guestfs_h *g;
7885
7886   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7887     return NULL;
7888   g = get_handle (py_g);
7889
7890   guestfs_close (g);
7891
7892   Py_INCREF (Py_None);
7893   return Py_None;
7894 }
7895
7896 ";
7897
7898   let emit_put_list_function typ =
7899     pr "static PyObject *\n";
7900     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7901     pr "{\n";
7902     pr "  PyObject *list;\n";
7903     pr "  int i;\n";
7904     pr "\n";
7905     pr "  list = PyList_New (%ss->len);\n" typ;
7906     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7907     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7908     pr "  return list;\n";
7909     pr "};\n";
7910     pr "\n"
7911   in
7912
7913   (* Structures, turned into Python dictionaries. *)
7914   List.iter (
7915     fun (typ, cols) ->
7916       pr "static PyObject *\n";
7917       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7918       pr "{\n";
7919       pr "  PyObject *dict;\n";
7920       pr "\n";
7921       pr "  dict = PyDict_New ();\n";
7922       List.iter (
7923         function
7924         | name, FString ->
7925             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7926             pr "                        PyString_FromString (%s->%s));\n"
7927               typ name
7928         | name, FBuffer ->
7929             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7930             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7931               typ name typ name
7932         | name, FUUID ->
7933             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7934             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7935               typ name
7936         | name, (FBytes|FUInt64) ->
7937             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7938             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7939               typ name
7940         | name, FInt64 ->
7941             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7942             pr "                        PyLong_FromLongLong (%s->%s));\n"
7943               typ name
7944         | name, FUInt32 ->
7945             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7946             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7947               typ name
7948         | name, FInt32 ->
7949             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7950             pr "                        PyLong_FromLong (%s->%s));\n"
7951               typ name
7952         | name, FOptPercent ->
7953             pr "  if (%s->%s >= 0)\n" typ name;
7954             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7955             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7956               typ name;
7957             pr "  else {\n";
7958             pr "    Py_INCREF (Py_None);\n";
7959             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7960             pr "  }\n"
7961         | name, FChar ->
7962             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7963             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7964       ) cols;
7965       pr "  return dict;\n";
7966       pr "};\n";
7967       pr "\n";
7968
7969   ) structs;
7970
7971   (* Emit a put_TYPE_list function definition only if that function is used. *)
7972   List.iter (
7973     function
7974     | typ, (RStructListOnly | RStructAndList) ->
7975         (* generate the function for typ *)
7976         emit_put_list_function typ
7977     | typ, _ -> () (* empty *)
7978   ) (rstructs_used_by all_functions);
7979
7980   (* Python wrapper functions. *)
7981   List.iter (
7982     fun (name, style, _, _, _, _, _) ->
7983       pr "static PyObject *\n";
7984       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7985       pr "{\n";
7986
7987       pr "  PyObject *py_g;\n";
7988       pr "  guestfs_h *g;\n";
7989       pr "  PyObject *py_r;\n";
7990
7991       let error_code =
7992         match fst style with
7993         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7994         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7995         | RConstString _ | RConstOptString _ ->
7996             pr "  const char *r;\n"; "NULL"
7997         | RString _ -> pr "  char *r;\n"; "NULL"
7998         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7999         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8000         | RStructList (_, typ) ->
8001             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8002         | RBufferOut _ ->
8003             pr "  char *r;\n";
8004             pr "  size_t size;\n";
8005             "NULL" in
8006
8007       List.iter (
8008         function
8009         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8010             pr "  const char *%s;\n" n
8011         | OptString n -> pr "  const char *%s;\n" n
8012         | StringList n | DeviceList n ->
8013             pr "  PyObject *py_%s;\n" n;
8014             pr "  char **%s;\n" n
8015         | Bool n -> pr "  int %s;\n" n
8016         | Int n -> pr "  int %s;\n" n
8017         | Int64 n -> pr "  long long %s;\n" n
8018       ) (snd style);
8019
8020       pr "\n";
8021
8022       (* Convert the parameters. *)
8023       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8024       List.iter (
8025         function
8026         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8027         | OptString _ -> pr "z"
8028         | StringList _ | DeviceList _ -> pr "O"
8029         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8030         | Int _ -> pr "i"
8031         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8032                              * emulate C's int/long/long long in Python?
8033                              *)
8034       ) (snd style);
8035       pr ":guestfs_%s\",\n" name;
8036       pr "                         &py_g";
8037       List.iter (
8038         function
8039         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8040         | OptString n -> pr ", &%s" n
8041         | StringList n | DeviceList n -> pr ", &py_%s" n
8042         | Bool n -> pr ", &%s" n
8043         | Int n -> pr ", &%s" n
8044         | Int64 n -> pr ", &%s" n
8045       ) (snd style);
8046
8047       pr "))\n";
8048       pr "    return NULL;\n";
8049
8050       pr "  g = get_handle (py_g);\n";
8051       List.iter (
8052         function
8053         | Pathname _ | Device _ | Dev_or_Path _ | String _
8054         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8055         | StringList n | DeviceList n ->
8056             pr "  %s = get_string_list (py_%s);\n" n n;
8057             pr "  if (!%s) return NULL;\n" n
8058       ) (snd style);
8059
8060       pr "\n";
8061
8062       pr "  r = guestfs_%s " name;
8063       generate_c_call_args ~handle:"g" style;
8064       pr ";\n";
8065
8066       List.iter (
8067         function
8068         | Pathname _ | Device _ | Dev_or_Path _ | String _
8069         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8070         | StringList n | DeviceList n ->
8071             pr "  free (%s);\n" n
8072       ) (snd style);
8073
8074       pr "  if (r == %s) {\n" error_code;
8075       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8076       pr "    return NULL;\n";
8077       pr "  }\n";
8078       pr "\n";
8079
8080       (match fst style with
8081        | RErr ->
8082            pr "  Py_INCREF (Py_None);\n";
8083            pr "  py_r = Py_None;\n"
8084        | RInt _
8085        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8086        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8087        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8088        | RConstOptString _ ->
8089            pr "  if (r)\n";
8090            pr "    py_r = PyString_FromString (r);\n";
8091            pr "  else {\n";
8092            pr "    Py_INCREF (Py_None);\n";
8093            pr "    py_r = Py_None;\n";
8094            pr "  }\n"
8095        | RString _ ->
8096            pr "  py_r = PyString_FromString (r);\n";
8097            pr "  free (r);\n"
8098        | RStringList _ ->
8099            pr "  py_r = put_string_list (r);\n";
8100            pr "  free_strings (r);\n"
8101        | RStruct (_, typ) ->
8102            pr "  py_r = put_%s (r);\n" typ;
8103            pr "  guestfs_free_%s (r);\n" typ
8104        | RStructList (_, typ) ->
8105            pr "  py_r = put_%s_list (r);\n" typ;
8106            pr "  guestfs_free_%s_list (r);\n" typ
8107        | RHashtable n ->
8108            pr "  py_r = put_table (r);\n";
8109            pr "  free_strings (r);\n"
8110        | RBufferOut _ ->
8111            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8112            pr "  free (r);\n"
8113       );
8114
8115       pr "  return py_r;\n";
8116       pr "}\n";
8117       pr "\n"
8118   ) all_functions;
8119
8120   (* Table of functions. *)
8121   pr "static PyMethodDef methods[] = {\n";
8122   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8123   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8124   List.iter (
8125     fun (name, _, _, _, _, _, _) ->
8126       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8127         name name
8128   ) all_functions;
8129   pr "  { NULL, NULL, 0, NULL }\n";
8130   pr "};\n";
8131   pr "\n";
8132
8133   (* Init function. *)
8134   pr "\
8135 void
8136 initlibguestfsmod (void)
8137 {
8138   static int initialized = 0;
8139
8140   if (initialized) return;
8141   Py_InitModule ((char *) \"libguestfsmod\", methods);
8142   initialized = 1;
8143 }
8144 "
8145
8146 (* Generate Python module. *)
8147 and generate_python_py () =
8148   generate_header HashStyle LGPLv2;
8149
8150   pr "\
8151 u\"\"\"Python bindings for libguestfs
8152
8153 import guestfs
8154 g = guestfs.GuestFS ()
8155 g.add_drive (\"guest.img\")
8156 g.launch ()
8157 parts = g.list_partitions ()
8158
8159 The guestfs module provides a Python binding to the libguestfs API
8160 for examining and modifying virtual machine disk images.
8161
8162 Amongst the things this is good for: making batch configuration
8163 changes to guests, getting disk used/free statistics (see also:
8164 virt-df), migrating between virtualization systems (see also:
8165 virt-p2v), performing partial backups, performing partial guest
8166 clones, cloning guests and changing registry/UUID/hostname info, and
8167 much else besides.
8168
8169 Libguestfs uses Linux kernel and qemu code, and can access any type of
8170 guest filesystem that Linux and qemu can, including but not limited
8171 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8172 schemes, qcow, qcow2, vmdk.
8173
8174 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8175 LVs, what filesystem is in each LV, etc.).  It can also run commands
8176 in the context of the guest.  Also you can access filesystems over FTP.
8177
8178 Errors which happen while using the API are turned into Python
8179 RuntimeError exceptions.
8180
8181 To create a guestfs handle you usually have to perform the following
8182 sequence of calls:
8183
8184 # Create the handle, call add_drive at least once, and possibly
8185 # several times if the guest has multiple block devices:
8186 g = guestfs.GuestFS ()
8187 g.add_drive (\"guest.img\")
8188
8189 # Launch the qemu subprocess and wait for it to become ready:
8190 g.launch ()
8191
8192 # Now you can issue commands, for example:
8193 logvols = g.lvs ()
8194
8195 \"\"\"
8196
8197 import libguestfsmod
8198
8199 class GuestFS:
8200     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8201
8202     def __init__ (self):
8203         \"\"\"Create a new libguestfs handle.\"\"\"
8204         self._o = libguestfsmod.create ()
8205
8206     def __del__ (self):
8207         libguestfsmod.close (self._o)
8208
8209 ";
8210
8211   List.iter (
8212     fun (name, style, _, flags, _, _, longdesc) ->
8213       pr "    def %s " name;
8214       generate_py_call_args ~handle:"self" (snd style);
8215       pr ":\n";
8216
8217       if not (List.mem NotInDocs flags) then (
8218         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8219         let doc =
8220           match fst style with
8221           | RErr | RInt _ | RInt64 _ | RBool _
8222           | RConstOptString _ | RConstString _
8223           | RString _ | RBufferOut _ -> doc
8224           | RStringList _ ->
8225               doc ^ "\n\nThis function returns a list of strings."
8226           | RStruct (_, typ) ->
8227               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8228           | RStructList (_, typ) ->
8229               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8230           | RHashtable _ ->
8231               doc ^ "\n\nThis function returns a dictionary." in
8232         let doc =
8233           if List.mem ProtocolLimitWarning flags then
8234             doc ^ "\n\n" ^ protocol_limit_warning
8235           else doc in
8236         let doc =
8237           if List.mem DangerWillRobinson flags then
8238             doc ^ "\n\n" ^ danger_will_robinson
8239           else doc in
8240         let doc =
8241           match deprecation_notice flags with
8242           | None -> doc
8243           | Some txt -> doc ^ "\n\n" ^ txt in
8244         let doc = pod2text ~width:60 name doc in
8245         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8246         let doc = String.concat "\n        " doc in
8247         pr "        u\"\"\"%s\"\"\"\n" doc;
8248       );
8249       pr "        return libguestfsmod.%s " name;
8250       generate_py_call_args ~handle:"self._o" (snd style);
8251       pr "\n";
8252       pr "\n";
8253   ) all_functions
8254
8255 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8256 and generate_py_call_args ~handle args =
8257   pr "(%s" handle;
8258   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8259   pr ")"
8260
8261 (* Useful if you need the longdesc POD text as plain text.  Returns a
8262  * list of lines.
8263  *
8264  * Because this is very slow (the slowest part of autogeneration),
8265  * we memoize the results.
8266  *)
8267 and pod2text ~width name longdesc =
8268   let key = width, name, longdesc in
8269   try Hashtbl.find pod2text_memo key
8270   with Not_found ->
8271     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8272     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8273     close_out chan;
8274     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8275     let chan = Unix.open_process_in cmd in
8276     let lines = ref [] in
8277     let rec loop i =
8278       let line = input_line chan in
8279       if i = 1 then             (* discard the first line of output *)
8280         loop (i+1)
8281       else (
8282         let line = triml line in
8283         lines := line :: !lines;
8284         loop (i+1)
8285       ) in
8286     let lines = try loop 1 with End_of_file -> List.rev !lines in
8287     Unix.unlink filename;
8288     (match Unix.close_process_in chan with
8289      | Unix.WEXITED 0 -> ()
8290      | Unix.WEXITED i ->
8291          failwithf "pod2text: process exited with non-zero status (%d)" i
8292      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8293          failwithf "pod2text: process signalled or stopped by signal %d" i
8294     );
8295     Hashtbl.add pod2text_memo key lines;
8296     pod2text_memo_updated ();
8297     lines
8298
8299 (* Generate ruby bindings. *)
8300 and generate_ruby_c () =
8301   generate_header CStyle LGPLv2;
8302
8303   pr "\
8304 #include <stdio.h>
8305 #include <stdlib.h>
8306
8307 #include <ruby.h>
8308
8309 #include \"guestfs.h\"
8310
8311 #include \"extconf.h\"
8312
8313 /* For Ruby < 1.9 */
8314 #ifndef RARRAY_LEN
8315 #define RARRAY_LEN(r) (RARRAY((r))->len)
8316 #endif
8317
8318 static VALUE m_guestfs;                 /* guestfs module */
8319 static VALUE c_guestfs;                 /* guestfs_h handle */
8320 static VALUE e_Error;                   /* used for all errors */
8321
8322 static void ruby_guestfs_free (void *p)
8323 {
8324   if (!p) return;
8325   guestfs_close ((guestfs_h *) p);
8326 }
8327
8328 static VALUE ruby_guestfs_create (VALUE m)
8329 {
8330   guestfs_h *g;
8331
8332   g = guestfs_create ();
8333   if (!g)
8334     rb_raise (e_Error, \"failed to create guestfs handle\");
8335
8336   /* Don't print error messages to stderr by default. */
8337   guestfs_set_error_handler (g, NULL, NULL);
8338
8339   /* Wrap it, and make sure the close function is called when the
8340    * handle goes away.
8341    */
8342   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8343 }
8344
8345 static VALUE ruby_guestfs_close (VALUE gv)
8346 {
8347   guestfs_h *g;
8348   Data_Get_Struct (gv, guestfs_h, g);
8349
8350   ruby_guestfs_free (g);
8351   DATA_PTR (gv) = NULL;
8352
8353   return Qnil;
8354 }
8355
8356 ";
8357
8358   List.iter (
8359     fun (name, style, _, _, _, _, _) ->
8360       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8361       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8362       pr ")\n";
8363       pr "{\n";
8364       pr "  guestfs_h *g;\n";
8365       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8366       pr "  if (!g)\n";
8367       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8368         name;
8369       pr "\n";
8370
8371       List.iter (
8372         function
8373         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8374             pr "  Check_Type (%sv, T_STRING);\n" n;
8375             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8376             pr "  if (!%s)\n" n;
8377             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8378             pr "              \"%s\", \"%s\");\n" n name
8379         | OptString n ->
8380             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8381         | StringList n | DeviceList n ->
8382             pr "  char **%s;\n" n;
8383             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8384             pr "  {\n";
8385             pr "    int i, len;\n";
8386             pr "    len = RARRAY_LEN (%sv);\n" n;
8387             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8388               n;
8389             pr "    for (i = 0; i < len; ++i) {\n";
8390             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8391             pr "      %s[i] = StringValueCStr (v);\n" n;
8392             pr "    }\n";
8393             pr "    %s[len] = NULL;\n" n;
8394             pr "  }\n";
8395         | Bool n ->
8396             pr "  int %s = RTEST (%sv);\n" n n
8397         | Int n ->
8398             pr "  int %s = NUM2INT (%sv);\n" n n
8399         | Int64 n ->
8400             pr "  long long %s = NUM2LL (%sv);\n" n n
8401       ) (snd style);
8402       pr "\n";
8403
8404       let error_code =
8405         match fst style with
8406         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8407         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8408         | RConstString _ | RConstOptString _ ->
8409             pr "  const char *r;\n"; "NULL"
8410         | RString _ -> pr "  char *r;\n"; "NULL"
8411         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8412         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8413         | RStructList (_, typ) ->
8414             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8415         | RBufferOut _ ->
8416             pr "  char *r;\n";
8417             pr "  size_t size;\n";
8418             "NULL" in
8419       pr "\n";
8420
8421       pr "  r = guestfs_%s " name;
8422       generate_c_call_args ~handle:"g" style;
8423       pr ";\n";
8424
8425       List.iter (
8426         function
8427         | Pathname _ | Device _ | Dev_or_Path _ | String _
8428         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8429         | StringList n | DeviceList n ->
8430             pr "  free (%s);\n" n
8431       ) (snd style);
8432
8433       pr "  if (r == %s)\n" error_code;
8434       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8435       pr "\n";
8436
8437       (match fst style with
8438        | RErr ->
8439            pr "  return Qnil;\n"
8440        | RInt _ | RBool _ ->
8441            pr "  return INT2NUM (r);\n"
8442        | RInt64 _ ->
8443            pr "  return ULL2NUM (r);\n"
8444        | RConstString _ ->
8445            pr "  return rb_str_new2 (r);\n";
8446        | RConstOptString _ ->
8447            pr "  if (r)\n";
8448            pr "    return rb_str_new2 (r);\n";
8449            pr "  else\n";
8450            pr "    return Qnil;\n";
8451        | RString _ ->
8452            pr "  VALUE rv = rb_str_new2 (r);\n";
8453            pr "  free (r);\n";
8454            pr "  return rv;\n";
8455        | RStringList _ ->
8456            pr "  int i, len = 0;\n";
8457            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8458            pr "  VALUE rv = rb_ary_new2 (len);\n";
8459            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8460            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8461            pr "    free (r[i]);\n";
8462            pr "  }\n";
8463            pr "  free (r);\n";
8464            pr "  return rv;\n"
8465        | RStruct (_, typ) ->
8466            let cols = cols_of_struct typ in
8467            generate_ruby_struct_code typ cols
8468        | RStructList (_, typ) ->
8469            let cols = cols_of_struct typ in
8470            generate_ruby_struct_list_code typ cols
8471        | RHashtable _ ->
8472            pr "  VALUE rv = rb_hash_new ();\n";
8473            pr "  int i;\n";
8474            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8475            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8476            pr "    free (r[i]);\n";
8477            pr "    free (r[i+1]);\n";
8478            pr "  }\n";
8479            pr "  free (r);\n";
8480            pr "  return rv;\n"
8481        | RBufferOut _ ->
8482            pr "  VALUE rv = rb_str_new (r, size);\n";
8483            pr "  free (r);\n";
8484            pr "  return rv;\n";
8485       );
8486
8487       pr "}\n";
8488       pr "\n"
8489   ) all_functions;
8490
8491   pr "\
8492 /* Initialize the module. */
8493 void Init__guestfs ()
8494 {
8495   m_guestfs = rb_define_module (\"Guestfs\");
8496   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8497   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8498
8499   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8500   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8501
8502 ";
8503   (* Define the rest of the methods. *)
8504   List.iter (
8505     fun (name, style, _, _, _, _, _) ->
8506       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8507       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8508   ) all_functions;
8509
8510   pr "}\n"
8511
8512 (* Ruby code to return a struct. *)
8513 and generate_ruby_struct_code typ cols =
8514   pr "  VALUE rv = rb_hash_new ();\n";
8515   List.iter (
8516     function
8517     | name, FString ->
8518         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8519     | name, FBuffer ->
8520         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8521     | name, FUUID ->
8522         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8523     | name, (FBytes|FUInt64) ->
8524         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8525     | name, FInt64 ->
8526         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8527     | name, FUInt32 ->
8528         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8529     | name, FInt32 ->
8530         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8531     | name, FOptPercent ->
8532         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8533     | name, FChar -> (* XXX wrong? *)
8534         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8535   ) cols;
8536   pr "  guestfs_free_%s (r);\n" typ;
8537   pr "  return rv;\n"
8538
8539 (* Ruby code to return a struct list. *)
8540 and generate_ruby_struct_list_code typ cols =
8541   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8542   pr "  int i;\n";
8543   pr "  for (i = 0; i < r->len; ++i) {\n";
8544   pr "    VALUE hv = rb_hash_new ();\n";
8545   List.iter (
8546     function
8547     | name, FString ->
8548         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8549     | name, FBuffer ->
8550         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
8551     | name, FUUID ->
8552         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8553     | name, (FBytes|FUInt64) ->
8554         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8555     | name, FInt64 ->
8556         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8557     | name, FUInt32 ->
8558         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8559     | name, FInt32 ->
8560         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8561     | name, FOptPercent ->
8562         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8563     | name, FChar -> (* XXX wrong? *)
8564         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8565   ) cols;
8566   pr "    rb_ary_push (rv, hv);\n";
8567   pr "  }\n";
8568   pr "  guestfs_free_%s_list (r);\n" typ;
8569   pr "  return rv;\n"
8570
8571 (* Generate Java bindings GuestFS.java file. *)
8572 and generate_java_java () =
8573   generate_header CStyle LGPLv2;
8574
8575   pr "\
8576 package com.redhat.et.libguestfs;
8577
8578 import java.util.HashMap;
8579 import com.redhat.et.libguestfs.LibGuestFSException;
8580 import com.redhat.et.libguestfs.PV;
8581 import com.redhat.et.libguestfs.VG;
8582 import com.redhat.et.libguestfs.LV;
8583 import com.redhat.et.libguestfs.Stat;
8584 import com.redhat.et.libguestfs.StatVFS;
8585 import com.redhat.et.libguestfs.IntBool;
8586 import com.redhat.et.libguestfs.Dirent;
8587
8588 /**
8589  * The GuestFS object is a libguestfs handle.
8590  *
8591  * @author rjones
8592  */
8593 public class GuestFS {
8594   // Load the native code.
8595   static {
8596     System.loadLibrary (\"guestfs_jni\");
8597   }
8598
8599   /**
8600    * The native guestfs_h pointer.
8601    */
8602   long g;
8603
8604   /**
8605    * Create a libguestfs handle.
8606    *
8607    * @throws LibGuestFSException
8608    */
8609   public GuestFS () throws LibGuestFSException
8610   {
8611     g = _create ();
8612   }
8613   private native long _create () throws LibGuestFSException;
8614
8615   /**
8616    * Close a libguestfs handle.
8617    *
8618    * You can also leave handles to be collected by the garbage
8619    * collector, but this method ensures that the resources used
8620    * by the handle are freed up immediately.  If you call any
8621    * other methods after closing the handle, you will get an
8622    * exception.
8623    *
8624    * @throws LibGuestFSException
8625    */
8626   public void close () throws LibGuestFSException
8627   {
8628     if (g != 0)
8629       _close (g);
8630     g = 0;
8631   }
8632   private native void _close (long g) throws LibGuestFSException;
8633
8634   public void finalize () throws LibGuestFSException
8635   {
8636     close ();
8637   }
8638
8639 ";
8640
8641   List.iter (
8642     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8643       if not (List.mem NotInDocs flags); then (
8644         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8645         let doc =
8646           if List.mem ProtocolLimitWarning flags then
8647             doc ^ "\n\n" ^ protocol_limit_warning
8648           else doc in
8649         let doc =
8650           if List.mem DangerWillRobinson flags then
8651             doc ^ "\n\n" ^ danger_will_robinson
8652           else doc in
8653         let doc =
8654           match deprecation_notice flags with
8655           | None -> doc
8656           | Some txt -> doc ^ "\n\n" ^ txt in
8657         let doc = pod2text ~width:60 name doc in
8658         let doc = List.map (            (* RHBZ#501883 *)
8659           function
8660           | "" -> "<p>"
8661           | nonempty -> nonempty
8662         ) doc in
8663         let doc = String.concat "\n   * " doc in
8664
8665         pr "  /**\n";
8666         pr "   * %s\n" shortdesc;
8667         pr "   * <p>\n";
8668         pr "   * %s\n" doc;
8669         pr "   * @throws LibGuestFSException\n";
8670         pr "   */\n";
8671         pr "  ";
8672       );
8673       generate_java_prototype ~public:true ~semicolon:false name style;
8674       pr "\n";
8675       pr "  {\n";
8676       pr "    if (g == 0)\n";
8677       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8678         name;
8679       pr "    ";
8680       if fst style <> RErr then pr "return ";
8681       pr "_%s " name;
8682       generate_java_call_args ~handle:"g" (snd style);
8683       pr ";\n";
8684       pr "  }\n";
8685       pr "  ";
8686       generate_java_prototype ~privat:true ~native:true name style;
8687       pr "\n";
8688       pr "\n";
8689   ) all_functions;
8690
8691   pr "}\n"
8692
8693 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8694 and generate_java_call_args ~handle args =
8695   pr "(%s" handle;
8696   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8697   pr ")"
8698
8699 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8700     ?(semicolon=true) name style =
8701   if privat then pr "private ";
8702   if public then pr "public ";
8703   if native then pr "native ";
8704
8705   (* return type *)
8706   (match fst style with
8707    | RErr -> pr "void ";
8708    | RInt _ -> pr "int ";
8709    | RInt64 _ -> pr "long ";
8710    | RBool _ -> pr "boolean ";
8711    | RConstString _ | RConstOptString _ | RString _
8712    | RBufferOut _ -> pr "String ";
8713    | RStringList _ -> pr "String[] ";
8714    | RStruct (_, typ) ->
8715        let name = java_name_of_struct typ in
8716        pr "%s " name;
8717    | RStructList (_, typ) ->
8718        let name = java_name_of_struct typ in
8719        pr "%s[] " name;
8720    | RHashtable _ -> pr "HashMap<String,String> ";
8721   );
8722
8723   if native then pr "_%s " name else pr "%s " name;
8724   pr "(";
8725   let needs_comma = ref false in
8726   if native then (
8727     pr "long g";
8728     needs_comma := true
8729   );
8730
8731   (* args *)
8732   List.iter (
8733     fun arg ->
8734       if !needs_comma then pr ", ";
8735       needs_comma := true;
8736
8737       match arg with
8738       | Pathname n
8739       | Device n | Dev_or_Path n
8740       | String n
8741       | OptString n
8742       | FileIn n
8743       | FileOut n ->
8744           pr "String %s" n
8745       | StringList n | DeviceList n ->
8746           pr "String[] %s" n
8747       | Bool n ->
8748           pr "boolean %s" n
8749       | Int n ->
8750           pr "int %s" n
8751       | Int64 n ->
8752           pr "long %s" n
8753   ) (snd style);
8754
8755   pr ")\n";
8756   pr "    throws LibGuestFSException";
8757   if semicolon then pr ";"
8758
8759 and generate_java_struct jtyp cols =
8760   generate_header CStyle LGPLv2;
8761
8762   pr "\
8763 package com.redhat.et.libguestfs;
8764
8765 /**
8766  * Libguestfs %s structure.
8767  *
8768  * @author rjones
8769  * @see GuestFS
8770  */
8771 public class %s {
8772 " jtyp jtyp;
8773
8774   List.iter (
8775     function
8776     | name, FString
8777     | name, FUUID
8778     | name, FBuffer -> pr "  public String %s;\n" name
8779     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8780     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8781     | name, FChar -> pr "  public char %s;\n" name
8782     | name, FOptPercent ->
8783         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8784         pr "  public float %s;\n" name
8785   ) cols;
8786
8787   pr "}\n"
8788
8789 and generate_java_c () =
8790   generate_header CStyle LGPLv2;
8791
8792   pr "\
8793 #include <stdio.h>
8794 #include <stdlib.h>
8795 #include <string.h>
8796
8797 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8798 #include \"guestfs.h\"
8799
8800 /* Note that this function returns.  The exception is not thrown
8801  * until after the wrapper function returns.
8802  */
8803 static void
8804 throw_exception (JNIEnv *env, const char *msg)
8805 {
8806   jclass cl;
8807   cl = (*env)->FindClass (env,
8808                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8809   (*env)->ThrowNew (env, cl, msg);
8810 }
8811
8812 JNIEXPORT jlong JNICALL
8813 Java_com_redhat_et_libguestfs_GuestFS__1create
8814   (JNIEnv *env, jobject obj)
8815 {
8816   guestfs_h *g;
8817
8818   g = guestfs_create ();
8819   if (g == NULL) {
8820     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8821     return 0;
8822   }
8823   guestfs_set_error_handler (g, NULL, NULL);
8824   return (jlong) (long) g;
8825 }
8826
8827 JNIEXPORT void JNICALL
8828 Java_com_redhat_et_libguestfs_GuestFS__1close
8829   (JNIEnv *env, jobject obj, jlong jg)
8830 {
8831   guestfs_h *g = (guestfs_h *) (long) jg;
8832   guestfs_close (g);
8833 }
8834
8835 ";
8836
8837   List.iter (
8838     fun (name, style, _, _, _, _, _) ->
8839       pr "JNIEXPORT ";
8840       (match fst style with
8841        | RErr -> pr "void ";
8842        | RInt _ -> pr "jint ";
8843        | RInt64 _ -> pr "jlong ";
8844        | RBool _ -> pr "jboolean ";
8845        | RConstString _ | RConstOptString _ | RString _
8846        | RBufferOut _ -> pr "jstring ";
8847        | RStruct _ | RHashtable _ ->
8848            pr "jobject ";
8849        | RStringList _ | RStructList _ ->
8850            pr "jobjectArray ";
8851       );
8852       pr "JNICALL\n";
8853       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8854       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8855       pr "\n";
8856       pr "  (JNIEnv *env, jobject obj, jlong jg";
8857       List.iter (
8858         function
8859         | Pathname n
8860         | Device n | Dev_or_Path n
8861         | String n
8862         | OptString n
8863         | FileIn n
8864         | FileOut n ->
8865             pr ", jstring j%s" n
8866         | StringList n | DeviceList n ->
8867             pr ", jobjectArray j%s" n
8868         | Bool n ->
8869             pr ", jboolean j%s" n
8870         | Int n ->
8871             pr ", jint j%s" n
8872         | Int64 n ->
8873             pr ", jlong j%s" n
8874       ) (snd style);
8875       pr ")\n";
8876       pr "{\n";
8877       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8878       let error_code, no_ret =
8879         match fst style with
8880         | RErr -> pr "  int r;\n"; "-1", ""
8881         | RBool _
8882         | RInt _ -> pr "  int r;\n"; "-1", "0"
8883         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8884         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8885         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8886         | RString _ ->
8887             pr "  jstring jr;\n";
8888             pr "  char *r;\n"; "NULL", "NULL"
8889         | RStringList _ ->
8890             pr "  jobjectArray jr;\n";
8891             pr "  int r_len;\n";
8892             pr "  jclass cl;\n";
8893             pr "  jstring jstr;\n";
8894             pr "  char **r;\n"; "NULL", "NULL"
8895         | RStruct (_, typ) ->
8896             pr "  jobject jr;\n";
8897             pr "  jclass cl;\n";
8898             pr "  jfieldID fl;\n";
8899             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8900         | RStructList (_, typ) ->
8901             pr "  jobjectArray jr;\n";
8902             pr "  jclass cl;\n";
8903             pr "  jfieldID fl;\n";
8904             pr "  jobject jfl;\n";
8905             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8906         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8907         | RBufferOut _ ->
8908             pr "  jstring jr;\n";
8909             pr "  char *r;\n";
8910             pr "  size_t size;\n";
8911             "NULL", "NULL" in
8912       List.iter (
8913         function
8914         | Pathname n
8915         | Device n | Dev_or_Path n
8916         | String n
8917         | OptString n
8918         | FileIn n
8919         | FileOut n ->
8920             pr "  const char *%s;\n" n
8921         | StringList n | DeviceList n ->
8922             pr "  int %s_len;\n" n;
8923             pr "  const char **%s;\n" n
8924         | Bool n
8925         | Int n ->
8926             pr "  int %s;\n" n
8927         | Int64 n ->
8928             pr "  int64_t %s;\n" n
8929       ) (snd style);
8930
8931       let needs_i =
8932         (match fst style with
8933          | RStringList _ | RStructList _ -> true
8934          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8935          | RConstOptString _
8936          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8937           List.exists (function
8938                        | StringList _ -> true
8939                        | DeviceList _ -> true
8940                        | _ -> false) (snd style) in
8941       if needs_i then
8942         pr "  int i;\n";
8943
8944       pr "\n";
8945
8946       (* Get the parameters. *)
8947       List.iter (
8948         function
8949         | Pathname n
8950         | Device n | Dev_or_Path n
8951         | String n
8952         | FileIn n
8953         | FileOut n ->
8954             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8955         | OptString n ->
8956             (* This is completely undocumented, but Java null becomes
8957              * a NULL parameter.
8958              *)
8959             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8960         | StringList n | DeviceList n ->
8961             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8962             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8963             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8964             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8965               n;
8966             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8967             pr "  }\n";
8968             pr "  %s[%s_len] = NULL;\n" n n;
8969         | Bool n
8970         | Int n
8971         | Int64 n ->
8972             pr "  %s = j%s;\n" n n
8973       ) (snd style);
8974
8975       (* Make the call. *)
8976       pr "  r = guestfs_%s " name;
8977       generate_c_call_args ~handle:"g" style;
8978       pr ";\n";
8979
8980       (* Release the parameters. *)
8981       List.iter (
8982         function
8983         | Pathname n
8984         | Device n | Dev_or_Path n
8985         | String n
8986         | FileIn n
8987         | FileOut n ->
8988             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8989         | OptString n ->
8990             pr "  if (j%s)\n" n;
8991             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8992         | StringList n | DeviceList n ->
8993             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8994             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8995               n;
8996             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8997             pr "  }\n";
8998             pr "  free (%s);\n" n
8999         | Bool n
9000         | Int n
9001         | Int64 n -> ()
9002       ) (snd style);
9003
9004       (* Check for errors. *)
9005       pr "  if (r == %s) {\n" error_code;
9006       pr "    throw_exception (env, guestfs_last_error (g));\n";
9007       pr "    return %s;\n" no_ret;
9008       pr "  }\n";
9009
9010       (* Return value. *)
9011       (match fst style with
9012        | RErr -> ()
9013        | RInt _ -> pr "  return (jint) r;\n"
9014        | RBool _ -> pr "  return (jboolean) r;\n"
9015        | RInt64 _ -> pr "  return (jlong) r;\n"
9016        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9017        | RConstOptString _ ->
9018            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9019        | RString _ ->
9020            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9021            pr "  free (r);\n";
9022            pr "  return jr;\n"
9023        | RStringList _ ->
9024            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9025            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9026            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9027            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9028            pr "  for (i = 0; i < r_len; ++i) {\n";
9029            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9030            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9031            pr "    free (r[i]);\n";
9032            pr "  }\n";
9033            pr "  free (r);\n";
9034            pr "  return jr;\n"
9035        | RStruct (_, typ) ->
9036            let jtyp = java_name_of_struct typ in
9037            let cols = cols_of_struct typ in
9038            generate_java_struct_return typ jtyp cols
9039        | RStructList (_, typ) ->
9040            let jtyp = java_name_of_struct typ in
9041            let cols = cols_of_struct typ in
9042            generate_java_struct_list_return typ jtyp cols
9043        | RHashtable _ ->
9044            (* XXX *)
9045            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9046            pr "  return NULL;\n"
9047        | RBufferOut _ ->
9048            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9049            pr "  free (r);\n";
9050            pr "  return jr;\n"
9051       );
9052
9053       pr "}\n";
9054       pr "\n"
9055   ) all_functions
9056
9057 and generate_java_struct_return typ jtyp cols =
9058   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9059   pr "  jr = (*env)->AllocObject (env, cl);\n";
9060   List.iter (
9061     function
9062     | name, FString ->
9063         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9064         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9065     | name, FUUID ->
9066         pr "  {\n";
9067         pr "    char s[33];\n";
9068         pr "    memcpy (s, r->%s, 32);\n" name;
9069         pr "    s[32] = 0;\n";
9070         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9071         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9072         pr "  }\n";
9073     | name, FBuffer ->
9074         pr "  {\n";
9075         pr "    int len = r->%s_len;\n" name;
9076         pr "    char s[len+1];\n";
9077         pr "    memcpy (s, r->%s, len);\n" name;
9078         pr "    s[len] = 0;\n";
9079         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9080         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9081         pr "  }\n";
9082     | name, (FBytes|FUInt64|FInt64) ->
9083         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9084         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9085     | name, (FUInt32|FInt32) ->
9086         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9087         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9088     | name, FOptPercent ->
9089         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9090         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9091     | name, FChar ->
9092         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9093         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9094   ) cols;
9095   pr "  free (r);\n";
9096   pr "  return jr;\n"
9097
9098 and generate_java_struct_list_return typ jtyp cols =
9099   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9100   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9101   pr "  for (i = 0; i < r->len; ++i) {\n";
9102   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9103   List.iter (
9104     function
9105     | name, FString ->
9106         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9107         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9108     | name, FUUID ->
9109         pr "    {\n";
9110         pr "      char s[33];\n";
9111         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9112         pr "      s[32] = 0;\n";
9113         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9114         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9115         pr "    }\n";
9116     | name, FBuffer ->
9117         pr "    {\n";
9118         pr "      int len = r->val[i].%s_len;\n" name;
9119         pr "      char s[len+1];\n";
9120         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9121         pr "      s[len] = 0;\n";
9122         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9123         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9124         pr "    }\n";
9125     | name, (FBytes|FUInt64|FInt64) ->
9126         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9127         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9128     | name, (FUInt32|FInt32) ->
9129         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9130         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9131     | name, FOptPercent ->
9132         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9133         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9134     | name, FChar ->
9135         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9136         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9137   ) cols;
9138   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9139   pr "  }\n";
9140   pr "  guestfs_free_%s_list (r);\n" typ;
9141   pr "  return jr;\n"
9142
9143 and generate_java_makefile_inc () =
9144   generate_header HashStyle GPLv2;
9145
9146   pr "java_built_sources = \\\n";
9147   List.iter (
9148     fun (typ, jtyp) ->
9149         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9150   ) java_structs;
9151   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9152
9153 and generate_haskell_hs () =
9154   generate_header HaskellStyle LGPLv2;
9155
9156   (* XXX We only know how to generate partial FFI for Haskell
9157    * at the moment.  Please help out!
9158    *)
9159   let can_generate style =
9160     match style with
9161     | RErr, _
9162     | RInt _, _
9163     | RInt64 _, _ -> true
9164     | RBool _, _
9165     | RConstString _, _
9166     | RConstOptString _, _
9167     | RString _, _
9168     | RStringList _, _
9169     | RStruct _, _
9170     | RStructList _, _
9171     | RHashtable _, _
9172     | RBufferOut _, _ -> false in
9173
9174   pr "\
9175 {-# INCLUDE <guestfs.h> #-}
9176 {-# LANGUAGE ForeignFunctionInterface #-}
9177
9178 module Guestfs (
9179   create";
9180
9181   (* List out the names of the actions we want to export. *)
9182   List.iter (
9183     fun (name, style, _, _, _, _, _) ->
9184       if can_generate style then pr ",\n  %s" name
9185   ) all_functions;
9186
9187   pr "
9188   ) where
9189 import Foreign
9190 import Foreign.C
9191 import Foreign.C.Types
9192 import IO
9193 import Control.Exception
9194 import Data.Typeable
9195
9196 data GuestfsS = GuestfsS            -- represents the opaque C struct
9197 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9198 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9199
9200 -- XXX define properly later XXX
9201 data PV = PV
9202 data VG = VG
9203 data LV = LV
9204 data IntBool = IntBool
9205 data Stat = Stat
9206 data StatVFS = StatVFS
9207 data Hashtable = Hashtable
9208
9209 foreign import ccall unsafe \"guestfs_create\" c_create
9210   :: IO GuestfsP
9211 foreign import ccall unsafe \"&guestfs_close\" c_close
9212   :: FunPtr (GuestfsP -> IO ())
9213 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9214   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9215
9216 create :: IO GuestfsH
9217 create = do
9218   p <- c_create
9219   c_set_error_handler p nullPtr nullPtr
9220   h <- newForeignPtr c_close p
9221   return h
9222
9223 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9224   :: GuestfsP -> IO CString
9225
9226 -- last_error :: GuestfsH -> IO (Maybe String)
9227 -- last_error h = do
9228 --   str <- withForeignPtr h (\\p -> c_last_error p)
9229 --   maybePeek peekCString str
9230
9231 last_error :: GuestfsH -> IO (String)
9232 last_error h = do
9233   str <- withForeignPtr h (\\p -> c_last_error p)
9234   if (str == nullPtr)
9235     then return \"no error\"
9236     else peekCString str
9237
9238 ";
9239
9240   (* Generate wrappers for each foreign function. *)
9241   List.iter (
9242     fun (name, style, _, _, _, _, _) ->
9243       if can_generate style then (
9244         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9245         pr "  :: ";
9246         generate_haskell_prototype ~handle:"GuestfsP" style;
9247         pr "\n";
9248         pr "\n";
9249         pr "%s :: " name;
9250         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9251         pr "\n";
9252         pr "%s %s = do\n" name
9253           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9254         pr "  r <- ";
9255         (* Convert pointer arguments using with* functions. *)
9256         List.iter (
9257           function
9258           | FileIn n
9259           | FileOut n
9260           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9261           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9262           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9263           | Bool _ | Int _ | Int64 _ -> ()
9264         ) (snd style);
9265         (* Convert integer arguments. *)
9266         let args =
9267           List.map (
9268             function
9269             | Bool n -> sprintf "(fromBool %s)" n
9270             | Int n -> sprintf "(fromIntegral %s)" n
9271             | Int64 n -> sprintf "(fromIntegral %s)" n
9272             | FileIn n | FileOut n
9273             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9274           ) (snd style) in
9275         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9276           (String.concat " " ("p" :: args));
9277         (match fst style with
9278          | RErr | RInt _ | RInt64 _ | RBool _ ->
9279              pr "  if (r == -1)\n";
9280              pr "    then do\n";
9281              pr "      err <- last_error h\n";
9282              pr "      fail err\n";
9283          | RConstString _ | RConstOptString _ | RString _
9284          | RStringList _ | RStruct _
9285          | RStructList _ | RHashtable _ | RBufferOut _ ->
9286              pr "  if (r == nullPtr)\n";
9287              pr "    then do\n";
9288              pr "      err <- last_error h\n";
9289              pr "      fail err\n";
9290         );
9291         (match fst style with
9292          | RErr ->
9293              pr "    else return ()\n"
9294          | RInt _ ->
9295              pr "    else return (fromIntegral r)\n"
9296          | RInt64 _ ->
9297              pr "    else return (fromIntegral r)\n"
9298          | RBool _ ->
9299              pr "    else return (toBool r)\n"
9300          | RConstString _
9301          | RConstOptString _
9302          | RString _
9303          | RStringList _
9304          | RStruct _
9305          | RStructList _
9306          | RHashtable _
9307          | RBufferOut _ ->
9308              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9309         );
9310         pr "\n";
9311       )
9312   ) all_functions
9313
9314 and generate_haskell_prototype ~handle ?(hs = false) style =
9315   pr "%s -> " handle;
9316   let string = if hs then "String" else "CString" in
9317   let int = if hs then "Int" else "CInt" in
9318   let bool = if hs then "Bool" else "CInt" in
9319   let int64 = if hs then "Integer" else "Int64" in
9320   List.iter (
9321     fun arg ->
9322       (match arg with
9323        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9324        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9325        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9326        | Bool _ -> pr "%s" bool
9327        | Int _ -> pr "%s" int
9328        | Int64 _ -> pr "%s" int
9329        | FileIn _ -> pr "%s" string
9330        | FileOut _ -> pr "%s" string
9331       );
9332       pr " -> ";
9333   ) (snd style);
9334   pr "IO (";
9335   (match fst style with
9336    | RErr -> if not hs then pr "CInt"
9337    | RInt _ -> pr "%s" int
9338    | RInt64 _ -> pr "%s" int64
9339    | RBool _ -> pr "%s" bool
9340    | RConstString _ -> pr "%s" string
9341    | RConstOptString _ -> pr "Maybe %s" string
9342    | RString _ -> pr "%s" string
9343    | RStringList _ -> pr "[%s]" string
9344    | RStruct (_, typ) ->
9345        let name = java_name_of_struct typ in
9346        pr "%s" name
9347    | RStructList (_, typ) ->
9348        let name = java_name_of_struct typ in
9349        pr "[%s]" name
9350    | RHashtable _ -> pr "Hashtable"
9351    | RBufferOut _ -> pr "%s" string
9352   );
9353   pr ")"
9354
9355 and generate_bindtests () =
9356   generate_header CStyle LGPLv2;
9357
9358   pr "\
9359 #include <stdio.h>
9360 #include <stdlib.h>
9361 #include <inttypes.h>
9362 #include <string.h>
9363
9364 #include \"guestfs.h\"
9365 #include \"guestfs-internal-actions.h\"
9366 #include \"guestfs_protocol.h\"
9367
9368 #define error guestfs_error
9369 #define safe_calloc guestfs_safe_calloc
9370 #define safe_malloc guestfs_safe_malloc
9371
9372 static void
9373 print_strings (char *const *argv)
9374 {
9375   int argc;
9376
9377   printf (\"[\");
9378   for (argc = 0; argv[argc] != NULL; ++argc) {
9379     if (argc > 0) printf (\", \");
9380     printf (\"\\\"%%s\\\"\", argv[argc]);
9381   }
9382   printf (\"]\\n\");
9383 }
9384
9385 /* The test0 function prints its parameters to stdout. */
9386 ";
9387
9388   let test0, tests =
9389     match test_functions with
9390     | [] -> assert false
9391     | test0 :: tests -> test0, tests in
9392
9393   let () =
9394     let (name, style, _, _, _, _, _) = test0 in
9395     generate_prototype ~extern:false ~semicolon:false ~newline:true
9396       ~handle:"g" ~prefix:"guestfs__" name style;
9397     pr "{\n";
9398     List.iter (
9399       function
9400       | Pathname n
9401       | Device n | Dev_or_Path n
9402       | String n
9403       | FileIn n
9404       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9405       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9406       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9407       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9408       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9409       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9410     ) (snd style);
9411     pr "  /* Java changes stdout line buffering so we need this: */\n";
9412     pr "  fflush (stdout);\n";
9413     pr "  return 0;\n";
9414     pr "}\n";
9415     pr "\n" in
9416
9417   List.iter (
9418     fun (name, style, _, _, _, _, _) ->
9419       if String.sub name (String.length name - 3) 3 <> "err" then (
9420         pr "/* Test normal return. */\n";
9421         generate_prototype ~extern:false ~semicolon:false ~newline:true
9422           ~handle:"g" ~prefix:"guestfs__" name style;
9423         pr "{\n";
9424         (match fst style with
9425          | RErr ->
9426              pr "  return 0;\n"
9427          | RInt _ ->
9428              pr "  int r;\n";
9429              pr "  sscanf (val, \"%%d\", &r);\n";
9430              pr "  return r;\n"
9431          | RInt64 _ ->
9432              pr "  int64_t r;\n";
9433              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9434              pr "  return r;\n"
9435          | RBool _ ->
9436              pr "  return strcmp (val, \"true\") == 0;\n"
9437          | RConstString _
9438          | RConstOptString _ ->
9439              (* Can't return the input string here.  Return a static
9440               * string so we ensure we get a segfault if the caller
9441               * tries to free it.
9442               *)
9443              pr "  return \"static string\";\n"
9444          | RString _ ->
9445              pr "  return strdup (val);\n"
9446          | RStringList _ ->
9447              pr "  char **strs;\n";
9448              pr "  int n, i;\n";
9449              pr "  sscanf (val, \"%%d\", &n);\n";
9450              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9451              pr "  for (i = 0; i < n; ++i) {\n";
9452              pr "    strs[i] = safe_malloc (g, 16);\n";
9453              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9454              pr "  }\n";
9455              pr "  strs[n] = NULL;\n";
9456              pr "  return strs;\n"
9457          | RStruct (_, typ) ->
9458              pr "  struct guestfs_%s *r;\n" typ;
9459              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9460              pr "  return r;\n"
9461          | RStructList (_, typ) ->
9462              pr "  struct guestfs_%s_list *r;\n" typ;
9463              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9464              pr "  sscanf (val, \"%%d\", &r->len);\n";
9465              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9466              pr "  return r;\n"
9467          | RHashtable _ ->
9468              pr "  char **strs;\n";
9469              pr "  int n, i;\n";
9470              pr "  sscanf (val, \"%%d\", &n);\n";
9471              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9472              pr "  for (i = 0; i < n; ++i) {\n";
9473              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9474              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9475              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9476              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9477              pr "  }\n";
9478              pr "  strs[n*2] = NULL;\n";
9479              pr "  return strs;\n"
9480          | RBufferOut _ ->
9481              pr "  return strdup (val);\n"
9482         );
9483         pr "}\n";
9484         pr "\n"
9485       ) else (
9486         pr "/* Test error return. */\n";
9487         generate_prototype ~extern:false ~semicolon:false ~newline:true
9488           ~handle:"g" ~prefix:"guestfs__" name style;
9489         pr "{\n";
9490         pr "  error (g, \"error\");\n";
9491         (match fst style with
9492          | RErr | RInt _ | RInt64 _ | RBool _ ->
9493              pr "  return -1;\n"
9494          | RConstString _ | RConstOptString _
9495          | RString _ | RStringList _ | RStruct _
9496          | RStructList _
9497          | RHashtable _
9498          | RBufferOut _ ->
9499              pr "  return NULL;\n"
9500         );
9501         pr "}\n";
9502         pr "\n"
9503       )
9504   ) tests
9505
9506 and generate_ocaml_bindtests () =
9507   generate_header OCamlStyle GPLv2;
9508
9509   pr "\
9510 let () =
9511   let g = Guestfs.create () in
9512 ";
9513
9514   let mkargs args =
9515     String.concat " " (
9516       List.map (
9517         function
9518         | CallString s -> "\"" ^ s ^ "\""
9519         | CallOptString None -> "None"
9520         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9521         | CallStringList xs ->
9522             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9523         | CallInt i when i >= 0 -> string_of_int i
9524         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9525         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9526         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9527         | CallBool b -> string_of_bool b
9528       ) args
9529     )
9530   in
9531
9532   generate_lang_bindtests (
9533     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9534   );
9535
9536   pr "print_endline \"EOF\"\n"
9537
9538 and generate_perl_bindtests () =
9539   pr "#!/usr/bin/perl -w\n";
9540   generate_header HashStyle GPLv2;
9541
9542   pr "\
9543 use strict;
9544
9545 use Sys::Guestfs;
9546
9547 my $g = Sys::Guestfs->new ();
9548 ";
9549
9550   let mkargs args =
9551     String.concat ", " (
9552       List.map (
9553         function
9554         | CallString s -> "\"" ^ s ^ "\""
9555         | CallOptString None -> "undef"
9556         | CallOptString (Some s) -> sprintf "\"%s\"" s
9557         | CallStringList xs ->
9558             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9559         | CallInt i -> string_of_int i
9560         | CallInt64 i -> Int64.to_string i
9561         | CallBool b -> if b then "1" else "0"
9562       ) args
9563     )
9564   in
9565
9566   generate_lang_bindtests (
9567     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9568   );
9569
9570   pr "print \"EOF\\n\"\n"
9571
9572 and generate_python_bindtests () =
9573   generate_header HashStyle GPLv2;
9574
9575   pr "\
9576 import guestfs
9577
9578 g = guestfs.GuestFS ()
9579 ";
9580
9581   let mkargs args =
9582     String.concat ", " (
9583       List.map (
9584         function
9585         | CallString s -> "\"" ^ s ^ "\""
9586         | CallOptString None -> "None"
9587         | CallOptString (Some s) -> sprintf "\"%s\"" s
9588         | CallStringList xs ->
9589             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9590         | CallInt i -> string_of_int i
9591         | CallInt64 i -> Int64.to_string i
9592         | CallBool b -> if b then "1" else "0"
9593       ) args
9594     )
9595   in
9596
9597   generate_lang_bindtests (
9598     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9599   );
9600
9601   pr "print \"EOF\"\n"
9602
9603 and generate_ruby_bindtests () =
9604   generate_header HashStyle GPLv2;
9605
9606   pr "\
9607 require 'guestfs'
9608
9609 g = Guestfs::create()
9610 ";
9611
9612   let mkargs args =
9613     String.concat ", " (
9614       List.map (
9615         function
9616         | CallString s -> "\"" ^ s ^ "\""
9617         | CallOptString None -> "nil"
9618         | CallOptString (Some s) -> sprintf "\"%s\"" s
9619         | CallStringList xs ->
9620             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9621         | CallInt i -> string_of_int i
9622         | CallInt64 i -> Int64.to_string i
9623         | CallBool b -> string_of_bool b
9624       ) args
9625     )
9626   in
9627
9628   generate_lang_bindtests (
9629     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9630   );
9631
9632   pr "print \"EOF\\n\"\n"
9633
9634 and generate_java_bindtests () =
9635   generate_header CStyle GPLv2;
9636
9637   pr "\
9638 import com.redhat.et.libguestfs.*;
9639
9640 public class Bindtests {
9641     public static void main (String[] argv)
9642     {
9643         try {
9644             GuestFS g = new GuestFS ();
9645 ";
9646
9647   let mkargs args =
9648     String.concat ", " (
9649       List.map (
9650         function
9651         | CallString s -> "\"" ^ s ^ "\""
9652         | CallOptString None -> "null"
9653         | CallOptString (Some s) -> sprintf "\"%s\"" s
9654         | CallStringList xs ->
9655             "new String[]{" ^
9656               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9657         | CallInt i -> string_of_int i
9658         | CallInt64 i -> Int64.to_string i
9659         | CallBool b -> string_of_bool b
9660       ) args
9661     )
9662   in
9663
9664   generate_lang_bindtests (
9665     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9666   );
9667
9668   pr "
9669             System.out.println (\"EOF\");
9670         }
9671         catch (Exception exn) {
9672             System.err.println (exn);
9673             System.exit (1);
9674         }
9675     }
9676 }
9677 "
9678
9679 and generate_haskell_bindtests () =
9680   generate_header HaskellStyle GPLv2;
9681
9682   pr "\
9683 module Bindtests where
9684 import qualified Guestfs
9685
9686 main = do
9687   g <- Guestfs.create
9688 ";
9689
9690   let mkargs args =
9691     String.concat " " (
9692       List.map (
9693         function
9694         | CallString s -> "\"" ^ s ^ "\""
9695         | CallOptString None -> "Nothing"
9696         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9697         | CallStringList xs ->
9698             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9699         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9700         | CallInt i -> string_of_int i
9701         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
9702         | CallInt64 i -> Int64.to_string i
9703         | CallBool true -> "True"
9704         | CallBool false -> "False"
9705       ) args
9706     )
9707   in
9708
9709   generate_lang_bindtests (
9710     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9711   );
9712
9713   pr "  putStrLn \"EOF\"\n"
9714
9715 (* Language-independent bindings tests - we do it this way to
9716  * ensure there is parity in testing bindings across all languages.
9717  *)
9718 and generate_lang_bindtests call =
9719   call "test0" [CallString "abc"; CallOptString (Some "def");
9720                 CallStringList []; CallBool false;
9721                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9722   call "test0" [CallString "abc"; CallOptString None;
9723                 CallStringList []; CallBool false;
9724                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9725   call "test0" [CallString ""; CallOptString (Some "def");
9726                 CallStringList []; CallBool false;
9727                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9728   call "test0" [CallString ""; CallOptString (Some "");
9729                 CallStringList []; CallBool false;
9730                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9731   call "test0" [CallString "abc"; CallOptString (Some "def");
9732                 CallStringList ["1"]; CallBool false;
9733                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9734   call "test0" [CallString "abc"; CallOptString (Some "def");
9735                 CallStringList ["1"; "2"]; CallBool false;
9736                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9737   call "test0" [CallString "abc"; CallOptString (Some "def");
9738                 CallStringList ["1"]; CallBool true;
9739                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9740   call "test0" [CallString "abc"; CallOptString (Some "def");
9741                 CallStringList ["1"]; CallBool false;
9742                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
9743   call "test0" [CallString "abc"; CallOptString (Some "def");
9744                 CallStringList ["1"]; CallBool false;
9745                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
9746   call "test0" [CallString "abc"; CallOptString (Some "def");
9747                 CallStringList ["1"]; CallBool false;
9748                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
9749   call "test0" [CallString "abc"; CallOptString (Some "def");
9750                 CallStringList ["1"]; CallBool false;
9751                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
9752   call "test0" [CallString "abc"; CallOptString (Some "def");
9753                 CallStringList ["1"]; CallBool false;
9754                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
9755   call "test0" [CallString "abc"; CallOptString (Some "def");
9756                 CallStringList ["1"]; CallBool false;
9757                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
9758
9759 (* XXX Add here tests of the return and error functions. *)
9760
9761 (* This is used to generate the src/MAX_PROC_NR file which
9762  * contains the maximum procedure number, a surrogate for the
9763  * ABI version number.  See src/Makefile.am for the details.
9764  *)
9765 and generate_max_proc_nr () =
9766   let proc_nrs = List.map (
9767     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9768   ) daemon_functions in
9769
9770   let max_proc_nr = List.fold_left max 0 proc_nrs in
9771
9772   pr "%d\n" max_proc_nr
9773
9774 let output_to filename =
9775   let filename_new = filename ^ ".new" in
9776   chan := open_out filename_new;
9777   let close () =
9778     close_out !chan;
9779     chan := stdout;
9780
9781     (* Is the new file different from the current file? *)
9782     if Sys.file_exists filename && files_equal filename filename_new then
9783       Unix.unlink filename_new          (* same, so skip it *)
9784     else (
9785       (* different, overwrite old one *)
9786       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9787       Unix.rename filename_new filename;
9788       Unix.chmod filename 0o444;
9789       printf "written %s\n%!" filename;
9790     )
9791   in
9792   close
9793
9794 (* Main program. *)
9795 let () =
9796   check_functions ();
9797
9798   if not (Sys.file_exists "HACKING") then (
9799     eprintf "\
9800 You are probably running this from the wrong directory.
9801 Run it from the top source directory using the command
9802   src/generator.ml
9803 ";
9804     exit 1
9805   );
9806
9807   let close = output_to "src/guestfs_protocol.x" in
9808   generate_xdr ();
9809   close ();
9810
9811   let close = output_to "src/guestfs-structs.h" in
9812   generate_structs_h ();
9813   close ();
9814
9815   let close = output_to "src/guestfs-actions.h" in
9816   generate_actions_h ();
9817   close ();
9818
9819   let close = output_to "src/guestfs-internal-actions.h" in
9820   generate_internal_actions_h ();
9821   close ();
9822
9823   let close = output_to "src/guestfs-actions.c" in
9824   generate_client_actions ();
9825   close ();
9826
9827   let close = output_to "daemon/actions.h" in
9828   generate_daemon_actions_h ();
9829   close ();
9830
9831   let close = output_to "daemon/stubs.c" in
9832   generate_daemon_actions ();
9833   close ();
9834
9835   let close = output_to "daemon/names.c" in
9836   generate_daemon_names ();
9837   close ();
9838
9839   let close = output_to "capitests/tests.c" in
9840   generate_tests ();
9841   close ();
9842
9843   let close = output_to "src/guestfs-bindtests.c" in
9844   generate_bindtests ();
9845   close ();
9846
9847   let close = output_to "fish/cmds.c" in
9848   generate_fish_cmds ();
9849   close ();
9850
9851   let close = output_to "fish/completion.c" in
9852   generate_fish_completion ();
9853   close ();
9854
9855   let close = output_to "guestfs-structs.pod" in
9856   generate_structs_pod ();
9857   close ();
9858
9859   let close = output_to "guestfs-actions.pod" in
9860   generate_actions_pod ();
9861   close ();
9862
9863   let close = output_to "guestfish-actions.pod" in
9864   generate_fish_actions_pod ();
9865   close ();
9866
9867   let close = output_to "ocaml/guestfs.mli" in
9868   generate_ocaml_mli ();
9869   close ();
9870
9871   let close = output_to "ocaml/guestfs.ml" in
9872   generate_ocaml_ml ();
9873   close ();
9874
9875   let close = output_to "ocaml/guestfs_c_actions.c" in
9876   generate_ocaml_c ();
9877   close ();
9878
9879   let close = output_to "ocaml/bindtests.ml" in
9880   generate_ocaml_bindtests ();
9881   close ();
9882
9883   let close = output_to "perl/Guestfs.xs" in
9884   generate_perl_xs ();
9885   close ();
9886
9887   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9888   generate_perl_pm ();
9889   close ();
9890
9891   let close = output_to "perl/bindtests.pl" in
9892   generate_perl_bindtests ();
9893   close ();
9894
9895   let close = output_to "python/guestfs-py.c" in
9896   generate_python_c ();
9897   close ();
9898
9899   let close = output_to "python/guestfs.py" in
9900   generate_python_py ();
9901   close ();
9902
9903   let close = output_to "python/bindtests.py" in
9904   generate_python_bindtests ();
9905   close ();
9906
9907   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9908   generate_ruby_c ();
9909   close ();
9910
9911   let close = output_to "ruby/bindtests.rb" in
9912   generate_ruby_bindtests ();
9913   close ();
9914
9915   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9916   generate_java_java ();
9917   close ();
9918
9919   List.iter (
9920     fun (typ, jtyp) ->
9921       let cols = cols_of_struct typ in
9922       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9923       let close = output_to filename in
9924       generate_java_struct jtyp cols;
9925       close ();
9926   ) java_structs;
9927
9928   let close = output_to "java/Makefile.inc" in
9929   generate_java_makefile_inc ();
9930   close ();
9931
9932   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9933   generate_java_c ();
9934   close ();
9935
9936   let close = output_to "java/Bindtests.java" in
9937   generate_java_bindtests ();
9938   close ();
9939
9940   let close = output_to "haskell/Guestfs.hs" in
9941   generate_haskell_hs ();
9942   close ();
9943
9944   let close = output_to "haskell/Bindtests.hs" in
9945   generate_haskell_bindtests ();
9946   close ();
9947
9948   let close = output_to "src/MAX_PROC_NR" in
9949   generate_max_proc_nr ();
9950   close ();
9951
9952   (* Always generate this file last, and unconditionally.  It's used
9953    * by the Makefile to know when we must re-run the generator.
9954    *)
9955   let chan = open_out "src/stamp-generator" in
9956   fprintf chan "1\n";
9957   close_out chan