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