c261ea22a1f11f2f5d9a50e0df529e8b914925ec
[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     InitISOFS, Always, TestOutputBuffer (
3895       [["pread"; "/empty"; "0"; "100"]], "")],
3896    "read part of a file",
3897    "\
3898 This command lets you read part of a file.  It reads C<count>
3899 bytes of the file, starting at C<offset>, from file C<path>.
3900
3901 This may read fewer bytes than requested.  For further details
3902 see the L<pread(2)> system call.");
3903
3904   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3905    [InitEmpty, Always, TestRun (
3906       [["part_init"; "/dev/sda"; "gpt"]])],
3907    "create an empty partition table",
3908    "\
3909 This creates an empty partition table on C<device> of one of the
3910 partition types listed below.  Usually C<parttype> should be
3911 either C<msdos> or C<gpt> (for large disks).
3912
3913 Initially there are no partitions.  Following this, you should
3914 call C<guestfs_part_add> for each partition required.
3915
3916 Possible values for C<parttype> are:
3917
3918 =over 4
3919
3920 =item B<efi> | B<gpt>
3921
3922 Intel EFI / GPT partition table.
3923
3924 This is recommended for >= 2 TB partitions that will be accessed
3925 from Linux and Intel-based Mac OS X.  It also has limited backwards
3926 compatibility with the C<mbr> format.
3927
3928 =item B<mbr> | B<msdos>
3929
3930 The standard PC \"Master Boot Record\" (MBR) format used
3931 by MS-DOS and Windows.  This partition type will B<only> work
3932 for device sizes up to 2 TB.  For large disks we recommend
3933 using C<gpt>.
3934
3935 =back
3936
3937 Other partition table types that may work but are not
3938 supported include:
3939
3940 =over 4
3941
3942 =item B<aix>
3943
3944 AIX disk labels.
3945
3946 =item B<amiga> | B<rdb>
3947
3948 Amiga \"Rigid Disk Block\" format.
3949
3950 =item B<bsd>
3951
3952 BSD disk labels.
3953
3954 =item B<dasd>
3955
3956 DASD, used on IBM mainframes.
3957
3958 =item B<dvh>
3959
3960 MIPS/SGI volumes.
3961
3962 =item B<mac>
3963
3964 Old Mac partition format.  Modern Macs use C<gpt>.
3965
3966 =item B<pc98>
3967
3968 NEC PC-98 format, common in Japan apparently.
3969
3970 =item B<sun>
3971
3972 Sun disk labels.
3973
3974 =back");
3975
3976   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3977    [InitEmpty, Always, TestRun (
3978       [["part_init"; "/dev/sda"; "mbr"];
3979        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3980     InitEmpty, Always, TestRun (
3981       [["part_init"; "/dev/sda"; "gpt"];
3982        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3983        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3984     InitEmpty, Always, TestRun (
3985       [["part_init"; "/dev/sda"; "mbr"];
3986        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3987        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3988        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3989        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3990    "add a partition to the device",
3991    "\
3992 This command adds a partition to C<device>.  If there is no partition
3993 table on the device, call C<guestfs_part_init> first.
3994
3995 The C<prlogex> parameter is the type of partition.  Normally you
3996 should pass C<p> or C<primary> here, but MBR partition tables also
3997 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
3998 types.
3999
4000 C<startsect> and C<endsect> are the start and end of the partition
4001 in I<sectors>.  C<endsect> may be negative, which means it counts
4002 backwards from the end of the disk (C<-1> is the last sector).
4003
4004 Creating a partition which covers the whole disk is not so easy.
4005 Use C<guestfs_part_disk> to do that.");
4006
4007   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4008    [InitEmpty, Always, TestRun (
4009       [["part_disk"; "/dev/sda"; "mbr"]]);
4010     InitEmpty, Always, TestRun (
4011       [["part_disk"; "/dev/sda"; "gpt"]])],
4012    "partition whole disk with a single primary partition",
4013    "\
4014 This command is simply a combination of C<guestfs_part_init>
4015 followed by C<guestfs_part_add> to create a single primary partition
4016 covering the whole disk.
4017
4018 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4019 but other possible values are described in C<guestfs_part_init>.");
4020
4021   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4022    [InitEmpty, Always, TestRun (
4023       [["part_disk"; "/dev/sda"; "mbr"];
4024        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4025    "make a partition bootable",
4026    "\
4027 This sets the bootable flag on partition numbered C<partnum> on
4028 device C<device>.  Note that partitions are numbered from 1.
4029
4030 The bootable flag is used by some PC BIOSes to determine which
4031 partition to boot from.  It is by no means universally recognized,
4032 and in any case if your operating system installed a boot
4033 sector on the device itself, then that takes precedence.");
4034
4035   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4036    [InitEmpty, Always, TestRun (
4037       [["part_disk"; "/dev/sda"; "gpt"];
4038        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4039    "set partition name",
4040    "\
4041 This sets the partition name on partition numbered C<partnum> on
4042 device C<device>.  Note that partitions are numbered from 1.
4043
4044 The partition name can only be set on certain types of partition
4045 table.  This works on C<gpt> but not on C<mbr> partitions.");
4046
4047   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4048    [], (* XXX Add a regression test for this. *)
4049    "list partitions on a device",
4050    "\
4051 This command parses the partition table on C<device> and
4052 returns the list of partitions found.
4053
4054 The fields in the returned structure are:
4055
4056 =over 4
4057
4058 =item B<part_num>
4059
4060 Partition number, counting from 1.
4061
4062 =item B<part_start>
4063
4064 Start of the partition I<in bytes>.  To get sectors you have to
4065 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4066
4067 =item B<part_end>
4068
4069 End of the partition in bytes.
4070
4071 =item B<part_size>
4072
4073 Size of the partition in bytes.
4074
4075 =back");
4076
4077   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4078    [InitEmpty, Always, TestOutput (
4079       [["part_disk"; "/dev/sda"; "gpt"];
4080        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4081    "get the partition table type",
4082    "\
4083 This command examines the partition table on C<device> and
4084 returns the partition table type (format) being used.
4085
4086 Common return values include: C<msdos> (a DOS/Windows style MBR
4087 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4088 values are possible, although unusual.  See C<guestfs_part_init>
4089 for a full list.");
4090
4091   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4092    [InitBasicFS, Always, TestOutputBuffer (
4093       [["fill"; "0x63"; "10"; "/test"];
4094        ["read_file"; "/test"]], "cccccccccc")],
4095    "fill a file with octets",
4096    "\
4097 This command creates a new file called C<path>.  The initial
4098 content of the file is C<len> octets of C<c>, where C<c>
4099 must be a number in the range C<[0..255]>.
4100
4101 To fill a file with zero bytes (sparsely), it is
4102 much more efficient to use C<guestfs_truncate_size>.");
4103
4104 ]
4105
4106 let all_functions = non_daemon_functions @ daemon_functions
4107
4108 (* In some places we want the functions to be displayed sorted
4109  * alphabetically, so this is useful:
4110  *)
4111 let all_functions_sorted =
4112   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4113                compare n1 n2) all_functions
4114
4115 (* Field types for structures. *)
4116 type field =
4117   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4118   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4119   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4120   | FUInt32
4121   | FInt32
4122   | FUInt64
4123   | FInt64
4124   | FBytes                      (* Any int measure that counts bytes. *)
4125   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4126   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4127
4128 (* Because we generate extra parsing code for LVM command line tools,
4129  * we have to pull out the LVM columns separately here.
4130  *)
4131 let lvm_pv_cols = [
4132   "pv_name", FString;
4133   "pv_uuid", FUUID;
4134   "pv_fmt", FString;
4135   "pv_size", FBytes;
4136   "dev_size", FBytes;
4137   "pv_free", FBytes;
4138   "pv_used", FBytes;
4139   "pv_attr", FString (* XXX *);
4140   "pv_pe_count", FInt64;
4141   "pv_pe_alloc_count", FInt64;
4142   "pv_tags", FString;
4143   "pe_start", FBytes;
4144   "pv_mda_count", FInt64;
4145   "pv_mda_free", FBytes;
4146   (* Not in Fedora 10:
4147      "pv_mda_size", FBytes;
4148   *)
4149 ]
4150 let lvm_vg_cols = [
4151   "vg_name", FString;
4152   "vg_uuid", FUUID;
4153   "vg_fmt", FString;
4154   "vg_attr", FString (* XXX *);
4155   "vg_size", FBytes;
4156   "vg_free", FBytes;
4157   "vg_sysid", FString;
4158   "vg_extent_size", FBytes;
4159   "vg_extent_count", FInt64;
4160   "vg_free_count", FInt64;
4161   "max_lv", FInt64;
4162   "max_pv", FInt64;
4163   "pv_count", FInt64;
4164   "lv_count", FInt64;
4165   "snap_count", FInt64;
4166   "vg_seqno", FInt64;
4167   "vg_tags", FString;
4168   "vg_mda_count", FInt64;
4169   "vg_mda_free", FBytes;
4170   (* Not in Fedora 10:
4171      "vg_mda_size", FBytes;
4172   *)
4173 ]
4174 let lvm_lv_cols = [
4175   "lv_name", FString;
4176   "lv_uuid", FUUID;
4177   "lv_attr", FString (* XXX *);
4178   "lv_major", FInt64;
4179   "lv_minor", FInt64;
4180   "lv_kernel_major", FInt64;
4181   "lv_kernel_minor", FInt64;
4182   "lv_size", FBytes;
4183   "seg_count", FInt64;
4184   "origin", FString;
4185   "snap_percent", FOptPercent;
4186   "copy_percent", FOptPercent;
4187   "move_pv", FString;
4188   "lv_tags", FString;
4189   "mirror_log", FString;
4190   "modules", FString;
4191 ]
4192
4193 (* Names and fields in all structures (in RStruct and RStructList)
4194  * that we support.
4195  *)
4196 let structs = [
4197   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4198    * not use this struct in any new code.
4199    *)
4200   "int_bool", [
4201     "i", FInt32;                (* for historical compatibility *)
4202     "b", FInt32;                (* for historical compatibility *)
4203   ];
4204
4205   (* LVM PVs, VGs, LVs. *)
4206   "lvm_pv", lvm_pv_cols;
4207   "lvm_vg", lvm_vg_cols;
4208   "lvm_lv", lvm_lv_cols;
4209
4210   (* Column names and types from stat structures.
4211    * NB. Can't use things like 'st_atime' because glibc header files
4212    * define some of these as macros.  Ugh.
4213    *)
4214   "stat", [
4215     "dev", FInt64;
4216     "ino", FInt64;
4217     "mode", FInt64;
4218     "nlink", FInt64;
4219     "uid", FInt64;
4220     "gid", FInt64;
4221     "rdev", FInt64;
4222     "size", FInt64;
4223     "blksize", FInt64;
4224     "blocks", FInt64;
4225     "atime", FInt64;
4226     "mtime", FInt64;
4227     "ctime", FInt64;
4228   ];
4229   "statvfs", [
4230     "bsize", FInt64;
4231     "frsize", FInt64;
4232     "blocks", FInt64;
4233     "bfree", FInt64;
4234     "bavail", FInt64;
4235     "files", FInt64;
4236     "ffree", FInt64;
4237     "favail", FInt64;
4238     "fsid", FInt64;
4239     "flag", FInt64;
4240     "namemax", FInt64;
4241   ];
4242
4243   (* Column names in dirent structure. *)
4244   "dirent", [
4245     "ino", FInt64;
4246     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4247     "ftyp", FChar;
4248     "name", FString;
4249   ];
4250
4251   (* Version numbers. *)
4252   "version", [
4253     "major", FInt64;
4254     "minor", FInt64;
4255     "release", FInt64;
4256     "extra", FString;
4257   ];
4258
4259   (* Extended attribute. *)
4260   "xattr", [
4261     "attrname", FString;
4262     "attrval", FBuffer;
4263   ];
4264
4265   (* Inotify events. *)
4266   "inotify_event", [
4267     "in_wd", FInt64;
4268     "in_mask", FUInt32;
4269     "in_cookie", FUInt32;
4270     "in_name", FString;
4271   ];
4272
4273   (* Partition table entry. *)
4274   "partition", [
4275     "part_num", FInt32;
4276     "part_start", FBytes;
4277     "part_end", FBytes;
4278     "part_size", FBytes;
4279   ];
4280 ] (* end of structs *)
4281
4282 (* Ugh, Java has to be different ..
4283  * These names are also used by the Haskell bindings.
4284  *)
4285 let java_structs = [
4286   "int_bool", "IntBool";
4287   "lvm_pv", "PV";
4288   "lvm_vg", "VG";
4289   "lvm_lv", "LV";
4290   "stat", "Stat";
4291   "statvfs", "StatVFS";
4292   "dirent", "Dirent";
4293   "version", "Version";
4294   "xattr", "XAttr";
4295   "inotify_event", "INotifyEvent";
4296   "partition", "Partition";
4297 ]
4298
4299 (* What structs are actually returned. *)
4300 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4301
4302 (* Returns a list of RStruct/RStructList structs that are returned
4303  * by any function.  Each element of returned list is a pair:
4304  *
4305  * (structname, RStructOnly)
4306  *    == there exists function which returns RStruct (_, structname)
4307  * (structname, RStructListOnly)
4308  *    == there exists function which returns RStructList (_, structname)
4309  * (structname, RStructAndList)
4310  *    == there are functions returning both RStruct (_, structname)
4311  *                                      and RStructList (_, structname)
4312  *)
4313 let rstructs_used_by functions =
4314   (* ||| is a "logical OR" for rstructs_used_t *)
4315   let (|||) a b =
4316     match a, b with
4317     | RStructAndList, _
4318     | _, RStructAndList -> RStructAndList
4319     | RStructOnly, RStructListOnly
4320     | RStructListOnly, RStructOnly -> RStructAndList
4321     | RStructOnly, RStructOnly -> RStructOnly
4322     | RStructListOnly, RStructListOnly -> RStructListOnly
4323   in
4324
4325   let h = Hashtbl.create 13 in
4326
4327   (* if elem->oldv exists, update entry using ||| operator,
4328    * else just add elem->newv to the hash
4329    *)
4330   let update elem newv =
4331     try  let oldv = Hashtbl.find h elem in
4332          Hashtbl.replace h elem (newv ||| oldv)
4333     with Not_found -> Hashtbl.add h elem newv
4334   in
4335
4336   List.iter (
4337     fun (_, style, _, _, _, _, _) ->
4338       match fst style with
4339       | RStruct (_, structname) -> update structname RStructOnly
4340       | RStructList (_, structname) -> update structname RStructListOnly
4341       | _ -> ()
4342   ) functions;
4343
4344   (* return key->values as a list of (key,value) *)
4345   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4346
4347 (* Used for testing language bindings. *)
4348 type callt =
4349   | CallString of string
4350   | CallOptString of string option
4351   | CallStringList of string list
4352   | CallInt of int
4353   | CallInt64 of int64
4354   | CallBool of bool
4355
4356 (* Used to memoize the result of pod2text. *)
4357 let pod2text_memo_filename = "src/.pod2text.data"
4358 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4359   try
4360     let chan = open_in pod2text_memo_filename in
4361     let v = input_value chan in
4362     close_in chan;
4363     v
4364   with
4365     _ -> Hashtbl.create 13
4366 let pod2text_memo_updated () =
4367   let chan = open_out pod2text_memo_filename in
4368   output_value chan pod2text_memo;
4369   close_out chan
4370
4371 (* Useful functions.
4372  * Note we don't want to use any external OCaml libraries which
4373  * makes this a bit harder than it should be.
4374  *)
4375 let failwithf fs = ksprintf failwith fs
4376
4377 let replace_char s c1 c2 =
4378   let s2 = String.copy s in
4379   let r = ref false in
4380   for i = 0 to String.length s2 - 1 do
4381     if String.unsafe_get s2 i = c1 then (
4382       String.unsafe_set s2 i c2;
4383       r := true
4384     )
4385   done;
4386   if not !r then s else s2
4387
4388 let isspace c =
4389   c = ' '
4390   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4391
4392 let triml ?(test = isspace) str =
4393   let i = ref 0 in
4394   let n = ref (String.length str) in
4395   while !n > 0 && test str.[!i]; do
4396     decr n;
4397     incr i
4398   done;
4399   if !i = 0 then str
4400   else String.sub str !i !n
4401
4402 let trimr ?(test = isspace) str =
4403   let n = ref (String.length str) in
4404   while !n > 0 && test str.[!n-1]; do
4405     decr n
4406   done;
4407   if !n = String.length str then str
4408   else String.sub str 0 !n
4409
4410 let trim ?(test = isspace) str =
4411   trimr ~test (triml ~test str)
4412
4413 let rec find s sub =
4414   let len = String.length s in
4415   let sublen = String.length sub in
4416   let rec loop i =
4417     if i <= len-sublen then (
4418       let rec loop2 j =
4419         if j < sublen then (
4420           if s.[i+j] = sub.[j] then loop2 (j+1)
4421           else -1
4422         ) else
4423           i (* found *)
4424       in
4425       let r = loop2 0 in
4426       if r = -1 then loop (i+1) else r
4427     ) else
4428       -1 (* not found *)
4429   in
4430   loop 0
4431
4432 let rec replace_str s s1 s2 =
4433   let len = String.length s in
4434   let sublen = String.length s1 in
4435   let i = find s s1 in
4436   if i = -1 then s
4437   else (
4438     let s' = String.sub s 0 i in
4439     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4440     s' ^ s2 ^ replace_str s'' s1 s2
4441   )
4442
4443 let rec string_split sep str =
4444   let len = String.length str in
4445   let seplen = String.length sep in
4446   let i = find str sep in
4447   if i = -1 then [str]
4448   else (
4449     let s' = String.sub str 0 i in
4450     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4451     s' :: string_split sep s''
4452   )
4453
4454 let files_equal n1 n2 =
4455   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4456   match Sys.command cmd with
4457   | 0 -> true
4458   | 1 -> false
4459   | i -> failwithf "%s: failed with error code %d" cmd i
4460
4461 let rec filter_map f = function
4462   | [] -> []
4463   | x :: xs ->
4464       match f x with
4465       | Some y -> y :: filter_map f xs
4466       | None -> filter_map f xs
4467
4468 let rec find_map f = function
4469   | [] -> raise Not_found
4470   | x :: xs ->
4471       match f x with
4472       | Some y -> y
4473       | None -> find_map f xs
4474
4475 let iteri f xs =
4476   let rec loop i = function
4477     | [] -> ()
4478     | x :: xs -> f i x; loop (i+1) xs
4479   in
4480   loop 0 xs
4481
4482 let mapi f xs =
4483   let rec loop i = function
4484     | [] -> []
4485     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4486   in
4487   loop 0 xs
4488
4489 let name_of_argt = function
4490   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4491   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4492   | FileIn n | FileOut n -> n
4493
4494 let java_name_of_struct typ =
4495   try List.assoc typ java_structs
4496   with Not_found ->
4497     failwithf
4498       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4499
4500 let cols_of_struct typ =
4501   try List.assoc typ structs
4502   with Not_found ->
4503     failwithf "cols_of_struct: unknown struct %s" typ
4504
4505 let seq_of_test = function
4506   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4507   | TestOutputListOfDevices (s, _)
4508   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4509   | TestOutputTrue s | TestOutputFalse s
4510   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4511   | TestOutputStruct (s, _)
4512   | TestLastFail s -> s
4513
4514 (* Handling for function flags. *)
4515 let protocol_limit_warning =
4516   "Because of the message protocol, there is a transfer limit
4517 of somewhere between 2MB and 4MB.  To transfer large files you should use
4518 FTP."
4519
4520 let danger_will_robinson =
4521   "B<This command is dangerous.  Without careful use you
4522 can easily destroy all your data>."
4523
4524 let deprecation_notice flags =
4525   try
4526     let alt =
4527       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4528     let txt =
4529       sprintf "This function is deprecated.
4530 In new code, use the C<%s> call instead.
4531
4532 Deprecated functions will not be removed from the API, but the
4533 fact that they are deprecated indicates that there are problems
4534 with correct use of these functions." alt in
4535     Some txt
4536   with
4537     Not_found -> None
4538
4539 (* Check function names etc. for consistency. *)
4540 let check_functions () =
4541   let contains_uppercase str =
4542     let len = String.length str in
4543     let rec loop i =
4544       if i >= len then false
4545       else (
4546         let c = str.[i] in
4547         if c >= 'A' && c <= 'Z' then true
4548         else loop (i+1)
4549       )
4550     in
4551     loop 0
4552   in
4553
4554   (* Check function names. *)
4555   List.iter (
4556     fun (name, _, _, _, _, _, _) ->
4557       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4558         failwithf "function name %s does not need 'guestfs' prefix" name;
4559       if name = "" then
4560         failwithf "function name is empty";
4561       if name.[0] < 'a' || name.[0] > 'z' then
4562         failwithf "function name %s must start with lowercase a-z" name;
4563       if String.contains name '-' then
4564         failwithf "function name %s should not contain '-', use '_' instead."
4565           name
4566   ) all_functions;
4567
4568   (* Check function parameter/return names. *)
4569   List.iter (
4570     fun (name, style, _, _, _, _, _) ->
4571       let check_arg_ret_name n =
4572         if contains_uppercase n then
4573           failwithf "%s param/ret %s should not contain uppercase chars"
4574             name n;
4575         if String.contains n '-' || String.contains n '_' then
4576           failwithf "%s param/ret %s should not contain '-' or '_'"
4577             name n;
4578         if n = "value" then
4579           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;
4580         if n = "int" || n = "char" || n = "short" || n = "long" then
4581           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4582         if n = "i" || n = "n" then
4583           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4584         if n = "argv" || n = "args" then
4585           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4586
4587         (* List Haskell, OCaml and C keywords here.
4588          * http://www.haskell.org/haskellwiki/Keywords
4589          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4590          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4591          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4592          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4593          * Omitting _-containing words, since they're handled above.
4594          * Omitting the OCaml reserved word, "val", is ok,
4595          * and saves us from renaming several parameters.
4596          *)
4597         let reserved = [
4598           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4599           "char"; "class"; "const"; "constraint"; "continue"; "data";
4600           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4601           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4602           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4603           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4604           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4605           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4606           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4607           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4608           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4609           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4610           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4611           "volatile"; "when"; "where"; "while";
4612           ] in
4613         if List.mem n reserved then
4614           failwithf "%s has param/ret using reserved word %s" name n;
4615       in
4616
4617       (match fst style with
4618        | RErr -> ()
4619        | RInt n | RInt64 n | RBool n
4620        | RConstString n | RConstOptString n | RString n
4621        | RStringList n | RStruct (n, _) | RStructList (n, _)
4622        | RHashtable n | RBufferOut n ->
4623            check_arg_ret_name n
4624       );
4625       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4626   ) all_functions;
4627
4628   (* Check short descriptions. *)
4629   List.iter (
4630     fun (name, _, _, _, _, shortdesc, _) ->
4631       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4632         failwithf "short description of %s should begin with lowercase." name;
4633       let c = shortdesc.[String.length shortdesc-1] in
4634       if c = '\n' || c = '.' then
4635         failwithf "short description of %s should not end with . or \\n." name
4636   ) all_functions;
4637
4638   (* Check long dscriptions. *)
4639   List.iter (
4640     fun (name, _, _, _, _, _, longdesc) ->
4641       if longdesc.[String.length longdesc-1] = '\n' then
4642         failwithf "long description of %s should not end with \\n." name
4643   ) all_functions;
4644
4645   (* Check proc_nrs. *)
4646   List.iter (
4647     fun (name, _, proc_nr, _, _, _, _) ->
4648       if proc_nr <= 0 then
4649         failwithf "daemon function %s should have proc_nr > 0" name
4650   ) daemon_functions;
4651
4652   List.iter (
4653     fun (name, _, proc_nr, _, _, _, _) ->
4654       if proc_nr <> -1 then
4655         failwithf "non-daemon function %s should have proc_nr -1" name
4656   ) non_daemon_functions;
4657
4658   let proc_nrs =
4659     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4660       daemon_functions in
4661   let proc_nrs =
4662     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4663   let rec loop = function
4664     | [] -> ()
4665     | [_] -> ()
4666     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4667         loop rest
4668     | (name1,nr1) :: (name2,nr2) :: _ ->
4669         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4670           name1 name2 nr1 nr2
4671   in
4672   loop proc_nrs;
4673
4674   (* Check tests. *)
4675   List.iter (
4676     function
4677       (* Ignore functions that have no tests.  We generate a
4678        * warning when the user does 'make check' instead.
4679        *)
4680     | name, _, _, _, [], _, _ -> ()
4681     | name, _, _, _, tests, _, _ ->
4682         let funcs =
4683           List.map (
4684             fun (_, _, test) ->
4685               match seq_of_test test with
4686               | [] ->
4687                   failwithf "%s has a test containing an empty sequence" name
4688               | cmds -> List.map List.hd cmds
4689           ) tests in
4690         let funcs = List.flatten funcs in
4691
4692         let tested = List.mem name funcs in
4693
4694         if not tested then
4695           failwithf "function %s has tests but does not test itself" name
4696   ) all_functions
4697
4698 (* 'pr' prints to the current output file. *)
4699 let chan = ref stdout
4700 let pr fs = ksprintf (output_string !chan) fs
4701
4702 (* Generate a header block in a number of standard styles. *)
4703 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4704 type license = GPLv2 | LGPLv2
4705
4706 let generate_header comment license =
4707   let c = match comment with
4708     | CStyle ->     pr "/* "; " *"
4709     | HashStyle ->  pr "# ";  "#"
4710     | OCamlStyle -> pr "(* "; " *"
4711     | HaskellStyle -> pr "{- "; "  " in
4712   pr "libguestfs generated file\n";
4713   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4714   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4715   pr "%s\n" c;
4716   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4717   pr "%s\n" c;
4718   (match license with
4719    | GPLv2 ->
4720        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4721        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4722        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4723        pr "%s (at your option) any later version.\n" c;
4724        pr "%s\n" c;
4725        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4726        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4727        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4728        pr "%s GNU General Public License for more details.\n" c;
4729        pr "%s\n" c;
4730        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4731        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4732        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4733
4734    | LGPLv2 ->
4735        pr "%s This library is free software; you can redistribute it and/or\n" c;
4736        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4737        pr "%s License as published by the Free Software Foundation; either\n" c;
4738        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4739        pr "%s\n" c;
4740        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4741        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4742        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4743        pr "%s Lesser General Public License for more details.\n" c;
4744        pr "%s\n" c;
4745        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4746        pr "%s License along with this library; if not, write to the Free Software\n" c;
4747        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4748   );
4749   (match comment with
4750    | CStyle -> pr " */\n"
4751    | HashStyle -> ()
4752    | OCamlStyle -> pr " *)\n"
4753    | HaskellStyle -> pr "-}\n"
4754   );
4755   pr "\n"
4756
4757 (* Start of main code generation functions below this line. *)
4758
4759 (* Generate the pod documentation for the C API. *)
4760 let rec generate_actions_pod () =
4761   List.iter (
4762     fun (shortname, style, _, flags, _, _, longdesc) ->
4763       if not (List.mem NotInDocs flags) then (
4764         let name = "guestfs_" ^ shortname in
4765         pr "=head2 %s\n\n" name;
4766         pr " ";
4767         generate_prototype ~extern:false ~handle:"handle" name style;
4768         pr "\n\n";
4769         pr "%s\n\n" longdesc;
4770         (match fst style with
4771          | RErr ->
4772              pr "This function returns 0 on success or -1 on error.\n\n"
4773          | RInt _ ->
4774              pr "On error this function returns -1.\n\n"
4775          | RInt64 _ ->
4776              pr "On error this function returns -1.\n\n"
4777          | RBool _ ->
4778              pr "This function returns a C truth value on success or -1 on error.\n\n"
4779          | RConstString _ ->
4780              pr "This function returns a string, or NULL on error.
4781 The string is owned by the guest handle and must I<not> be freed.\n\n"
4782          | RConstOptString _ ->
4783              pr "This function returns a string which may be NULL.
4784 There is way to return an error from this function.
4785 The string is owned by the guest handle and must I<not> be freed.\n\n"
4786          | RString _ ->
4787              pr "This function returns a string, or NULL on error.
4788 I<The caller must free the returned string after use>.\n\n"
4789          | RStringList _ ->
4790              pr "This function returns a NULL-terminated array of strings
4791 (like L<environ(3)>), or NULL if there was an error.
4792 I<The caller must free the strings and the array after use>.\n\n"
4793          | RStruct (_, typ) ->
4794              pr "This function returns a C<struct guestfs_%s *>,
4795 or NULL if there was an error.
4796 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4797          | RStructList (_, typ) ->
4798              pr "This function returns a C<struct guestfs_%s_list *>
4799 (see E<lt>guestfs-structs.hE<gt>),
4800 or NULL if there was an error.
4801 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4802          | RHashtable _ ->
4803              pr "This function returns a NULL-terminated array of
4804 strings, or NULL if there was an error.
4805 The array of strings will always have length C<2n+1>, where
4806 C<n> keys and values alternate, followed by the trailing NULL entry.
4807 I<The caller must free the strings and the array after use>.\n\n"
4808          | RBufferOut _ ->
4809              pr "This function returns a buffer, or NULL on error.
4810 The size of the returned buffer is written to C<*size_r>.
4811 I<The caller must free the returned buffer after use>.\n\n"
4812         );
4813         if List.mem ProtocolLimitWarning flags then
4814           pr "%s\n\n" protocol_limit_warning;
4815         if List.mem DangerWillRobinson flags then
4816           pr "%s\n\n" danger_will_robinson;
4817         match deprecation_notice flags with
4818         | None -> ()
4819         | Some txt -> pr "%s\n\n" txt
4820       )
4821   ) all_functions_sorted
4822
4823 and generate_structs_pod () =
4824   (* Structs documentation. *)
4825   List.iter (
4826     fun (typ, cols) ->
4827       pr "=head2 guestfs_%s\n" typ;
4828       pr "\n";
4829       pr " struct guestfs_%s {\n" typ;
4830       List.iter (
4831         function
4832         | name, FChar -> pr "   char %s;\n" name
4833         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4834         | name, FInt32 -> pr "   int32_t %s;\n" name
4835         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4836         | name, FInt64 -> pr "   int64_t %s;\n" name
4837         | name, FString -> pr "   char *%s;\n" name
4838         | name, FBuffer ->
4839             pr "   /* The next two fields describe a byte array. */\n";
4840             pr "   uint32_t %s_len;\n" name;
4841             pr "   char *%s;\n" name
4842         | name, FUUID ->
4843             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4844             pr "   char %s[32];\n" name
4845         | name, FOptPercent ->
4846             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4847             pr "   float %s;\n" name
4848       ) cols;
4849       pr " };\n";
4850       pr " \n";
4851       pr " struct guestfs_%s_list {\n" typ;
4852       pr "   uint32_t len; /* Number of elements in list. */\n";
4853       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4854       pr " };\n";
4855       pr " \n";
4856       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4857       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4858         typ typ;
4859       pr "\n"
4860   ) structs
4861
4862 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4863  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4864  *
4865  * We have to use an underscore instead of a dash because otherwise
4866  * rpcgen generates incorrect code.
4867  *
4868  * This header is NOT exported to clients, but see also generate_structs_h.
4869  *)
4870 and generate_xdr () =
4871   generate_header CStyle LGPLv2;
4872
4873   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4874   pr "typedef string str<>;\n";
4875   pr "\n";
4876
4877   (* Internal structures. *)
4878   List.iter (
4879     function
4880     | typ, cols ->
4881         pr "struct guestfs_int_%s {\n" typ;
4882         List.iter (function
4883                    | name, FChar -> pr "  char %s;\n" name
4884                    | name, FString -> pr "  string %s<>;\n" name
4885                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4886                    | name, FUUID -> pr "  opaque %s[32];\n" name
4887                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4888                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4889                    | name, FOptPercent -> pr "  float %s;\n" name
4890                   ) cols;
4891         pr "};\n";
4892         pr "\n";
4893         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4894         pr "\n";
4895   ) structs;
4896
4897   List.iter (
4898     fun (shortname, style, _, _, _, _, _) ->
4899       let name = "guestfs_" ^ shortname in
4900
4901       (match snd style with
4902        | [] -> ()
4903        | args ->
4904            pr "struct %s_args {\n" name;
4905            List.iter (
4906              function
4907              | Pathname n | Device n | Dev_or_Path n | String n ->
4908                  pr "  string %s<>;\n" n
4909              | OptString n -> pr "  str *%s;\n" n
4910              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4911              | Bool n -> pr "  bool %s;\n" n
4912              | Int n -> pr "  int %s;\n" n
4913              | Int64 n -> pr "  hyper %s;\n" n
4914              | FileIn _ | FileOut _ -> ()
4915            ) args;
4916            pr "};\n\n"
4917       );
4918       (match fst style with
4919        | RErr -> ()
4920        | RInt n ->
4921            pr "struct %s_ret {\n" name;
4922            pr "  int %s;\n" n;
4923            pr "};\n\n"
4924        | RInt64 n ->
4925            pr "struct %s_ret {\n" name;
4926            pr "  hyper %s;\n" n;
4927            pr "};\n\n"
4928        | RBool n ->
4929            pr "struct %s_ret {\n" name;
4930            pr "  bool %s;\n" n;
4931            pr "};\n\n"
4932        | RConstString _ | RConstOptString _ ->
4933            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4934        | RString n ->
4935            pr "struct %s_ret {\n" name;
4936            pr "  string %s<>;\n" n;
4937            pr "};\n\n"
4938        | RStringList n ->
4939            pr "struct %s_ret {\n" name;
4940            pr "  str %s<>;\n" n;
4941            pr "};\n\n"
4942        | RStruct (n, typ) ->
4943            pr "struct %s_ret {\n" name;
4944            pr "  guestfs_int_%s %s;\n" typ n;
4945            pr "};\n\n"
4946        | RStructList (n, typ) ->
4947            pr "struct %s_ret {\n" name;
4948            pr "  guestfs_int_%s_list %s;\n" typ n;
4949            pr "};\n\n"
4950        | RHashtable n ->
4951            pr "struct %s_ret {\n" name;
4952            pr "  str %s<>;\n" n;
4953            pr "};\n\n"
4954        | RBufferOut n ->
4955            pr "struct %s_ret {\n" name;
4956            pr "  opaque %s<>;\n" n;
4957            pr "};\n\n"
4958       );
4959   ) daemon_functions;
4960
4961   (* Table of procedure numbers. *)
4962   pr "enum guestfs_procedure {\n";
4963   List.iter (
4964     fun (shortname, _, proc_nr, _, _, _, _) ->
4965       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4966   ) daemon_functions;
4967   pr "  GUESTFS_PROC_NR_PROCS\n";
4968   pr "};\n";
4969   pr "\n";
4970
4971   (* Having to choose a maximum message size is annoying for several
4972    * reasons (it limits what we can do in the API), but it (a) makes
4973    * the protocol a lot simpler, and (b) provides a bound on the size
4974    * of the daemon which operates in limited memory space.  For large
4975    * file transfers you should use FTP.
4976    *)
4977   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4978   pr "\n";
4979
4980   (* Message header, etc. *)
4981   pr "\
4982 /* The communication protocol is now documented in the guestfs(3)
4983  * manpage.
4984  */
4985
4986 const GUESTFS_PROGRAM = 0x2000F5F5;
4987 const GUESTFS_PROTOCOL_VERSION = 1;
4988
4989 /* These constants must be larger than any possible message length. */
4990 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4991 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4992
4993 enum guestfs_message_direction {
4994   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4995   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4996 };
4997
4998 enum guestfs_message_status {
4999   GUESTFS_STATUS_OK = 0,
5000   GUESTFS_STATUS_ERROR = 1
5001 };
5002
5003 const GUESTFS_ERROR_LEN = 256;
5004
5005 struct guestfs_message_error {
5006   string error_message<GUESTFS_ERROR_LEN>;
5007 };
5008
5009 struct guestfs_message_header {
5010   unsigned prog;                     /* GUESTFS_PROGRAM */
5011   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5012   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5013   guestfs_message_direction direction;
5014   unsigned serial;                   /* message serial number */
5015   guestfs_message_status status;
5016 };
5017
5018 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5019
5020 struct guestfs_chunk {
5021   int cancel;                        /* if non-zero, transfer is cancelled */
5022   /* data size is 0 bytes if the transfer has finished successfully */
5023   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5024 };
5025 "
5026
5027 (* Generate the guestfs-structs.h file. *)
5028 and generate_structs_h () =
5029   generate_header CStyle LGPLv2;
5030
5031   (* This is a public exported header file containing various
5032    * structures.  The structures are carefully written to have
5033    * exactly the same in-memory format as the XDR structures that
5034    * we use on the wire to the daemon.  The reason for creating
5035    * copies of these structures here is just so we don't have to
5036    * export the whole of guestfs_protocol.h (which includes much
5037    * unrelated and XDR-dependent stuff that we don't want to be
5038    * public, or required by clients).
5039    *
5040    * To reiterate, we will pass these structures to and from the
5041    * client with a simple assignment or memcpy, so the format
5042    * must be identical to what rpcgen / the RFC defines.
5043    *)
5044
5045   (* Public structures. *)
5046   List.iter (
5047     fun (typ, cols) ->
5048       pr "struct guestfs_%s {\n" typ;
5049       List.iter (
5050         function
5051         | name, FChar -> pr "  char %s;\n" name
5052         | name, FString -> pr "  char *%s;\n" name
5053         | name, FBuffer ->
5054             pr "  uint32_t %s_len;\n" name;
5055             pr "  char *%s;\n" name
5056         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5057         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5058         | name, FInt32 -> pr "  int32_t %s;\n" name
5059         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5060         | name, FInt64 -> pr "  int64_t %s;\n" name
5061         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5062       ) cols;
5063       pr "};\n";
5064       pr "\n";
5065       pr "struct guestfs_%s_list {\n" typ;
5066       pr "  uint32_t len;\n";
5067       pr "  struct guestfs_%s *val;\n" typ;
5068       pr "};\n";
5069       pr "\n";
5070       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5071       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5072       pr "\n"
5073   ) structs
5074
5075 (* Generate the guestfs-actions.h file. *)
5076 and generate_actions_h () =
5077   generate_header CStyle LGPLv2;
5078   List.iter (
5079     fun (shortname, style, _, _, _, _, _) ->
5080       let name = "guestfs_" ^ shortname in
5081       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5082         name style
5083   ) all_functions
5084
5085 (* Generate the guestfs-internal-actions.h file. *)
5086 and generate_internal_actions_h () =
5087   generate_header CStyle LGPLv2;
5088   List.iter (
5089     fun (shortname, style, _, _, _, _, _) ->
5090       let name = "guestfs__" ^ shortname in
5091       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5092         name style
5093   ) non_daemon_functions
5094
5095 (* Generate the client-side dispatch stubs. *)
5096 and generate_client_actions () =
5097   generate_header CStyle LGPLv2;
5098
5099   pr "\
5100 #include <stdio.h>
5101 #include <stdlib.h>
5102 #include <stdint.h>
5103 #include <inttypes.h>
5104
5105 #include \"guestfs.h\"
5106 #include \"guestfs-internal.h\"
5107 #include \"guestfs-internal-actions.h\"
5108 #include \"guestfs_protocol.h\"
5109
5110 #define error guestfs_error
5111 //#define perrorf guestfs_perrorf
5112 #define safe_malloc guestfs_safe_malloc
5113 #define safe_realloc guestfs_safe_realloc
5114 //#define safe_strdup guestfs_safe_strdup
5115 #define safe_memdup guestfs_safe_memdup
5116
5117 /* Check the return message from a call for validity. */
5118 static int
5119 check_reply_header (guestfs_h *g,
5120                     const struct guestfs_message_header *hdr,
5121                     unsigned int proc_nr, unsigned int serial)
5122 {
5123   if (hdr->prog != GUESTFS_PROGRAM) {
5124     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5125     return -1;
5126   }
5127   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5128     error (g, \"wrong protocol version (%%d/%%d)\",
5129            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5130     return -1;
5131   }
5132   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5133     error (g, \"unexpected message direction (%%d/%%d)\",
5134            hdr->direction, GUESTFS_DIRECTION_REPLY);
5135     return -1;
5136   }
5137   if (hdr->proc != proc_nr) {
5138     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5139     return -1;
5140   }
5141   if (hdr->serial != serial) {
5142     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5143     return -1;
5144   }
5145
5146   return 0;
5147 }
5148
5149 /* Check we are in the right state to run a high-level action. */
5150 static int
5151 check_state (guestfs_h *g, const char *caller)
5152 {
5153   if (!guestfs__is_ready (g)) {
5154     if (guestfs__is_config (g) || guestfs__is_launching (g))
5155       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5156         caller);
5157     else
5158       error (g, \"%%s called from the wrong state, %%d != READY\",
5159         caller, guestfs__get_state (g));
5160     return -1;
5161   }
5162   return 0;
5163 }
5164
5165 ";
5166
5167   (* Generate code to generate guestfish call traces. *)
5168   let trace_call shortname style =
5169     pr "  if (guestfs__get_trace (g)) {\n";
5170
5171     let needs_i =
5172       List.exists (function
5173                    | StringList _ | DeviceList _ -> true
5174                    | _ -> false) (snd style) in
5175     if needs_i then (
5176       pr "    int i;\n";
5177       pr "\n"
5178     );
5179
5180     pr "    printf (\"%s\");\n" shortname;
5181     List.iter (
5182       function
5183       | String n                        (* strings *)
5184       | Device n
5185       | Pathname n
5186       | Dev_or_Path n
5187       | FileIn n
5188       | FileOut n ->
5189           (* guestfish doesn't support string escaping, so neither do we *)
5190           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5191       | OptString n ->                  (* string option *)
5192           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5193           pr "    else printf (\" null\");\n"
5194       | StringList n
5195       | DeviceList n ->                 (* string list *)
5196           pr "    putchar (' ');\n";
5197           pr "    putchar ('\"');\n";
5198           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5199           pr "      if (i > 0) putchar (' ');\n";
5200           pr "      fputs (%s[i], stdout);\n" n;
5201           pr "    }\n";
5202           pr "    putchar ('\"');\n";
5203       | Bool n ->                       (* boolean *)
5204           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5205       | Int n ->                        (* int *)
5206           pr "    printf (\" %%d\", %s);\n" n
5207       | Int64 n ->
5208           pr "    printf (\" %%\" PRIi64, %s);\n" n
5209     ) (snd style);
5210     pr "    putchar ('\\n');\n";
5211     pr "  }\n";
5212     pr "\n";
5213   in
5214
5215   (* For non-daemon functions, generate a wrapper around each function. *)
5216   List.iter (
5217     fun (shortname, style, _, _, _, _, _) ->
5218       let name = "guestfs_" ^ shortname in
5219
5220       generate_prototype ~extern:false ~semicolon:false ~newline:true
5221         ~handle:"g" name style;
5222       pr "{\n";
5223       trace_call shortname style;
5224       pr "  return guestfs__%s " shortname;
5225       generate_c_call_args ~handle:"g" style;
5226       pr ";\n";
5227       pr "}\n";
5228       pr "\n"
5229   ) non_daemon_functions;
5230
5231   (* Client-side stubs for each function. *)
5232   List.iter (
5233     fun (shortname, style, _, _, _, _, _) ->
5234       let name = "guestfs_" ^ shortname in
5235
5236       (* Generate the action stub. *)
5237       generate_prototype ~extern:false ~semicolon:false ~newline:true
5238         ~handle:"g" name style;
5239
5240       let error_code =
5241         match fst style with
5242         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5243         | RConstString _ | RConstOptString _ ->
5244             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5245         | RString _ | RStringList _
5246         | RStruct _ | RStructList _
5247         | RHashtable _ | RBufferOut _ ->
5248             "NULL" in
5249
5250       pr "{\n";
5251
5252       (match snd style with
5253        | [] -> ()
5254        | _ -> pr "  struct %s_args args;\n" name
5255       );
5256
5257       pr "  guestfs_message_header hdr;\n";
5258       pr "  guestfs_message_error err;\n";
5259       let has_ret =
5260         match fst style with
5261         | RErr -> false
5262         | RConstString _ | RConstOptString _ ->
5263             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5264         | RInt _ | RInt64 _
5265         | RBool _ | RString _ | RStringList _
5266         | RStruct _ | RStructList _
5267         | RHashtable _ | RBufferOut _ ->
5268             pr "  struct %s_ret ret;\n" name;
5269             true in
5270
5271       pr "  int serial;\n";
5272       pr "  int r;\n";
5273       pr "\n";
5274       trace_call shortname style;
5275       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5276       pr "  guestfs___set_busy (g);\n";
5277       pr "\n";
5278
5279       (* Send the main header and arguments. *)
5280       (match snd style with
5281        | [] ->
5282            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5283              (String.uppercase shortname)
5284        | args ->
5285            List.iter (
5286              function
5287              | Pathname n | Device n | Dev_or_Path n | String n ->
5288                  pr "  args.%s = (char *) %s;\n" n n
5289              | OptString n ->
5290                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5291              | StringList n | DeviceList n ->
5292                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5293                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5294              | Bool n ->
5295                  pr "  args.%s = %s;\n" n n
5296              | Int n ->
5297                  pr "  args.%s = %s;\n" n n
5298              | Int64 n ->
5299                  pr "  args.%s = %s;\n" n n
5300              | FileIn _ | FileOut _ -> ()
5301            ) args;
5302            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5303              (String.uppercase shortname);
5304            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5305              name;
5306       );
5307       pr "  if (serial == -1) {\n";
5308       pr "    guestfs___end_busy (g);\n";
5309       pr "    return %s;\n" error_code;
5310       pr "  }\n";
5311       pr "\n";
5312
5313       (* Send any additional files (FileIn) requested. *)
5314       let need_read_reply_label = ref false in
5315       List.iter (
5316         function
5317         | FileIn n ->
5318             pr "  r = guestfs___send_file (g, %s);\n" n;
5319             pr "  if (r == -1) {\n";
5320             pr "    guestfs___end_busy (g);\n";
5321             pr "    return %s;\n" error_code;
5322             pr "  }\n";
5323             pr "  if (r == -2) /* daemon cancelled */\n";
5324             pr "    goto read_reply;\n";
5325             need_read_reply_label := true;
5326             pr "\n";
5327         | _ -> ()
5328       ) (snd style);
5329
5330       (* Wait for the reply from the remote end. *)
5331       if !need_read_reply_label then pr " read_reply:\n";
5332       pr "  memset (&hdr, 0, sizeof hdr);\n";
5333       pr "  memset (&err, 0, sizeof err);\n";
5334       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5335       pr "\n";
5336       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5337       if not has_ret then
5338         pr "NULL, NULL"
5339       else
5340         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5341       pr ");\n";
5342
5343       pr "  if (r == -1) {\n";
5344       pr "    guestfs___end_busy (g);\n";
5345       pr "    return %s;\n" error_code;
5346       pr "  }\n";
5347       pr "\n";
5348
5349       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5350         (String.uppercase shortname);
5351       pr "    guestfs___end_busy (g);\n";
5352       pr "    return %s;\n" error_code;
5353       pr "  }\n";
5354       pr "\n";
5355
5356       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5357       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5358       pr "    free (err.error_message);\n";
5359       pr "    guestfs___end_busy (g);\n";
5360       pr "    return %s;\n" error_code;
5361       pr "  }\n";
5362       pr "\n";
5363
5364       (* Expecting to receive further files (FileOut)? *)
5365       List.iter (
5366         function
5367         | FileOut n ->
5368             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5369             pr "    guestfs___end_busy (g);\n";
5370             pr "    return %s;\n" error_code;
5371             pr "  }\n";
5372             pr "\n";
5373         | _ -> ()
5374       ) (snd style);
5375
5376       pr "  guestfs___end_busy (g);\n";
5377
5378       (match fst style with
5379        | RErr -> pr "  return 0;\n"
5380        | RInt n | RInt64 n | RBool n ->
5381            pr "  return ret.%s;\n" n
5382        | RConstString _ | RConstOptString _ ->
5383            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5384        | RString n ->
5385            pr "  return ret.%s; /* caller will free */\n" n
5386        | RStringList n | RHashtable n ->
5387            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5388            pr "  ret.%s.%s_val =\n" n n;
5389            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5390            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5391              n n;
5392            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5393            pr "  return ret.%s.%s_val;\n" n n
5394        | RStruct (n, _) ->
5395            pr "  /* caller will free this */\n";
5396            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5397        | RStructList (n, _) ->
5398            pr "  /* caller will free this */\n";
5399            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5400        | RBufferOut n ->
5401            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5402            pr "   * _val might be NULL here.  To make the API saner for\n";
5403            pr "   * callers, we turn this case into a unique pointer (using\n";
5404            pr "   * malloc(1)).\n";
5405            pr "   */\n";
5406            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5407            pr "    *size_r = ret.%s.%s_len;\n" n n;
5408            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5409            pr "  } else {\n";
5410            pr "    free (ret.%s.%s_val);\n" n n;
5411            pr "    char *p = safe_malloc (g, 1);\n";
5412            pr "    *size_r = ret.%s.%s_len;\n" n n;
5413            pr "    return p;\n";
5414            pr "  }\n";
5415       );
5416
5417       pr "}\n\n"
5418   ) daemon_functions;
5419
5420   (* Functions to free structures. *)
5421   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5422   pr " * structure format is identical to the XDR format.  See note in\n";
5423   pr " * generator.ml.\n";
5424   pr " */\n";
5425   pr "\n";
5426
5427   List.iter (
5428     fun (typ, _) ->
5429       pr "void\n";
5430       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5431       pr "{\n";
5432       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5433       pr "  free (x);\n";
5434       pr "}\n";
5435       pr "\n";
5436
5437       pr "void\n";
5438       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5439       pr "{\n";
5440       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5441       pr "  free (x);\n";
5442       pr "}\n";
5443       pr "\n";
5444
5445   ) structs;
5446
5447 (* Generate daemon/actions.h. *)
5448 and generate_daemon_actions_h () =
5449   generate_header CStyle GPLv2;
5450
5451   pr "#include \"../src/guestfs_protocol.h\"\n";
5452   pr "\n";
5453
5454   List.iter (
5455     fun (name, style, _, _, _, _, _) ->
5456       generate_prototype
5457         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5458         name style;
5459   ) daemon_functions
5460
5461 (* Generate the server-side stubs. *)
5462 and generate_daemon_actions () =
5463   generate_header CStyle GPLv2;
5464
5465   pr "#include <config.h>\n";
5466   pr "\n";
5467   pr "#include <stdio.h>\n";
5468   pr "#include <stdlib.h>\n";
5469   pr "#include <string.h>\n";
5470   pr "#include <inttypes.h>\n";
5471   pr "#include <rpc/types.h>\n";
5472   pr "#include <rpc/xdr.h>\n";
5473   pr "\n";
5474   pr "#include \"daemon.h\"\n";
5475   pr "#include \"c-ctype.h\"\n";
5476   pr "#include \"../src/guestfs_protocol.h\"\n";
5477   pr "#include \"actions.h\"\n";
5478   pr "\n";
5479
5480   List.iter (
5481     fun (name, style, _, _, _, _, _) ->
5482       (* Generate server-side stubs. *)
5483       pr "static void %s_stub (XDR *xdr_in)\n" name;
5484       pr "{\n";
5485       let error_code =
5486         match fst style with
5487         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5488         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5489         | RBool _ -> pr "  int r;\n"; "-1"
5490         | RConstString _ | RConstOptString _ ->
5491             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5492         | RString _ -> pr "  char *r;\n"; "NULL"
5493         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5494         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5495         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5496         | RBufferOut _ ->
5497             pr "  size_t size = 1;\n";
5498             pr "  char *r;\n";
5499             "NULL" in
5500
5501       (match snd style with
5502        | [] -> ()
5503        | args ->
5504            pr "  struct guestfs_%s_args args;\n" name;
5505            List.iter (
5506              function
5507              | Device n | Dev_or_Path n
5508              | Pathname n
5509              | String n -> ()
5510              | OptString n -> pr "  char *%s;\n" n
5511              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5512              | Bool n -> pr "  int %s;\n" n
5513              | Int n -> pr "  int %s;\n" n
5514              | Int64 n -> pr "  int64_t %s;\n" n
5515              | FileIn _ | FileOut _ -> ()
5516            ) args
5517       );
5518       pr "\n";
5519
5520       (match snd style with
5521        | [] -> ()
5522        | args ->
5523            pr "  memset (&args, 0, sizeof args);\n";
5524            pr "\n";
5525            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5526            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5527            pr "    return;\n";
5528            pr "  }\n";
5529            let pr_args n =
5530              pr "  char *%s = args.%s;\n" n n
5531            in
5532            let pr_list_handling_code n =
5533              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5534              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5535              pr "  if (%s == NULL) {\n" n;
5536              pr "    reply_with_perror (\"realloc\");\n";
5537              pr "    goto done;\n";
5538              pr "  }\n";
5539              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5540              pr "  args.%s.%s_val = %s;\n" n n n;
5541            in
5542            List.iter (
5543              function
5544              | Pathname n ->
5545                  pr_args n;
5546                  pr "  ABS_PATH (%s, goto done);\n" n;
5547              | Device n ->
5548                  pr_args n;
5549                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5550              | Dev_or_Path n ->
5551                  pr_args n;
5552                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5553              | String n -> pr_args n
5554              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5555              | StringList n ->
5556                  pr_list_handling_code n;
5557              | DeviceList n ->
5558                  pr_list_handling_code n;
5559                  pr "  /* Ensure that each is a device,\n";
5560                  pr "   * and perform device name translation. */\n";
5561                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5562                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5563                  pr "  }\n";
5564              | Bool n -> pr "  %s = args.%s;\n" n n
5565              | Int n -> pr "  %s = args.%s;\n" n n
5566              | Int64 n -> pr "  %s = args.%s;\n" n n
5567              | FileIn _ | FileOut _ -> ()
5568            ) args;
5569            pr "\n"
5570       );
5571
5572
5573       (* this is used at least for do_equal *)
5574       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5575         (* Emit NEED_ROOT just once, even when there are two or
5576            more Pathname args *)
5577         pr "  NEED_ROOT (goto done);\n";
5578       );
5579
5580       (* Don't want to call the impl with any FileIn or FileOut
5581        * parameters, since these go "outside" the RPC protocol.
5582        *)
5583       let args' =
5584         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5585           (snd style) in
5586       pr "  r = do_%s " name;
5587       generate_c_call_args (fst style, args');
5588       pr ";\n";
5589
5590       (match fst style with
5591        | RErr | RInt _ | RInt64 _ | RBool _
5592        | RConstString _ | RConstOptString _
5593        | RString _ | RStringList _ | RHashtable _
5594        | RStruct (_, _) | RStructList (_, _) ->
5595            pr "  if (r == %s)\n" error_code;
5596            pr "    /* do_%s has already called reply_with_error */\n" name;
5597            pr "    goto done;\n";
5598            pr "\n"
5599        | RBufferOut _ ->
5600            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5601            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5602            pr "   */\n";
5603            pr "  if (size == 1 && r == %s)\n" error_code;
5604            pr "    /* do_%s has already called reply_with_error */\n" name;
5605            pr "    goto done;\n";
5606            pr "\n"
5607       );
5608
5609       (* If there are any FileOut parameters, then the impl must
5610        * send its own reply.
5611        *)
5612       let no_reply =
5613         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5614       if no_reply then
5615         pr "  /* do_%s has already sent a reply */\n" name
5616       else (
5617         match fst style with
5618         | RErr -> pr "  reply (NULL, NULL);\n"
5619         | RInt n | RInt64 n | RBool n ->
5620             pr "  struct guestfs_%s_ret ret;\n" name;
5621             pr "  ret.%s = r;\n" n;
5622             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5623               name
5624         | RConstString _ | RConstOptString _ ->
5625             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5626         | RString n ->
5627             pr "  struct guestfs_%s_ret ret;\n" name;
5628             pr "  ret.%s = r;\n" n;
5629             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5630               name;
5631             pr "  free (r);\n"
5632         | RStringList n | RHashtable n ->
5633             pr "  struct guestfs_%s_ret ret;\n" name;
5634             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5635             pr "  ret.%s.%s_val = r;\n" n n;
5636             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5637               name;
5638             pr "  free_strings (r);\n"
5639         | RStruct (n, _) ->
5640             pr "  struct guestfs_%s_ret ret;\n" name;
5641             pr "  ret.%s = *r;\n" n;
5642             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5643               name;
5644             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5645               name
5646         | RStructList (n, _) ->
5647             pr "  struct guestfs_%s_ret ret;\n" name;
5648             pr "  ret.%s = *r;\n" n;
5649             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5650               name;
5651             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5652               name
5653         | RBufferOut n ->
5654             pr "  struct guestfs_%s_ret ret;\n" name;
5655             pr "  ret.%s.%s_val = r;\n" n n;
5656             pr "  ret.%s.%s_len = size;\n" n n;
5657             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5658               name;
5659             pr "  free (r);\n"
5660       );
5661
5662       (* Free the args. *)
5663       (match snd style with
5664        | [] ->
5665            pr "done: ;\n";
5666        | _ ->
5667            pr "done:\n";
5668            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5669              name
5670       );
5671
5672       pr "}\n\n";
5673   ) daemon_functions;
5674
5675   (* Dispatch function. *)
5676   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5677   pr "{\n";
5678   pr "  switch (proc_nr) {\n";
5679
5680   List.iter (
5681     fun (name, style, _, _, _, _, _) ->
5682       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5683       pr "      %s_stub (xdr_in);\n" name;
5684       pr "      break;\n"
5685   ) daemon_functions;
5686
5687   pr "    default:\n";
5688   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";
5689   pr "  }\n";
5690   pr "}\n";
5691   pr "\n";
5692
5693   (* LVM columns and tokenization functions. *)
5694   (* XXX This generates crap code.  We should rethink how we
5695    * do this parsing.
5696    *)
5697   List.iter (
5698     function
5699     | typ, cols ->
5700         pr "static const char *lvm_%s_cols = \"%s\";\n"
5701           typ (String.concat "," (List.map fst cols));
5702         pr "\n";
5703
5704         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5705         pr "{\n";
5706         pr "  char *tok, *p, *next;\n";
5707         pr "  int i, j;\n";
5708         pr "\n";
5709         (*
5710           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5711           pr "\n";
5712         *)
5713         pr "  if (!str) {\n";
5714         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5715         pr "    return -1;\n";
5716         pr "  }\n";
5717         pr "  if (!*str || c_isspace (*str)) {\n";
5718         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5719         pr "    return -1;\n";
5720         pr "  }\n";
5721         pr "  tok = str;\n";
5722         List.iter (
5723           fun (name, coltype) ->
5724             pr "  if (!tok) {\n";
5725             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5726             pr "    return -1;\n";
5727             pr "  }\n";
5728             pr "  p = strchrnul (tok, ',');\n";
5729             pr "  if (*p) next = p+1; else next = NULL;\n";
5730             pr "  *p = '\\0';\n";
5731             (match coltype with
5732              | FString ->
5733                  pr "  r->%s = strdup (tok);\n" name;
5734                  pr "  if (r->%s == NULL) {\n" name;
5735                  pr "    perror (\"strdup\");\n";
5736                  pr "    return -1;\n";
5737                  pr "  }\n"
5738              | FUUID ->
5739                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5740                  pr "    if (tok[j] == '\\0') {\n";
5741                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5742                  pr "      return -1;\n";
5743                  pr "    } else if (tok[j] != '-')\n";
5744                  pr "      r->%s[i++] = tok[j];\n" name;
5745                  pr "  }\n";
5746              | FBytes ->
5747                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5748                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5749                  pr "    return -1;\n";
5750                  pr "  }\n";
5751              | FInt64 ->
5752                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5753                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5754                  pr "    return -1;\n";
5755                  pr "  }\n";
5756              | FOptPercent ->
5757                  pr "  if (tok[0] == '\\0')\n";
5758                  pr "    r->%s = -1;\n" name;
5759                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5760                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5761                  pr "    return -1;\n";
5762                  pr "  }\n";
5763              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5764                  assert false (* can never be an LVM column *)
5765             );
5766             pr "  tok = next;\n";
5767         ) cols;
5768
5769         pr "  if (tok != NULL) {\n";
5770         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5771         pr "    return -1;\n";
5772         pr "  }\n";
5773         pr "  return 0;\n";
5774         pr "}\n";
5775         pr "\n";
5776
5777         pr "guestfs_int_lvm_%s_list *\n" typ;
5778         pr "parse_command_line_%ss (void)\n" typ;
5779         pr "{\n";
5780         pr "  char *out, *err;\n";
5781         pr "  char *p, *pend;\n";
5782         pr "  int r, i;\n";
5783         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5784         pr "  void *newp;\n";
5785         pr "\n";
5786         pr "  ret = malloc (sizeof *ret);\n";
5787         pr "  if (!ret) {\n";
5788         pr "    reply_with_perror (\"malloc\");\n";
5789         pr "    return NULL;\n";
5790         pr "  }\n";
5791         pr "\n";
5792         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5793         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5794         pr "\n";
5795         pr "  r = command (&out, &err,\n";
5796         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5797         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5798         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5799         pr "  if (r == -1) {\n";
5800         pr "    reply_with_error (\"%%s\", err);\n";
5801         pr "    free (out);\n";
5802         pr "    free (err);\n";
5803         pr "    free (ret);\n";
5804         pr "    return NULL;\n";
5805         pr "  }\n";
5806         pr "\n";
5807         pr "  free (err);\n";
5808         pr "\n";
5809         pr "  /* Tokenize each line of the output. */\n";
5810         pr "  p = out;\n";
5811         pr "  i = 0;\n";
5812         pr "  while (p) {\n";
5813         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5814         pr "    if (pend) {\n";
5815         pr "      *pend = '\\0';\n";
5816         pr "      pend++;\n";
5817         pr "    }\n";
5818         pr "\n";
5819         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5820         pr "      p++;\n";
5821         pr "\n";
5822         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5823         pr "      p = pend;\n";
5824         pr "      continue;\n";
5825         pr "    }\n";
5826         pr "\n";
5827         pr "    /* Allocate some space to store this next entry. */\n";
5828         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5829         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5830         pr "    if (newp == NULL) {\n";
5831         pr "      reply_with_perror (\"realloc\");\n";
5832         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5833         pr "      free (ret);\n";
5834         pr "      free (out);\n";
5835         pr "      return NULL;\n";
5836         pr "    }\n";
5837         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5838         pr "\n";
5839         pr "    /* Tokenize the next entry. */\n";
5840         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5841         pr "    if (r == -1) {\n";
5842         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5843         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5844         pr "      free (ret);\n";
5845         pr "      free (out);\n";
5846         pr "      return NULL;\n";
5847         pr "    }\n";
5848         pr "\n";
5849         pr "    ++i;\n";
5850         pr "    p = pend;\n";
5851         pr "  }\n";
5852         pr "\n";
5853         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5854         pr "\n";
5855         pr "  free (out);\n";
5856         pr "  return ret;\n";
5857         pr "}\n"
5858
5859   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5860
5861 (* Generate a list of function names, for debugging in the daemon.. *)
5862 and generate_daemon_names () =
5863   generate_header CStyle GPLv2;
5864
5865   pr "#include <config.h>\n";
5866   pr "\n";
5867   pr "#include \"daemon.h\"\n";
5868   pr "\n";
5869
5870   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5871   pr "const char *function_names[] = {\n";
5872   List.iter (
5873     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5874   ) daemon_functions;
5875   pr "};\n";
5876
5877 (* Generate the tests. *)
5878 and generate_tests () =
5879   generate_header CStyle GPLv2;
5880
5881   pr "\
5882 #include <stdio.h>
5883 #include <stdlib.h>
5884 #include <string.h>
5885 #include <unistd.h>
5886 #include <sys/types.h>
5887 #include <fcntl.h>
5888
5889 #include \"guestfs.h\"
5890 #include \"guestfs-internal.h\"
5891
5892 static guestfs_h *g;
5893 static int suppress_error = 0;
5894
5895 static void print_error (guestfs_h *g, void *data, const char *msg)
5896 {
5897   if (!suppress_error)
5898     fprintf (stderr, \"%%s\\n\", msg);
5899 }
5900
5901 /* FIXME: nearly identical code appears in fish.c */
5902 static void print_strings (char *const *argv)
5903 {
5904   int argc;
5905
5906   for (argc = 0; argv[argc] != NULL; ++argc)
5907     printf (\"\\t%%s\\n\", argv[argc]);
5908 }
5909
5910 /*
5911 static void print_table (char const *const *argv)
5912 {
5913   int i;
5914
5915   for (i = 0; argv[i] != NULL; i += 2)
5916     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5917 }
5918 */
5919
5920 ";
5921
5922   (* Generate a list of commands which are not tested anywhere. *)
5923   pr "static void no_test_warnings (void)\n";
5924   pr "{\n";
5925
5926   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5927   List.iter (
5928     fun (_, _, _, _, tests, _, _) ->
5929       let tests = filter_map (
5930         function
5931         | (_, (Always|If _|Unless _), test) -> Some test
5932         | (_, Disabled, _) -> None
5933       ) tests in
5934       let seq = List.concat (List.map seq_of_test tests) in
5935       let cmds_tested = List.map List.hd seq in
5936       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5937   ) all_functions;
5938
5939   List.iter (
5940     fun (name, _, _, _, _, _, _) ->
5941       if not (Hashtbl.mem hash name) then
5942         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5943   ) all_functions;
5944
5945   pr "}\n";
5946   pr "\n";
5947
5948   (* Generate the actual tests.  Note that we generate the tests
5949    * in reverse order, deliberately, so that (in general) the
5950    * newest tests run first.  This makes it quicker and easier to
5951    * debug them.
5952    *)
5953   let test_names =
5954     List.map (
5955       fun (name, _, _, _, tests, _, _) ->
5956         mapi (generate_one_test name) tests
5957     ) (List.rev all_functions) in
5958   let test_names = List.concat test_names in
5959   let nr_tests = List.length test_names in
5960
5961   pr "\
5962 int main (int argc, char *argv[])
5963 {
5964   char c = 0;
5965   unsigned long int n_failed = 0;
5966   const char *filename;
5967   int fd;
5968   int nr_tests, test_num = 0;
5969
5970   setbuf (stdout, NULL);
5971
5972   no_test_warnings ();
5973
5974   g = guestfs_create ();
5975   if (g == NULL) {
5976     printf (\"guestfs_create FAILED\\n\");
5977     exit (1);
5978   }
5979
5980   guestfs_set_error_handler (g, print_error, NULL);
5981
5982   guestfs_set_path (g, \"../appliance\");
5983
5984   filename = \"test1.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 = \"test2.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   filename = \"test3.img\";
6041   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6042   if (fd == -1) {
6043     perror (filename);
6044     exit (1);
6045   }
6046   if (lseek (fd, %d, SEEK_SET) == -1) {
6047     perror (\"lseek\");
6048     close (fd);
6049     unlink (filename);
6050     exit (1);
6051   }
6052   if (write (fd, &c, 1) == -1) {
6053     perror (\"write\");
6054     close (fd);
6055     unlink (filename);
6056     exit (1);
6057   }
6058   if (close (fd) == -1) {
6059     perror (filename);
6060     unlink (filename);
6061     exit (1);
6062   }
6063   if (guestfs_add_drive (g, filename) == -1) {
6064     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6065     exit (1);
6066   }
6067
6068   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6069     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6070     exit (1);
6071   }
6072
6073   if (guestfs_launch (g) == -1) {
6074     printf (\"guestfs_launch FAILED\\n\");
6075     exit (1);
6076   }
6077
6078   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6079   alarm (600);
6080
6081   /* Cancel previous alarm. */
6082   alarm (0);
6083
6084   nr_tests = %d;
6085
6086 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6087
6088   iteri (
6089     fun i test_name ->
6090       pr "  test_num++;\n";
6091       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6092       pr "  if (%s () == -1) {\n" test_name;
6093       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6094       pr "    n_failed++;\n";
6095       pr "  }\n";
6096   ) test_names;
6097   pr "\n";
6098
6099   pr "  guestfs_close (g);\n";
6100   pr "  unlink (\"test1.img\");\n";
6101   pr "  unlink (\"test2.img\");\n";
6102   pr "  unlink (\"test3.img\");\n";
6103   pr "\n";
6104
6105   pr "  if (n_failed > 0) {\n";
6106   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6107   pr "    exit (1);\n";
6108   pr "  }\n";
6109   pr "\n";
6110
6111   pr "  exit (0);\n";
6112   pr "}\n"
6113
6114 and generate_one_test name i (init, prereq, test) =
6115   let test_name = sprintf "test_%s_%d" name i in
6116
6117   pr "\
6118 static int %s_skip (void)
6119 {
6120   const char *str;
6121
6122   str = getenv (\"TEST_ONLY\");
6123   if (str)
6124     return strstr (str, \"%s\") == NULL;
6125   str = getenv (\"SKIP_%s\");
6126   if (str && STREQ (str, \"1\")) return 1;
6127   str = getenv (\"SKIP_TEST_%s\");
6128   if (str && STREQ (str, \"1\")) return 1;
6129   return 0;
6130 }
6131
6132 " test_name name (String.uppercase test_name) (String.uppercase name);
6133
6134   (match prereq with
6135    | Disabled | Always -> ()
6136    | If code | Unless code ->
6137        pr "static int %s_prereq (void)\n" test_name;
6138        pr "{\n";
6139        pr "  %s\n" code;
6140        pr "}\n";
6141        pr "\n";
6142   );
6143
6144   pr "\
6145 static int %s (void)
6146 {
6147   if (%s_skip ()) {
6148     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6149     return 0;
6150   }
6151
6152 " test_name test_name test_name;
6153
6154   (match prereq with
6155    | Disabled ->
6156        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6157    | If _ ->
6158        pr "  if (! %s_prereq ()) {\n" test_name;
6159        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6160        pr "    return 0;\n";
6161        pr "  }\n";
6162        pr "\n";
6163        generate_one_test_body name i test_name init test;
6164    | Unless _ ->
6165        pr "  if (%s_prereq ()) {\n" test_name;
6166        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6167        pr "    return 0;\n";
6168        pr "  }\n";
6169        pr "\n";
6170        generate_one_test_body name i test_name init test;
6171    | Always ->
6172        generate_one_test_body name i test_name init test
6173   );
6174
6175   pr "  return 0;\n";
6176   pr "}\n";
6177   pr "\n";
6178   test_name
6179
6180 and generate_one_test_body name i test_name init test =
6181   (match init with
6182    | InitNone (* XXX at some point, InitNone and InitEmpty became
6183                * folded together as the same thing.  Really we should
6184                * make InitNone do nothing at all, but the tests may
6185                * need to be checked to make sure this is OK.
6186                *)
6187    | InitEmpty ->
6188        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6189        List.iter (generate_test_command_call test_name)
6190          [["blockdev_setrw"; "/dev/sda"];
6191           ["umount_all"];
6192           ["lvm_remove_all"]]
6193    | InitPartition ->
6194        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6195        List.iter (generate_test_command_call test_name)
6196          [["blockdev_setrw"; "/dev/sda"];
6197           ["umount_all"];
6198           ["lvm_remove_all"];
6199           ["part_disk"; "/dev/sda"; "mbr"]]
6200    | InitBasicFS ->
6201        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6202        List.iter (generate_test_command_call test_name)
6203          [["blockdev_setrw"; "/dev/sda"];
6204           ["umount_all"];
6205           ["lvm_remove_all"];
6206           ["part_disk"; "/dev/sda"; "mbr"];
6207           ["mkfs"; "ext2"; "/dev/sda1"];
6208           ["mount"; "/dev/sda1"; "/"]]
6209    | InitBasicFSonLVM ->
6210        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6211          test_name;
6212        List.iter (generate_test_command_call test_name)
6213          [["blockdev_setrw"; "/dev/sda"];
6214           ["umount_all"];
6215           ["lvm_remove_all"];
6216           ["part_disk"; "/dev/sda"; "mbr"];
6217           ["pvcreate"; "/dev/sda1"];
6218           ["vgcreate"; "VG"; "/dev/sda1"];
6219           ["lvcreate"; "LV"; "VG"; "8"];
6220           ["mkfs"; "ext2"; "/dev/VG/LV"];
6221           ["mount"; "/dev/VG/LV"; "/"]]
6222    | InitISOFS ->
6223        pr "  /* InitISOFS for %s */\n" test_name;
6224        List.iter (generate_test_command_call test_name)
6225          [["blockdev_setrw"; "/dev/sda"];
6226           ["umount_all"];
6227           ["lvm_remove_all"];
6228           ["mount_ro"; "/dev/sdd"; "/"]]
6229   );
6230
6231   let get_seq_last = function
6232     | [] ->
6233         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6234           test_name
6235     | seq ->
6236         let seq = List.rev seq in
6237         List.rev (List.tl seq), List.hd seq
6238   in
6239
6240   match test with
6241   | TestRun seq ->
6242       pr "  /* TestRun for %s (%d) */\n" name i;
6243       List.iter (generate_test_command_call test_name) seq
6244   | TestOutput (seq, expected) ->
6245       pr "  /* TestOutput for %s (%d) */\n" name i;
6246       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6247       let seq, last = get_seq_last seq in
6248       let test () =
6249         pr "    if (STRNEQ (r, expected)) {\n";
6250         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
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   | TestOutputList (seq, expected) ->
6257       pr "  /* TestOutputList 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 "      if (STRNEQ (r[%d], expected)) {\n" i;
6270             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6271             pr "        return -1;\n";
6272             pr "      }\n";
6273             pr "    }\n"
6274         ) expected;
6275         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6276         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6277           test_name;
6278         pr "      print_strings (r);\n";
6279         pr "      return -1;\n";
6280         pr "    }\n"
6281       in
6282       List.iter (generate_test_command_call test_name) seq;
6283       generate_test_command_call ~test test_name last
6284   | TestOutputListOfDevices (seq, expected) ->
6285       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6286       let seq, last = get_seq_last seq in
6287       let test () =
6288         iteri (
6289           fun i str ->
6290             pr "    if (!r[%d]) {\n" i;
6291             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6292             pr "      print_strings (r);\n";
6293             pr "      return -1;\n";
6294             pr "    }\n";
6295             pr "    {\n";
6296             pr "      const char *expected = \"%s\";\n" (c_quote str);
6297             pr "      r[%d][5] = 's';\n" i;
6298             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6299             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6300             pr "        return -1;\n";
6301             pr "      }\n";
6302             pr "    }\n"
6303         ) expected;
6304         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6305         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6306           test_name;
6307         pr "      print_strings (r);\n";
6308         pr "      return -1;\n";
6309         pr "    }\n"
6310       in
6311       List.iter (generate_test_command_call test_name) seq;
6312       generate_test_command_call ~test test_name last
6313   | TestOutputInt (seq, expected) ->
6314       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6315       let seq, last = get_seq_last seq in
6316       let test () =
6317         pr "    if (r != %d) {\n" expected;
6318         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6319           test_name expected;
6320         pr "               (int) r);\n";
6321         pr "      return -1;\n";
6322         pr "    }\n"
6323       in
6324       List.iter (generate_test_command_call test_name) seq;
6325       generate_test_command_call ~test test_name last
6326   | TestOutputIntOp (seq, op, expected) ->
6327       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6328       let seq, last = get_seq_last seq in
6329       let test () =
6330         pr "    if (! (r %s %d)) {\n" op expected;
6331         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6332           test_name op expected;
6333         pr "               (int) r);\n";
6334         pr "      return -1;\n";
6335         pr "    }\n"
6336       in
6337       List.iter (generate_test_command_call test_name) seq;
6338       generate_test_command_call ~test test_name last
6339   | TestOutputTrue seq ->
6340       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6341       let seq, last = get_seq_last seq in
6342       let test () =
6343         pr "    if (!r) {\n";
6344         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6345           test_name;
6346         pr "      return -1;\n";
6347         pr "    }\n"
6348       in
6349       List.iter (generate_test_command_call test_name) seq;
6350       generate_test_command_call ~test test_name last
6351   | TestOutputFalse seq ->
6352       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6353       let seq, last = get_seq_last seq in
6354       let test () =
6355         pr "    if (r) {\n";
6356         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6357           test_name;
6358         pr "      return -1;\n";
6359         pr "    }\n"
6360       in
6361       List.iter (generate_test_command_call test_name) seq;
6362       generate_test_command_call ~test test_name last
6363   | TestOutputLength (seq, expected) ->
6364       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6365       let seq, last = get_seq_last seq in
6366       let test () =
6367         pr "    int j;\n";
6368         pr "    for (j = 0; j < %d; ++j)\n" expected;
6369         pr "      if (r[j] == NULL) {\n";
6370         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6371           test_name;
6372         pr "        print_strings (r);\n";
6373         pr "        return -1;\n";
6374         pr "      }\n";
6375         pr "    if (r[j] != NULL) {\n";
6376         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6377           test_name;
6378         pr "      print_strings (r);\n";
6379         pr "      return -1;\n";
6380         pr "    }\n"
6381       in
6382       List.iter (generate_test_command_call test_name) seq;
6383       generate_test_command_call ~test test_name last
6384   | TestOutputBuffer (seq, expected) ->
6385       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6386       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6387       let seq, last = get_seq_last seq in
6388       let len = String.length expected in
6389       let test () =
6390         pr "    if (size != %d) {\n" len;
6391         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6392         pr "      return -1;\n";
6393         pr "    }\n";
6394         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6395         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6396         pr "      return -1;\n";
6397         pr "    }\n"
6398       in
6399       List.iter (generate_test_command_call test_name) seq;
6400       generate_test_command_call ~test test_name last
6401   | TestOutputStruct (seq, checks) ->
6402       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6403       let seq, last = get_seq_last seq in
6404       let test () =
6405         List.iter (
6406           function
6407           | CompareWithInt (field, expected) ->
6408               pr "    if (r->%s != %d) {\n" field expected;
6409               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6410                 test_name field expected;
6411               pr "               (int) r->%s);\n" field;
6412               pr "      return -1;\n";
6413               pr "    }\n"
6414           | CompareWithIntOp (field, op, expected) ->
6415               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6416               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6417                 test_name field op expected;
6418               pr "               (int) r->%s);\n" field;
6419               pr "      return -1;\n";
6420               pr "    }\n"
6421           | CompareWithString (field, expected) ->
6422               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6423               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6424                 test_name field expected;
6425               pr "               r->%s);\n" field;
6426               pr "      return -1;\n";
6427               pr "    }\n"
6428           | CompareFieldsIntEq (field1, field2) ->
6429               pr "    if (r->%s != r->%s) {\n" field1 field2;
6430               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6431                 test_name field1 field2;
6432               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6433               pr "      return -1;\n";
6434               pr "    }\n"
6435           | CompareFieldsStrEq (field1, field2) ->
6436               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6437               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6438                 test_name field1 field2;
6439               pr "               r->%s, r->%s);\n" field1 field2;
6440               pr "      return -1;\n";
6441               pr "    }\n"
6442         ) checks
6443       in
6444       List.iter (generate_test_command_call test_name) seq;
6445       generate_test_command_call ~test test_name last
6446   | TestLastFail seq ->
6447       pr "  /* TestLastFail for %s (%d) */\n" name i;
6448       let seq, last = get_seq_last seq in
6449       List.iter (generate_test_command_call test_name) seq;
6450       generate_test_command_call test_name ~expect_error:true last
6451
6452 (* Generate the code to run a command, leaving the result in 'r'.
6453  * If you expect to get an error then you should set expect_error:true.
6454  *)
6455 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6456   match cmd with
6457   | [] -> assert false
6458   | name :: args ->
6459       (* Look up the command to find out what args/ret it has. *)
6460       let style =
6461         try
6462           let _, style, _, _, _, _, _ =
6463             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6464           style
6465         with Not_found ->
6466           failwithf "%s: in test, command %s was not found" test_name name in
6467
6468       if List.length (snd style) <> List.length args then
6469         failwithf "%s: in test, wrong number of args given to %s"
6470           test_name name;
6471
6472       pr "  {\n";
6473
6474       List.iter (
6475         function
6476         | OptString n, "NULL" -> ()
6477         | Pathname n, arg
6478         | Device n, arg
6479         | Dev_or_Path n, arg
6480         | String n, arg
6481         | OptString n, arg ->
6482             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6483         | Int _, _
6484         | Int64 _, _
6485         | Bool _, _
6486         | FileIn _, _ | FileOut _, _ -> ()
6487         | StringList n, arg | DeviceList n, arg ->
6488             let strs = string_split " " arg in
6489             iteri (
6490               fun i str ->
6491                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6492             ) strs;
6493             pr "    const char *const %s[] = {\n" n;
6494             iteri (
6495               fun i _ -> pr "      %s_%d,\n" n i
6496             ) strs;
6497             pr "      NULL\n";
6498             pr "    };\n";
6499       ) (List.combine (snd style) args);
6500
6501       let error_code =
6502         match fst style with
6503         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6504         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6505         | RConstString _ | RConstOptString _ ->
6506             pr "    const char *r;\n"; "NULL"
6507         | RString _ -> pr "    char *r;\n"; "NULL"
6508         | RStringList _ | RHashtable _ ->
6509             pr "    char **r;\n";
6510             pr "    int i;\n";
6511             "NULL"
6512         | RStruct (_, typ) ->
6513             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6514         | RStructList (_, typ) ->
6515             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6516         | RBufferOut _ ->
6517             pr "    char *r;\n";
6518             pr "    size_t size;\n";
6519             "NULL" in
6520
6521       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6522       pr "    r = guestfs_%s (g" name;
6523
6524       (* Generate the parameters. *)
6525       List.iter (
6526         function
6527         | OptString _, "NULL" -> pr ", NULL"
6528         | Pathname n, _
6529         | Device n, _ | Dev_or_Path n, _
6530         | String n, _
6531         | OptString n, _ ->
6532             pr ", %s" n
6533         | FileIn _, arg | FileOut _, arg ->
6534             pr ", \"%s\"" (c_quote arg)
6535         | StringList n, _ | DeviceList n, _ ->
6536             pr ", (char **) %s" n
6537         | Int _, arg ->
6538             let i =
6539               try int_of_string arg
6540               with Failure "int_of_string" ->
6541                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6542             pr ", %d" i
6543         | Int64 _, arg ->
6544             let i =
6545               try Int64.of_string arg
6546               with Failure "int_of_string" ->
6547                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6548             pr ", %Ld" i
6549         | Bool _, arg ->
6550             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6551       ) (List.combine (snd style) args);
6552
6553       (match fst style with
6554        | RBufferOut _ -> pr ", &size"
6555        | _ -> ()
6556       );
6557
6558       pr ");\n";
6559
6560       if not expect_error then
6561         pr "    if (r == %s)\n" error_code
6562       else
6563         pr "    if (r != %s)\n" error_code;
6564       pr "      return -1;\n";
6565
6566       (* Insert the test code. *)
6567       (match test with
6568        | None -> ()
6569        | Some f -> f ()
6570       );
6571
6572       (match fst style with
6573        | RErr | RInt _ | RInt64 _ | RBool _
6574        | RConstString _ | RConstOptString _ -> ()
6575        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6576        | RStringList _ | RHashtable _ ->
6577            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6578            pr "      free (r[i]);\n";
6579            pr "    free (r);\n"
6580        | RStruct (_, typ) ->
6581            pr "    guestfs_free_%s (r);\n" typ
6582        | RStructList (_, typ) ->
6583            pr "    guestfs_free_%s_list (r);\n" typ
6584       );
6585
6586       pr "  }\n"
6587
6588 and c_quote str =
6589   let str = replace_str str "\r" "\\r" in
6590   let str = replace_str str "\n" "\\n" in
6591   let str = replace_str str "\t" "\\t" in
6592   let str = replace_str str "\000" "\\0" in
6593   str
6594
6595 (* Generate a lot of different functions for guestfish. *)
6596 and generate_fish_cmds () =
6597   generate_header CStyle GPLv2;
6598
6599   let all_functions =
6600     List.filter (
6601       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6602     ) all_functions in
6603   let all_functions_sorted =
6604     List.filter (
6605       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6606     ) all_functions_sorted in
6607
6608   pr "#include <stdio.h>\n";
6609   pr "#include <stdlib.h>\n";
6610   pr "#include <string.h>\n";
6611   pr "#include <inttypes.h>\n";
6612   pr "\n";
6613   pr "#include <guestfs.h>\n";
6614   pr "#include \"c-ctype.h\"\n";
6615   pr "#include \"fish.h\"\n";
6616   pr "\n";
6617
6618   (* list_commands function, which implements guestfish -h *)
6619   pr "void list_commands (void)\n";
6620   pr "{\n";
6621   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6622   pr "  list_builtin_commands ();\n";
6623   List.iter (
6624     fun (name, _, _, flags, _, shortdesc, _) ->
6625       let name = replace_char name '_' '-' in
6626       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6627         name shortdesc
6628   ) all_functions_sorted;
6629   pr "  printf (\"    %%s\\n\",";
6630   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6631   pr "}\n";
6632   pr "\n";
6633
6634   (* display_command function, which implements guestfish -h cmd *)
6635   pr "void display_command (const char *cmd)\n";
6636   pr "{\n";
6637   List.iter (
6638     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6639       let name2 = replace_char name '_' '-' in
6640       let alias =
6641         try find_map (function FishAlias n -> Some n | _ -> None) flags
6642         with Not_found -> name in
6643       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6644       let synopsis =
6645         match snd style with
6646         | [] -> name2
6647         | args ->
6648             sprintf "%s %s"
6649               name2 (String.concat " " (List.map name_of_argt args)) in
6650
6651       let warnings =
6652         if List.mem ProtocolLimitWarning flags then
6653           ("\n\n" ^ protocol_limit_warning)
6654         else "" in
6655
6656       (* For DangerWillRobinson commands, we should probably have
6657        * guestfish prompt before allowing you to use them (especially
6658        * in interactive mode). XXX
6659        *)
6660       let warnings =
6661         warnings ^
6662           if List.mem DangerWillRobinson flags then
6663             ("\n\n" ^ danger_will_robinson)
6664           else "" in
6665
6666       let warnings =
6667         warnings ^
6668           match deprecation_notice flags with
6669           | None -> ""
6670           | Some txt -> "\n\n" ^ txt in
6671
6672       let describe_alias =
6673         if name <> alias then
6674           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6675         else "" in
6676
6677       pr "  if (";
6678       pr "STRCASEEQ (cmd, \"%s\")" name;
6679       if name <> name2 then
6680         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6681       if name <> alias then
6682         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6683       pr ")\n";
6684       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6685         name2 shortdesc
6686         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6687          "=head1 DESCRIPTION\n\n" ^
6688          longdesc ^ warnings ^ describe_alias);
6689       pr "  else\n"
6690   ) all_functions;
6691   pr "    display_builtin_command (cmd);\n";
6692   pr "}\n";
6693   pr "\n";
6694
6695   let emit_print_list_function typ =
6696     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6697       typ typ typ;
6698     pr "{\n";
6699     pr "  unsigned int i;\n";
6700     pr "\n";
6701     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6702     pr "    printf (\"[%%d] = {\\n\", i);\n";
6703     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6704     pr "    printf (\"}\\n\");\n";
6705     pr "  }\n";
6706     pr "}\n";
6707     pr "\n";
6708   in
6709
6710   (* print_* functions *)
6711   List.iter (
6712     fun (typ, cols) ->
6713       let needs_i =
6714         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6715
6716       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6717       pr "{\n";
6718       if needs_i then (
6719         pr "  unsigned int i;\n";
6720         pr "\n"
6721       );
6722       List.iter (
6723         function
6724         | name, FString ->
6725             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6726         | name, FUUID ->
6727             pr "  printf (\"%%s%s: \", indent);\n" name;
6728             pr "  for (i = 0; i < 32; ++i)\n";
6729             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6730             pr "  printf (\"\\n\");\n"
6731         | name, FBuffer ->
6732             pr "  printf (\"%%s%s: \", indent);\n" name;
6733             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6734             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6735             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6736             pr "    else\n";
6737             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6738             pr "  printf (\"\\n\");\n"
6739         | name, (FUInt64|FBytes) ->
6740             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6741               name typ name
6742         | name, FInt64 ->
6743             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6744               name typ name
6745         | name, FUInt32 ->
6746             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6747               name typ name
6748         | name, FInt32 ->
6749             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6750               name typ name
6751         | name, FChar ->
6752             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6753               name typ name
6754         | name, FOptPercent ->
6755             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6756               typ name name typ name;
6757             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6758       ) cols;
6759       pr "}\n";
6760       pr "\n";
6761   ) structs;
6762
6763   (* Emit a print_TYPE_list function definition only if that function is used. *)
6764   List.iter (
6765     function
6766     | typ, (RStructListOnly | RStructAndList) ->
6767         (* generate the function for typ *)
6768         emit_print_list_function typ
6769     | typ, _ -> () (* empty *)
6770   ) (rstructs_used_by all_functions);
6771
6772   (* Emit a print_TYPE function definition only if that function is used. *)
6773   List.iter (
6774     function
6775     | typ, (RStructOnly | RStructAndList) ->
6776         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6777         pr "{\n";
6778         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6779         pr "}\n";
6780         pr "\n";
6781     | typ, _ -> () (* empty *)
6782   ) (rstructs_used_by all_functions);
6783
6784   (* run_<action> actions *)
6785   List.iter (
6786     fun (name, style, _, flags, _, _, _) ->
6787       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6788       pr "{\n";
6789       (match fst style with
6790        | RErr
6791        | RInt _
6792        | RBool _ -> pr "  int r;\n"
6793        | RInt64 _ -> pr "  int64_t r;\n"
6794        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6795        | RString _ -> pr "  char *r;\n"
6796        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6797        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6798        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6799        | RBufferOut _ ->
6800            pr "  char *r;\n";
6801            pr "  size_t size;\n";
6802       );
6803       List.iter (
6804         function
6805         | Device n
6806         | String n
6807         | OptString n
6808         | FileIn n
6809         | FileOut n -> pr "  const char *%s;\n" n
6810         | Pathname n
6811         | Dev_or_Path n -> pr "  char *%s;\n" n
6812         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6813         | Bool n -> pr "  int %s;\n" n
6814         | Int n -> pr "  int %s;\n" n
6815         | Int64 n -> pr "  int64_t %s;\n" n
6816       ) (snd style);
6817
6818       (* Check and convert parameters. *)
6819       let argc_expected = List.length (snd style) in
6820       pr "  if (argc != %d) {\n" argc_expected;
6821       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6822         argc_expected;
6823       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6824       pr "    return -1;\n";
6825       pr "  }\n";
6826       iteri (
6827         fun i ->
6828           function
6829           | Device name
6830           | String name ->
6831               pr "  %s = argv[%d];\n" name i
6832           | Pathname name
6833           | Dev_or_Path name ->
6834               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6835               pr "  if (%s == NULL) return -1;\n" name
6836           | OptString name ->
6837               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6838                 name i i
6839           | FileIn name ->
6840               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6841                 name i i
6842           | FileOut name ->
6843               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6844                 name i i
6845           | StringList name | DeviceList name ->
6846               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6847               pr "  if (%s == NULL) return -1;\n" name;
6848           | Bool name ->
6849               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6850           | Int name ->
6851               pr "  %s = atoi (argv[%d]);\n" name i
6852           | Int64 name ->
6853               pr "  %s = atoll (argv[%d]);\n" name i
6854       ) (snd style);
6855
6856       (* Call C API function. *)
6857       let fn =
6858         try find_map (function FishAction n -> Some n | _ -> None) flags
6859         with Not_found -> sprintf "guestfs_%s" name in
6860       pr "  r = %s " fn;
6861       generate_c_call_args ~handle:"g" style;
6862       pr ";\n";
6863
6864       List.iter (
6865         function
6866         | Device name | String name
6867         | OptString name | FileIn name | FileOut name | Bool name
6868         | Int name | Int64 name -> ()
6869         | Pathname name | Dev_or_Path name ->
6870             pr "  free (%s);\n" name
6871         | StringList name | DeviceList name ->
6872             pr "  free_strings (%s);\n" name
6873       ) (snd style);
6874
6875       (* Check return value for errors and display command results. *)
6876       (match fst style with
6877        | RErr -> pr "  return r;\n"
6878        | RInt _ ->
6879            pr "  if (r == -1) return -1;\n";
6880            pr "  printf (\"%%d\\n\", r);\n";
6881            pr "  return 0;\n"
6882        | RInt64 _ ->
6883            pr "  if (r == -1) return -1;\n";
6884            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6885            pr "  return 0;\n"
6886        | RBool _ ->
6887            pr "  if (r == -1) return -1;\n";
6888            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6889            pr "  return 0;\n"
6890        | RConstString _ ->
6891            pr "  if (r == NULL) return -1;\n";
6892            pr "  printf (\"%%s\\n\", r);\n";
6893            pr "  return 0;\n"
6894        | RConstOptString _ ->
6895            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6896            pr "  return 0;\n"
6897        | RString _ ->
6898            pr "  if (r == NULL) return -1;\n";
6899            pr "  printf (\"%%s\\n\", r);\n";
6900            pr "  free (r);\n";
6901            pr "  return 0;\n"
6902        | RStringList _ ->
6903            pr "  if (r == NULL) return -1;\n";
6904            pr "  print_strings (r);\n";
6905            pr "  free_strings (r);\n";
6906            pr "  return 0;\n"
6907        | RStruct (_, typ) ->
6908            pr "  if (r == NULL) return -1;\n";
6909            pr "  print_%s (r);\n" typ;
6910            pr "  guestfs_free_%s (r);\n" typ;
6911            pr "  return 0;\n"
6912        | RStructList (_, typ) ->
6913            pr "  if (r == NULL) return -1;\n";
6914            pr "  print_%s_list (r);\n" typ;
6915            pr "  guestfs_free_%s_list (r);\n" typ;
6916            pr "  return 0;\n"
6917        | RHashtable _ ->
6918            pr "  if (r == NULL) return -1;\n";
6919            pr "  print_table (r);\n";
6920            pr "  free_strings (r);\n";
6921            pr "  return 0;\n"
6922        | RBufferOut _ ->
6923            pr "  if (r == NULL) return -1;\n";
6924            pr "  fwrite (r, size, 1, stdout);\n";
6925            pr "  free (r);\n";
6926            pr "  return 0;\n"
6927       );
6928       pr "}\n";
6929       pr "\n"
6930   ) all_functions;
6931
6932   (* run_action function *)
6933   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6934   pr "{\n";
6935   List.iter (
6936     fun (name, _, _, flags, _, _, _) ->
6937       let name2 = replace_char name '_' '-' in
6938       let alias =
6939         try find_map (function FishAlias n -> Some n | _ -> None) flags
6940         with Not_found -> name in
6941       pr "  if (";
6942       pr "STRCASEEQ (cmd, \"%s\")" name;
6943       if name <> name2 then
6944         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6945       if name <> alias then
6946         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6947       pr ")\n";
6948       pr "    return run_%s (cmd, argc, argv);\n" name;
6949       pr "  else\n";
6950   ) all_functions;
6951   pr "    {\n";
6952   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6953   pr "      return -1;\n";
6954   pr "    }\n";
6955   pr "  return 0;\n";
6956   pr "}\n";
6957   pr "\n"
6958
6959 (* Readline completion for guestfish. *)
6960 and generate_fish_completion () =
6961   generate_header CStyle GPLv2;
6962
6963   let all_functions =
6964     List.filter (
6965       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6966     ) all_functions in
6967
6968   pr "\
6969 #include <config.h>
6970
6971 #include <stdio.h>
6972 #include <stdlib.h>
6973 #include <string.h>
6974
6975 #ifdef HAVE_LIBREADLINE
6976 #include <readline/readline.h>
6977 #endif
6978
6979 #include \"fish.h\"
6980
6981 #ifdef HAVE_LIBREADLINE
6982
6983 static const char *const commands[] = {
6984   BUILTIN_COMMANDS_FOR_COMPLETION,
6985 ";
6986
6987   (* Get the commands, including the aliases.  They don't need to be
6988    * sorted - the generator() function just does a dumb linear search.
6989    *)
6990   let commands =
6991     List.map (
6992       fun (name, _, _, flags, _, _, _) ->
6993         let name2 = replace_char name '_' '-' in
6994         let alias =
6995           try find_map (function FishAlias n -> Some n | _ -> None) flags
6996           with Not_found -> name in
6997
6998         if name <> alias then [name2; alias] else [name2]
6999     ) all_functions in
7000   let commands = List.flatten commands in
7001
7002   List.iter (pr "  \"%s\",\n") commands;
7003
7004   pr "  NULL
7005 };
7006
7007 static char *
7008 generator (const char *text, int state)
7009 {
7010   static int index, len;
7011   const char *name;
7012
7013   if (!state) {
7014     index = 0;
7015     len = strlen (text);
7016   }
7017
7018   rl_attempted_completion_over = 1;
7019
7020   while ((name = commands[index]) != NULL) {
7021     index++;
7022     if (STRCASEEQLEN (name, text, len))
7023       return strdup (name);
7024   }
7025
7026   return NULL;
7027 }
7028
7029 #endif /* HAVE_LIBREADLINE */
7030
7031 char **do_completion (const char *text, int start, int end)
7032 {
7033   char **matches = NULL;
7034
7035 #ifdef HAVE_LIBREADLINE
7036   rl_completion_append_character = ' ';
7037
7038   if (start == 0)
7039     matches = rl_completion_matches (text, generator);
7040   else if (complete_dest_paths)
7041     matches = rl_completion_matches (text, complete_dest_paths_generator);
7042 #endif
7043
7044   return matches;
7045 }
7046 ";
7047
7048 (* Generate the POD documentation for guestfish. *)
7049 and generate_fish_actions_pod () =
7050   let all_functions_sorted =
7051     List.filter (
7052       fun (_, _, _, flags, _, _, _) ->
7053         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7054     ) all_functions_sorted in
7055
7056   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7057
7058   List.iter (
7059     fun (name, style, _, flags, _, _, longdesc) ->
7060       let longdesc =
7061         Str.global_substitute rex (
7062           fun s ->
7063             let sub =
7064               try Str.matched_group 1 s
7065               with Not_found ->
7066                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7067             "C<" ^ replace_char sub '_' '-' ^ ">"
7068         ) longdesc in
7069       let name = replace_char name '_' '-' in
7070       let alias =
7071         try find_map (function FishAlias n -> Some n | _ -> None) flags
7072         with Not_found -> name in
7073
7074       pr "=head2 %s" name;
7075       if name <> alias then
7076         pr " | %s" alias;
7077       pr "\n";
7078       pr "\n";
7079       pr " %s" name;
7080       List.iter (
7081         function
7082         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7083         | OptString n -> pr " %s" n
7084         | StringList n | DeviceList n -> pr " '%s ...'" n
7085         | Bool _ -> pr " true|false"
7086         | Int n -> pr " %s" n
7087         | Int64 n -> pr " %s" n
7088         | FileIn n | FileOut n -> pr " (%s|-)" n
7089       ) (snd style);
7090       pr "\n";
7091       pr "\n";
7092       pr "%s\n\n" longdesc;
7093
7094       if List.exists (function FileIn _ | FileOut _ -> true
7095                       | _ -> false) (snd style) then
7096         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7097
7098       if List.mem ProtocolLimitWarning flags then
7099         pr "%s\n\n" protocol_limit_warning;
7100
7101       if List.mem DangerWillRobinson flags then
7102         pr "%s\n\n" danger_will_robinson;
7103
7104       match deprecation_notice flags with
7105       | None -> ()
7106       | Some txt -> pr "%s\n\n" txt
7107   ) all_functions_sorted
7108
7109 (* Generate a C function prototype. *)
7110 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7111     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7112     ?(prefix = "")
7113     ?handle name style =
7114   if extern then pr "extern ";
7115   if static then pr "static ";
7116   (match fst style with
7117    | RErr -> pr "int "
7118    | RInt _ -> pr "int "
7119    | RInt64 _ -> pr "int64_t "
7120    | RBool _ -> pr "int "
7121    | RConstString _ | RConstOptString _ -> pr "const char *"
7122    | RString _ | RBufferOut _ -> pr "char *"
7123    | RStringList _ | RHashtable _ -> pr "char **"
7124    | RStruct (_, typ) ->
7125        if not in_daemon then pr "struct guestfs_%s *" typ
7126        else pr "guestfs_int_%s *" typ
7127    | RStructList (_, typ) ->
7128        if not in_daemon then pr "struct guestfs_%s_list *" typ
7129        else pr "guestfs_int_%s_list *" typ
7130   );
7131   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7132   pr "%s%s (" prefix name;
7133   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7134     pr "void"
7135   else (
7136     let comma = ref false in
7137     (match handle with
7138      | None -> ()
7139      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7140     );
7141     let next () =
7142       if !comma then (
7143         if single_line then pr ", " else pr ",\n\t\t"
7144       );
7145       comma := true
7146     in
7147     List.iter (
7148       function
7149       | Pathname n
7150       | Device n | Dev_or_Path n
7151       | String n
7152       | OptString n ->
7153           next ();
7154           pr "const char *%s" n
7155       | StringList n | DeviceList n ->
7156           next ();
7157           pr "char *const *%s" n
7158       | Bool n -> next (); pr "int %s" n
7159       | Int n -> next (); pr "int %s" n
7160       | Int64 n -> next (); pr "int64_t %s" n
7161       | FileIn n
7162       | FileOut n ->
7163           if not in_daemon then (next (); pr "const char *%s" n)
7164     ) (snd style);
7165     if is_RBufferOut then (next (); pr "size_t *size_r");
7166   );
7167   pr ")";
7168   if semicolon then pr ";";
7169   if newline then pr "\n"
7170
7171 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7172 and generate_c_call_args ?handle ?(decl = false) style =
7173   pr "(";
7174   let comma = ref false in
7175   let next () =
7176     if !comma then pr ", ";
7177     comma := true
7178   in
7179   (match handle with
7180    | None -> ()
7181    | Some handle -> pr "%s" handle; comma := true
7182   );
7183   List.iter (
7184     fun arg ->
7185       next ();
7186       pr "%s" (name_of_argt arg)
7187   ) (snd style);
7188   (* For RBufferOut calls, add implicit &size parameter. *)
7189   if not decl then (
7190     match fst style with
7191     | RBufferOut _ ->
7192         next ();
7193         pr "&size"
7194     | _ -> ()
7195   );
7196   pr ")"
7197
7198 (* Generate the OCaml bindings interface. *)
7199 and generate_ocaml_mli () =
7200   generate_header OCamlStyle LGPLv2;
7201
7202   pr "\
7203 (** For API documentation you should refer to the C API
7204     in the guestfs(3) manual page.  The OCaml API uses almost
7205     exactly the same calls. *)
7206
7207 type t
7208 (** A [guestfs_h] handle. *)
7209
7210 exception Error of string
7211 (** This exception is raised when there is an error. *)
7212
7213 exception Handle_closed of string
7214 (** This exception is raised if you use a {!Guestfs.t} handle
7215     after calling {!close} on it.  The string is the name of
7216     the function. *)
7217
7218 val create : unit -> t
7219 (** Create a {!Guestfs.t} handle. *)
7220
7221 val close : t -> unit
7222 (** Close the {!Guestfs.t} handle and free up all resources used
7223     by it immediately.
7224
7225     Handles are closed by the garbage collector when they become
7226     unreferenced, but callers can call this in order to provide
7227     predictable cleanup. *)
7228
7229 ";
7230   generate_ocaml_structure_decls ();
7231
7232   (* The actions. *)
7233   List.iter (
7234     fun (name, style, _, _, _, shortdesc, _) ->
7235       generate_ocaml_prototype name style;
7236       pr "(** %s *)\n" shortdesc;
7237       pr "\n"
7238   ) all_functions_sorted
7239
7240 (* Generate the OCaml bindings implementation. *)
7241 and generate_ocaml_ml () =
7242   generate_header OCamlStyle LGPLv2;
7243
7244   pr "\
7245 type t
7246
7247 exception Error of string
7248 exception Handle_closed of string
7249
7250 external create : unit -> t = \"ocaml_guestfs_create\"
7251 external close : t -> unit = \"ocaml_guestfs_close\"
7252
7253 (* Give the exceptions names, so they can be raised from the C code. *)
7254 let () =
7255   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7256   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7257
7258 ";
7259
7260   generate_ocaml_structure_decls ();
7261
7262   (* The actions. *)
7263   List.iter (
7264     fun (name, style, _, _, _, shortdesc, _) ->
7265       generate_ocaml_prototype ~is_external:true name style;
7266   ) all_functions_sorted
7267
7268 (* Generate the OCaml bindings C implementation. *)
7269 and generate_ocaml_c () =
7270   generate_header CStyle LGPLv2;
7271
7272   pr "\
7273 #include <stdio.h>
7274 #include <stdlib.h>
7275 #include <string.h>
7276
7277 #include <caml/config.h>
7278 #include <caml/alloc.h>
7279 #include <caml/callback.h>
7280 #include <caml/fail.h>
7281 #include <caml/memory.h>
7282 #include <caml/mlvalues.h>
7283 #include <caml/signals.h>
7284
7285 #include <guestfs.h>
7286
7287 #include \"guestfs_c.h\"
7288
7289 /* Copy a hashtable of string pairs into an assoc-list.  We return
7290  * the list in reverse order, but hashtables aren't supposed to be
7291  * ordered anyway.
7292  */
7293 static CAMLprim value
7294 copy_table (char * const * argv)
7295 {
7296   CAMLparam0 ();
7297   CAMLlocal5 (rv, pairv, kv, vv, cons);
7298   int i;
7299
7300   rv = Val_int (0);
7301   for (i = 0; argv[i] != NULL; i += 2) {
7302     kv = caml_copy_string (argv[i]);
7303     vv = caml_copy_string (argv[i+1]);
7304     pairv = caml_alloc (2, 0);
7305     Store_field (pairv, 0, kv);
7306     Store_field (pairv, 1, vv);
7307     cons = caml_alloc (2, 0);
7308     Store_field (cons, 1, rv);
7309     rv = cons;
7310     Store_field (cons, 0, pairv);
7311   }
7312
7313   CAMLreturn (rv);
7314 }
7315
7316 ";
7317
7318   (* Struct copy functions. *)
7319
7320   let emit_ocaml_copy_list_function typ =
7321     pr "static CAMLprim value\n";
7322     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7323     pr "{\n";
7324     pr "  CAMLparam0 ();\n";
7325     pr "  CAMLlocal2 (rv, v);\n";
7326     pr "  unsigned int i;\n";
7327     pr "\n";
7328     pr "  if (%ss->len == 0)\n" typ;
7329     pr "    CAMLreturn (Atom (0));\n";
7330     pr "  else {\n";
7331     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7332     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7333     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7334     pr "      caml_modify (&Field (rv, i), v);\n";
7335     pr "    }\n";
7336     pr "    CAMLreturn (rv);\n";
7337     pr "  }\n";
7338     pr "}\n";
7339     pr "\n";
7340   in
7341
7342   List.iter (
7343     fun (typ, cols) ->
7344       let has_optpercent_col =
7345         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7346
7347       pr "static CAMLprim value\n";
7348       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7349       pr "{\n";
7350       pr "  CAMLparam0 ();\n";
7351       if has_optpercent_col then
7352         pr "  CAMLlocal3 (rv, v, v2);\n"
7353       else
7354         pr "  CAMLlocal2 (rv, v);\n";
7355       pr "\n";
7356       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7357       iteri (
7358         fun i col ->
7359           (match col with
7360            | name, FString ->
7361                pr "  v = caml_copy_string (%s->%s);\n" typ name
7362            | name, FBuffer ->
7363                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7364                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7365                  typ name typ name
7366            | name, FUUID ->
7367                pr "  v = caml_alloc_string (32);\n";
7368                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7369            | name, (FBytes|FInt64|FUInt64) ->
7370                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7371            | name, (FInt32|FUInt32) ->
7372                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7373            | name, FOptPercent ->
7374                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7375                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7376                pr "    v = caml_alloc (1, 0);\n";
7377                pr "    Store_field (v, 0, v2);\n";
7378                pr "  } else /* None */\n";
7379                pr "    v = Val_int (0);\n";
7380            | name, FChar ->
7381                pr "  v = Val_int (%s->%s);\n" typ name
7382           );
7383           pr "  Store_field (rv, %d, v);\n" i
7384       ) cols;
7385       pr "  CAMLreturn (rv);\n";
7386       pr "}\n";
7387       pr "\n";
7388   ) structs;
7389
7390   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7391   List.iter (
7392     function
7393     | typ, (RStructListOnly | RStructAndList) ->
7394         (* generate the function for typ *)
7395         emit_ocaml_copy_list_function typ
7396     | typ, _ -> () (* empty *)
7397   ) (rstructs_used_by all_functions);
7398
7399   (* The wrappers. *)
7400   List.iter (
7401     fun (name, style, _, _, _, _, _) ->
7402       pr "/* Automatically generated wrapper for function\n";
7403       pr " * ";
7404       generate_ocaml_prototype name style;
7405       pr " */\n";
7406       pr "\n";
7407
7408       let params =
7409         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7410
7411       let needs_extra_vs =
7412         match fst style with RConstOptString _ -> true | _ -> false in
7413
7414       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7415       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7416       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7417       pr "\n";
7418
7419       pr "CAMLprim value\n";
7420       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7421       List.iter (pr ", value %s") (List.tl params);
7422       pr ")\n";
7423       pr "{\n";
7424
7425       (match params with
7426        | [p1; p2; p3; p4; p5] ->
7427            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7428        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7429            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7430            pr "  CAMLxparam%d (%s);\n"
7431              (List.length rest) (String.concat ", " rest)
7432        | ps ->
7433            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7434       );
7435       if not needs_extra_vs then
7436         pr "  CAMLlocal1 (rv);\n"
7437       else
7438         pr "  CAMLlocal3 (rv, v, v2);\n";
7439       pr "\n";
7440
7441       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7442       pr "  if (g == NULL)\n";
7443       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7444       pr "\n";
7445
7446       List.iter (
7447         function
7448         | Pathname n
7449         | Device n | Dev_or_Path n
7450         | String n
7451         | FileIn n
7452         | FileOut n ->
7453             pr "  const char *%s = String_val (%sv);\n" n n
7454         | OptString n ->
7455             pr "  const char *%s =\n" n;
7456             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7457               n n
7458         | StringList n | DeviceList n ->
7459             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7460         | Bool n ->
7461             pr "  int %s = Bool_val (%sv);\n" n n
7462         | Int n ->
7463             pr "  int %s = Int_val (%sv);\n" n n
7464         | Int64 n ->
7465             pr "  int64_t %s = Int64_val (%sv);\n" n n
7466       ) (snd style);
7467       let error_code =
7468         match fst style with
7469         | RErr -> pr "  int r;\n"; "-1"
7470         | RInt _ -> pr "  int r;\n"; "-1"
7471         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7472         | RBool _ -> pr "  int r;\n"; "-1"
7473         | RConstString _ | RConstOptString _ ->
7474             pr "  const char *r;\n"; "NULL"
7475         | RString _ -> pr "  char *r;\n"; "NULL"
7476         | RStringList _ ->
7477             pr "  int i;\n";
7478             pr "  char **r;\n";
7479             "NULL"
7480         | RStruct (_, typ) ->
7481             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7482         | RStructList (_, typ) ->
7483             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7484         | RHashtable _ ->
7485             pr "  int i;\n";
7486             pr "  char **r;\n";
7487             "NULL"
7488         | RBufferOut _ ->
7489             pr "  char *r;\n";
7490             pr "  size_t size;\n";
7491             "NULL" in
7492       pr "\n";
7493
7494       pr "  caml_enter_blocking_section ();\n";
7495       pr "  r = guestfs_%s " name;
7496       generate_c_call_args ~handle:"g" style;
7497       pr ";\n";
7498       pr "  caml_leave_blocking_section ();\n";
7499
7500       List.iter (
7501         function
7502         | StringList n | DeviceList n ->
7503             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7504         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7505         | Bool _ | Int _ | Int64 _
7506         | FileIn _ | FileOut _ -> ()
7507       ) (snd style);
7508
7509       pr "  if (r == %s)\n" error_code;
7510       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7511       pr "\n";
7512
7513       (match fst style with
7514        | RErr -> pr "  rv = Val_unit;\n"
7515        | RInt _ -> pr "  rv = Val_int (r);\n"
7516        | RInt64 _ ->
7517            pr "  rv = caml_copy_int64 (r);\n"
7518        | RBool _ -> pr "  rv = Val_bool (r);\n"
7519        | RConstString _ ->
7520            pr "  rv = caml_copy_string (r);\n"
7521        | RConstOptString _ ->
7522            pr "  if (r) { /* Some string */\n";
7523            pr "    v = caml_alloc (1, 0);\n";
7524            pr "    v2 = caml_copy_string (r);\n";
7525            pr "    Store_field (v, 0, v2);\n";
7526            pr "  } else /* None */\n";
7527            pr "    v = Val_int (0);\n";
7528        | RString _ ->
7529            pr "  rv = caml_copy_string (r);\n";
7530            pr "  free (r);\n"
7531        | RStringList _ ->
7532            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7533            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7534            pr "  free (r);\n"
7535        | RStruct (_, typ) ->
7536            pr "  rv = copy_%s (r);\n" typ;
7537            pr "  guestfs_free_%s (r);\n" typ;
7538        | RStructList (_, typ) ->
7539            pr "  rv = copy_%s_list (r);\n" typ;
7540            pr "  guestfs_free_%s_list (r);\n" typ;
7541        | RHashtable _ ->
7542            pr "  rv = copy_table (r);\n";
7543            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7544            pr "  free (r);\n";
7545        | RBufferOut _ ->
7546            pr "  rv = caml_alloc_string (size);\n";
7547            pr "  memcpy (String_val (rv), r, size);\n";
7548       );
7549
7550       pr "  CAMLreturn (rv);\n";
7551       pr "}\n";
7552       pr "\n";
7553
7554       if List.length params > 5 then (
7555         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7556         pr "CAMLprim value ";
7557         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7558         pr "CAMLprim value\n";
7559         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7560         pr "{\n";
7561         pr "  return ocaml_guestfs_%s (argv[0]" name;
7562         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7563         pr ");\n";
7564         pr "}\n";
7565         pr "\n"
7566       )
7567   ) all_functions_sorted
7568
7569 and generate_ocaml_structure_decls () =
7570   List.iter (
7571     fun (typ, cols) ->
7572       pr "type %s = {\n" typ;
7573       List.iter (
7574         function
7575         | name, FString -> pr "  %s : string;\n" name
7576         | name, FBuffer -> pr "  %s : string;\n" name
7577         | name, FUUID -> pr "  %s : string;\n" name
7578         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7579         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7580         | name, FChar -> pr "  %s : char;\n" name
7581         | name, FOptPercent -> pr "  %s : float option;\n" name
7582       ) cols;
7583       pr "}\n";
7584       pr "\n"
7585   ) structs
7586
7587 and generate_ocaml_prototype ?(is_external = false) name style =
7588   if is_external then pr "external " else pr "val ";
7589   pr "%s : t -> " name;
7590   List.iter (
7591     function
7592     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7593     | OptString _ -> pr "string option -> "
7594     | StringList _ | DeviceList _ -> pr "string array -> "
7595     | Bool _ -> pr "bool -> "
7596     | Int _ -> pr "int -> "
7597     | Int64 _ -> pr "int64 -> "
7598   ) (snd style);
7599   (match fst style with
7600    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7601    | RInt _ -> pr "int"
7602    | RInt64 _ -> pr "int64"
7603    | RBool _ -> pr "bool"
7604    | RConstString _ -> pr "string"
7605    | RConstOptString _ -> pr "string option"
7606    | RString _ | RBufferOut _ -> pr "string"
7607    | RStringList _ -> pr "string array"
7608    | RStruct (_, typ) -> pr "%s" typ
7609    | RStructList (_, typ) -> pr "%s array" typ
7610    | RHashtable _ -> pr "(string * string) list"
7611   );
7612   if is_external then (
7613     pr " = ";
7614     if List.length (snd style) + 1 > 5 then
7615       pr "\"ocaml_guestfs_%s_byte\" " name;
7616     pr "\"ocaml_guestfs_%s\"" name
7617   );
7618   pr "\n"
7619
7620 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7621 and generate_perl_xs () =
7622   generate_header CStyle LGPLv2;
7623
7624   pr "\
7625 #include \"EXTERN.h\"
7626 #include \"perl.h\"
7627 #include \"XSUB.h\"
7628
7629 #include <guestfs.h>
7630
7631 #ifndef PRId64
7632 #define PRId64 \"lld\"
7633 #endif
7634
7635 static SV *
7636 my_newSVll(long long val) {
7637 #ifdef USE_64_BIT_ALL
7638   return newSViv(val);
7639 #else
7640   char buf[100];
7641   int len;
7642   len = snprintf(buf, 100, \"%%\" PRId64, val);
7643   return newSVpv(buf, len);
7644 #endif
7645 }
7646
7647 #ifndef PRIu64
7648 #define PRIu64 \"llu\"
7649 #endif
7650
7651 static SV *
7652 my_newSVull(unsigned long long val) {
7653 #ifdef USE_64_BIT_ALL
7654   return newSVuv(val);
7655 #else
7656   char buf[100];
7657   int len;
7658   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7659   return newSVpv(buf, len);
7660 #endif
7661 }
7662
7663 /* http://www.perlmonks.org/?node_id=680842 */
7664 static char **
7665 XS_unpack_charPtrPtr (SV *arg) {
7666   char **ret;
7667   AV *av;
7668   I32 i;
7669
7670   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7671     croak (\"array reference expected\");
7672
7673   av = (AV *)SvRV (arg);
7674   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7675   if (!ret)
7676     croak (\"malloc failed\");
7677
7678   for (i = 0; i <= av_len (av); i++) {
7679     SV **elem = av_fetch (av, i, 0);
7680
7681     if (!elem || !*elem)
7682       croak (\"missing element in list\");
7683
7684     ret[i] = SvPV_nolen (*elem);
7685   }
7686
7687   ret[i] = NULL;
7688
7689   return ret;
7690 }
7691
7692 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7693
7694 PROTOTYPES: ENABLE
7695
7696 guestfs_h *
7697 _create ()
7698    CODE:
7699       RETVAL = guestfs_create ();
7700       if (!RETVAL)
7701         croak (\"could not create guestfs handle\");
7702       guestfs_set_error_handler (RETVAL, NULL, NULL);
7703  OUTPUT:
7704       RETVAL
7705
7706 void
7707 DESTROY (g)
7708       guestfs_h *g;
7709  PPCODE:
7710       guestfs_close (g);
7711
7712 ";
7713
7714   List.iter (
7715     fun (name, style, _, _, _, _, _) ->
7716       (match fst style with
7717        | RErr -> pr "void\n"
7718        | RInt _ -> pr "SV *\n"
7719        | RInt64 _ -> pr "SV *\n"
7720        | RBool _ -> pr "SV *\n"
7721        | RConstString _ -> pr "SV *\n"
7722        | RConstOptString _ -> pr "SV *\n"
7723        | RString _ -> pr "SV *\n"
7724        | RBufferOut _ -> pr "SV *\n"
7725        | RStringList _
7726        | RStruct _ | RStructList _
7727        | RHashtable _ ->
7728            pr "void\n" (* all lists returned implictly on the stack *)
7729       );
7730       (* Call and arguments. *)
7731       pr "%s " name;
7732       generate_c_call_args ~handle:"g" ~decl:true style;
7733       pr "\n";
7734       pr "      guestfs_h *g;\n";
7735       iteri (
7736         fun i ->
7737           function
7738           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7739               pr "      char *%s;\n" n
7740           | OptString n ->
7741               (* http://www.perlmonks.org/?node_id=554277
7742                * Note that the implicit handle argument means we have
7743                * to add 1 to the ST(x) operator.
7744                *)
7745               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7746           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7747           | Bool n -> pr "      int %s;\n" n
7748           | Int n -> pr "      int %s;\n" n
7749           | Int64 n -> pr "      int64_t %s;\n" n
7750       ) (snd style);
7751
7752       let do_cleanups () =
7753         List.iter (
7754           function
7755           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7756           | Bool _ | Int _ | Int64 _
7757           | FileIn _ | FileOut _ -> ()
7758           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7759         ) (snd style)
7760       in
7761
7762       (* Code. *)
7763       (match fst style with
7764        | RErr ->
7765            pr "PREINIT:\n";
7766            pr "      int r;\n";
7767            pr " PPCODE:\n";
7768            pr "      r = guestfs_%s " name;
7769            generate_c_call_args ~handle:"g" style;
7770            pr ";\n";
7771            do_cleanups ();
7772            pr "      if (r == -1)\n";
7773            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7774        | RInt n
7775        | RBool n ->
7776            pr "PREINIT:\n";
7777            pr "      int %s;\n" n;
7778            pr "   CODE:\n";
7779            pr "      %s = guestfs_%s " n name;
7780            generate_c_call_args ~handle:"g" style;
7781            pr ";\n";
7782            do_cleanups ();
7783            pr "      if (%s == -1)\n" n;
7784            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7785            pr "      RETVAL = newSViv (%s);\n" n;
7786            pr " OUTPUT:\n";
7787            pr "      RETVAL\n"
7788        | RInt64 n ->
7789            pr "PREINIT:\n";
7790            pr "      int64_t %s;\n" n;
7791            pr "   CODE:\n";
7792            pr "      %s = guestfs_%s " n name;
7793            generate_c_call_args ~handle:"g" style;
7794            pr ";\n";
7795            do_cleanups ();
7796            pr "      if (%s == -1)\n" n;
7797            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7798            pr "      RETVAL = my_newSVll (%s);\n" n;
7799            pr " OUTPUT:\n";
7800            pr "      RETVAL\n"
7801        | RConstString n ->
7802            pr "PREINIT:\n";
7803            pr "      const char *%s;\n" n;
7804            pr "   CODE:\n";
7805            pr "      %s = guestfs_%s " n name;
7806            generate_c_call_args ~handle:"g" style;
7807            pr ";\n";
7808            do_cleanups ();
7809            pr "      if (%s == NULL)\n" n;
7810            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7811            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7812            pr " OUTPUT:\n";
7813            pr "      RETVAL\n"
7814        | RConstOptString n ->
7815            pr "PREINIT:\n";
7816            pr "      const char *%s;\n" n;
7817            pr "   CODE:\n";
7818            pr "      %s = guestfs_%s " n name;
7819            generate_c_call_args ~handle:"g" style;
7820            pr ";\n";
7821            do_cleanups ();
7822            pr "      if (%s == NULL)\n" n;
7823            pr "        RETVAL = &PL_sv_undef;\n";
7824            pr "      else\n";
7825            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7826            pr " OUTPUT:\n";
7827            pr "      RETVAL\n"
7828        | RString n ->
7829            pr "PREINIT:\n";
7830            pr "      char *%s;\n" n;
7831            pr "   CODE:\n";
7832            pr "      %s = guestfs_%s " n name;
7833            generate_c_call_args ~handle:"g" style;
7834            pr ";\n";
7835            do_cleanups ();
7836            pr "      if (%s == NULL)\n" n;
7837            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7838            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7839            pr "      free (%s);\n" n;
7840            pr " OUTPUT:\n";
7841            pr "      RETVAL\n"
7842        | RStringList n | RHashtable n ->
7843            pr "PREINIT:\n";
7844            pr "      char **%s;\n" n;
7845            pr "      int i, n;\n";
7846            pr " PPCODE:\n";
7847            pr "      %s = guestfs_%s " n name;
7848            generate_c_call_args ~handle:"g" style;
7849            pr ";\n";
7850            do_cleanups ();
7851            pr "      if (%s == NULL)\n" n;
7852            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7853            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7854            pr "      EXTEND (SP, n);\n";
7855            pr "      for (i = 0; i < n; ++i) {\n";
7856            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7857            pr "        free (%s[i]);\n" n;
7858            pr "      }\n";
7859            pr "      free (%s);\n" n;
7860        | RStruct (n, typ) ->
7861            let cols = cols_of_struct typ in
7862            generate_perl_struct_code typ cols name style n do_cleanups
7863        | RStructList (n, typ) ->
7864            let cols = cols_of_struct typ in
7865            generate_perl_struct_list_code typ cols name style n do_cleanups
7866        | RBufferOut n ->
7867            pr "PREINIT:\n";
7868            pr "      char *%s;\n" n;
7869            pr "      size_t size;\n";
7870            pr "   CODE:\n";
7871            pr "      %s = guestfs_%s " n name;
7872            generate_c_call_args ~handle:"g" style;
7873            pr ";\n";
7874            do_cleanups ();
7875            pr "      if (%s == NULL)\n" n;
7876            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7877            pr "      RETVAL = newSVpv (%s, size);\n" n;
7878            pr "      free (%s);\n" n;
7879            pr " OUTPUT:\n";
7880            pr "      RETVAL\n"
7881       );
7882
7883       pr "\n"
7884   ) all_functions
7885
7886 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7887   pr "PREINIT:\n";
7888   pr "      struct guestfs_%s_list *%s;\n" typ n;
7889   pr "      int i;\n";
7890   pr "      HV *hv;\n";
7891   pr " PPCODE:\n";
7892   pr "      %s = guestfs_%s " n name;
7893   generate_c_call_args ~handle:"g" style;
7894   pr ";\n";
7895   do_cleanups ();
7896   pr "      if (%s == NULL)\n" n;
7897   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7898   pr "      EXTEND (SP, %s->len);\n" n;
7899   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7900   pr "        hv = newHV ();\n";
7901   List.iter (
7902     function
7903     | name, FString ->
7904         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7905           name (String.length name) n name
7906     | name, FUUID ->
7907         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7908           name (String.length name) n name
7909     | name, FBuffer ->
7910         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7911           name (String.length name) n name n name
7912     | name, (FBytes|FUInt64) ->
7913         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7914           name (String.length name) n name
7915     | name, FInt64 ->
7916         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7917           name (String.length name) n name
7918     | name, (FInt32|FUInt32) ->
7919         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7920           name (String.length name) n name
7921     | name, FChar ->
7922         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7923           name (String.length name) n name
7924     | name, FOptPercent ->
7925         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7926           name (String.length name) n name
7927   ) cols;
7928   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7929   pr "      }\n";
7930   pr "      guestfs_free_%s_list (%s);\n" typ n
7931
7932 and generate_perl_struct_code typ cols name style n do_cleanups =
7933   pr "PREINIT:\n";
7934   pr "      struct guestfs_%s *%s;\n" typ n;
7935   pr " PPCODE:\n";
7936   pr "      %s = guestfs_%s " n name;
7937   generate_c_call_args ~handle:"g" style;
7938   pr ";\n";
7939   do_cleanups ();
7940   pr "      if (%s == NULL)\n" n;
7941   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7942   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7943   List.iter (
7944     fun ((name, _) as col) ->
7945       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7946
7947       match col with
7948       | name, FString ->
7949           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7950             n name
7951       | name, FBuffer ->
7952           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7953             n name n name
7954       | name, FUUID ->
7955           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7956             n name
7957       | name, (FBytes|FUInt64) ->
7958           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7959             n name
7960       | name, FInt64 ->
7961           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7962             n name
7963       | name, (FInt32|FUInt32) ->
7964           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7965             n name
7966       | name, FChar ->
7967           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7968             n name
7969       | name, FOptPercent ->
7970           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7971             n name
7972   ) cols;
7973   pr "      free (%s);\n" n
7974
7975 (* Generate Sys/Guestfs.pm. *)
7976 and generate_perl_pm () =
7977   generate_header HashStyle LGPLv2;
7978
7979   pr "\
7980 =pod
7981
7982 =head1 NAME
7983
7984 Sys::Guestfs - Perl bindings for libguestfs
7985
7986 =head1 SYNOPSIS
7987
7988  use Sys::Guestfs;
7989
7990  my $h = Sys::Guestfs->new ();
7991  $h->add_drive ('guest.img');
7992  $h->launch ();
7993  $h->mount ('/dev/sda1', '/');
7994  $h->touch ('/hello');
7995  $h->sync ();
7996
7997 =head1 DESCRIPTION
7998
7999 The C<Sys::Guestfs> module provides a Perl XS binding to the
8000 libguestfs API for examining and modifying virtual machine
8001 disk images.
8002
8003 Amongst the things this is good for: making batch configuration
8004 changes to guests, getting disk used/free statistics (see also:
8005 virt-df), migrating between virtualization systems (see also:
8006 virt-p2v), performing partial backups, performing partial guest
8007 clones, cloning guests and changing registry/UUID/hostname info, and
8008 much else besides.
8009
8010 Libguestfs uses Linux kernel and qemu code, and can access any type of
8011 guest filesystem that Linux and qemu can, including but not limited
8012 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8013 schemes, qcow, qcow2, vmdk.
8014
8015 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8016 LVs, what filesystem is in each LV, etc.).  It can also run commands
8017 in the context of the guest.  Also you can access filesystems over FTP.
8018
8019 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8020 functions for using libguestfs from Perl, including integration
8021 with libvirt.
8022
8023 =head1 ERRORS
8024
8025 All errors turn into calls to C<croak> (see L<Carp(3)>).
8026
8027 =head1 METHODS
8028
8029 =over 4
8030
8031 =cut
8032
8033 package Sys::Guestfs;
8034
8035 use strict;
8036 use warnings;
8037
8038 require XSLoader;
8039 XSLoader::load ('Sys::Guestfs');
8040
8041 =item $h = Sys::Guestfs->new ();
8042
8043 Create a new guestfs handle.
8044
8045 =cut
8046
8047 sub new {
8048   my $proto = shift;
8049   my $class = ref ($proto) || $proto;
8050
8051   my $self = Sys::Guestfs::_create ();
8052   bless $self, $class;
8053   return $self;
8054 }
8055
8056 ";
8057
8058   (* Actions.  We only need to print documentation for these as
8059    * they are pulled in from the XS code automatically.
8060    *)
8061   List.iter (
8062     fun (name, style, _, flags, _, _, longdesc) ->
8063       if not (List.mem NotInDocs flags) then (
8064         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8065         pr "=item ";
8066         generate_perl_prototype name style;
8067         pr "\n\n";
8068         pr "%s\n\n" longdesc;
8069         if List.mem ProtocolLimitWarning flags then
8070           pr "%s\n\n" protocol_limit_warning;
8071         if List.mem DangerWillRobinson flags then
8072           pr "%s\n\n" danger_will_robinson;
8073         match deprecation_notice flags with
8074         | None -> ()
8075         | Some txt -> pr "%s\n\n" txt
8076       )
8077   ) all_functions_sorted;
8078
8079   (* End of file. *)
8080   pr "\
8081 =cut
8082
8083 1;
8084
8085 =back
8086
8087 =head1 COPYRIGHT
8088
8089 Copyright (C) 2009 Red Hat Inc.
8090
8091 =head1 LICENSE
8092
8093 Please see the file COPYING.LIB for the full license.
8094
8095 =head1 SEE ALSO
8096
8097 L<guestfs(3)>,
8098 L<guestfish(1)>,
8099 L<http://libguestfs.org>,
8100 L<Sys::Guestfs::Lib(3)>.
8101
8102 =cut
8103 "
8104
8105 and generate_perl_prototype name style =
8106   (match fst style with
8107    | RErr -> ()
8108    | RBool n
8109    | RInt n
8110    | RInt64 n
8111    | RConstString n
8112    | RConstOptString n
8113    | RString n
8114    | RBufferOut n -> pr "$%s = " n
8115    | RStruct (n,_)
8116    | RHashtable n -> pr "%%%s = " n
8117    | RStringList n
8118    | RStructList (n,_) -> pr "@%s = " n
8119   );
8120   pr "$h->%s (" name;
8121   let comma = ref false in
8122   List.iter (
8123     fun arg ->
8124       if !comma then pr ", ";
8125       comma := true;
8126       match arg with
8127       | Pathname n | Device n | Dev_or_Path n | String n
8128       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8129           pr "$%s" n
8130       | StringList n | DeviceList n ->
8131           pr "\\@%s" n
8132   ) (snd style);
8133   pr ");"
8134
8135 (* Generate Python C module. *)
8136 and generate_python_c () =
8137   generate_header CStyle LGPLv2;
8138
8139   pr "\
8140 #include <Python.h>
8141
8142 #include <stdio.h>
8143 #include <stdlib.h>
8144 #include <assert.h>
8145
8146 #include \"guestfs.h\"
8147
8148 typedef struct {
8149   PyObject_HEAD
8150   guestfs_h *g;
8151 } Pyguestfs_Object;
8152
8153 static guestfs_h *
8154 get_handle (PyObject *obj)
8155 {
8156   assert (obj);
8157   assert (obj != Py_None);
8158   return ((Pyguestfs_Object *) obj)->g;
8159 }
8160
8161 static PyObject *
8162 put_handle (guestfs_h *g)
8163 {
8164   assert (g);
8165   return
8166     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8167 }
8168
8169 /* This list should be freed (but not the strings) after use. */
8170 static char **
8171 get_string_list (PyObject *obj)
8172 {
8173   int i, len;
8174   char **r;
8175
8176   assert (obj);
8177
8178   if (!PyList_Check (obj)) {
8179     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8180     return NULL;
8181   }
8182
8183   len = PyList_Size (obj);
8184   r = malloc (sizeof (char *) * (len+1));
8185   if (r == NULL) {
8186     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8187     return NULL;
8188   }
8189
8190   for (i = 0; i < len; ++i)
8191     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8192   r[len] = NULL;
8193
8194   return r;
8195 }
8196
8197 static PyObject *
8198 put_string_list (char * const * const argv)
8199 {
8200   PyObject *list;
8201   int argc, i;
8202
8203   for (argc = 0; argv[argc] != NULL; ++argc)
8204     ;
8205
8206   list = PyList_New (argc);
8207   for (i = 0; i < argc; ++i)
8208     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8209
8210   return list;
8211 }
8212
8213 static PyObject *
8214 put_table (char * const * const argv)
8215 {
8216   PyObject *list, *item;
8217   int argc, i;
8218
8219   for (argc = 0; argv[argc] != NULL; ++argc)
8220     ;
8221
8222   list = PyList_New (argc >> 1);
8223   for (i = 0; i < argc; i += 2) {
8224     item = PyTuple_New (2);
8225     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8226     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8227     PyList_SetItem (list, i >> 1, item);
8228   }
8229
8230   return list;
8231 }
8232
8233 static void
8234 free_strings (char **argv)
8235 {
8236   int argc;
8237
8238   for (argc = 0; argv[argc] != NULL; ++argc)
8239     free (argv[argc]);
8240   free (argv);
8241 }
8242
8243 static PyObject *
8244 py_guestfs_create (PyObject *self, PyObject *args)
8245 {
8246   guestfs_h *g;
8247
8248   g = guestfs_create ();
8249   if (g == NULL) {
8250     PyErr_SetString (PyExc_RuntimeError,
8251                      \"guestfs.create: failed to allocate handle\");
8252     return NULL;
8253   }
8254   guestfs_set_error_handler (g, NULL, NULL);
8255   return put_handle (g);
8256 }
8257
8258 static PyObject *
8259 py_guestfs_close (PyObject *self, PyObject *args)
8260 {
8261   PyObject *py_g;
8262   guestfs_h *g;
8263
8264   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8265     return NULL;
8266   g = get_handle (py_g);
8267
8268   guestfs_close (g);
8269
8270   Py_INCREF (Py_None);
8271   return Py_None;
8272 }
8273
8274 ";
8275
8276   let emit_put_list_function typ =
8277     pr "static PyObject *\n";
8278     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8279     pr "{\n";
8280     pr "  PyObject *list;\n";
8281     pr "  int i;\n";
8282     pr "\n";
8283     pr "  list = PyList_New (%ss->len);\n" typ;
8284     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8285     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8286     pr "  return list;\n";
8287     pr "};\n";
8288     pr "\n"
8289   in
8290
8291   (* Structures, turned into Python dictionaries. *)
8292   List.iter (
8293     fun (typ, cols) ->
8294       pr "static PyObject *\n";
8295       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8296       pr "{\n";
8297       pr "  PyObject *dict;\n";
8298       pr "\n";
8299       pr "  dict = PyDict_New ();\n";
8300       List.iter (
8301         function
8302         | name, FString ->
8303             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8304             pr "                        PyString_FromString (%s->%s));\n"
8305               typ name
8306         | name, FBuffer ->
8307             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8308             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8309               typ name typ name
8310         | name, FUUID ->
8311             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8312             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8313               typ name
8314         | name, (FBytes|FUInt64) ->
8315             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8316             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8317               typ name
8318         | name, FInt64 ->
8319             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8320             pr "                        PyLong_FromLongLong (%s->%s));\n"
8321               typ name
8322         | name, FUInt32 ->
8323             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8324             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8325               typ name
8326         | name, FInt32 ->
8327             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8328             pr "                        PyLong_FromLong (%s->%s));\n"
8329               typ name
8330         | name, FOptPercent ->
8331             pr "  if (%s->%s >= 0)\n" typ name;
8332             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8333             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8334               typ name;
8335             pr "  else {\n";
8336             pr "    Py_INCREF (Py_None);\n";
8337             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8338             pr "  }\n"
8339         | name, FChar ->
8340             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8341             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8342       ) cols;
8343       pr "  return dict;\n";
8344       pr "};\n";
8345       pr "\n";
8346
8347   ) structs;
8348
8349   (* Emit a put_TYPE_list function definition only if that function is used. *)
8350   List.iter (
8351     function
8352     | typ, (RStructListOnly | RStructAndList) ->
8353         (* generate the function for typ *)
8354         emit_put_list_function typ
8355     | typ, _ -> () (* empty *)
8356   ) (rstructs_used_by all_functions);
8357
8358   (* Python wrapper functions. *)
8359   List.iter (
8360     fun (name, style, _, _, _, _, _) ->
8361       pr "static PyObject *\n";
8362       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8363       pr "{\n";
8364
8365       pr "  PyObject *py_g;\n";
8366       pr "  guestfs_h *g;\n";
8367       pr "  PyObject *py_r;\n";
8368
8369       let error_code =
8370         match fst style with
8371         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8372         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8373         | RConstString _ | RConstOptString _ ->
8374             pr "  const char *r;\n"; "NULL"
8375         | RString _ -> pr "  char *r;\n"; "NULL"
8376         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8377         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8378         | RStructList (_, typ) ->
8379             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8380         | RBufferOut _ ->
8381             pr "  char *r;\n";
8382             pr "  size_t size;\n";
8383             "NULL" in
8384
8385       List.iter (
8386         function
8387         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8388             pr "  const char *%s;\n" n
8389         | OptString n -> pr "  const char *%s;\n" n
8390         | StringList n | DeviceList n ->
8391             pr "  PyObject *py_%s;\n" n;
8392             pr "  char **%s;\n" n
8393         | Bool n -> pr "  int %s;\n" n
8394         | Int n -> pr "  int %s;\n" n
8395         | Int64 n -> pr "  long long %s;\n" n
8396       ) (snd style);
8397
8398       pr "\n";
8399
8400       (* Convert the parameters. *)
8401       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8402       List.iter (
8403         function
8404         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8405         | OptString _ -> pr "z"
8406         | StringList _ | DeviceList _ -> pr "O"
8407         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8408         | Int _ -> pr "i"
8409         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8410                              * emulate C's int/long/long long in Python?
8411                              *)
8412       ) (snd style);
8413       pr ":guestfs_%s\",\n" name;
8414       pr "                         &py_g";
8415       List.iter (
8416         function
8417         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8418         | OptString n -> pr ", &%s" n
8419         | StringList n | DeviceList n -> pr ", &py_%s" n
8420         | Bool n -> pr ", &%s" n
8421         | Int n -> pr ", &%s" n
8422         | Int64 n -> pr ", &%s" n
8423       ) (snd style);
8424
8425       pr "))\n";
8426       pr "    return NULL;\n";
8427
8428       pr "  g = get_handle (py_g);\n";
8429       List.iter (
8430         function
8431         | Pathname _ | Device _ | Dev_or_Path _ | String _
8432         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8433         | StringList n | DeviceList n ->
8434             pr "  %s = get_string_list (py_%s);\n" n n;
8435             pr "  if (!%s) return NULL;\n" n
8436       ) (snd style);
8437
8438       pr "\n";
8439
8440       pr "  r = guestfs_%s " name;
8441       generate_c_call_args ~handle:"g" style;
8442       pr ";\n";
8443
8444       List.iter (
8445         function
8446         | Pathname _ | Device _ | Dev_or_Path _ | String _
8447         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8448         | StringList n | DeviceList n ->
8449             pr "  free (%s);\n" n
8450       ) (snd style);
8451
8452       pr "  if (r == %s) {\n" error_code;
8453       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8454       pr "    return NULL;\n";
8455       pr "  }\n";
8456       pr "\n";
8457
8458       (match fst style with
8459        | RErr ->
8460            pr "  Py_INCREF (Py_None);\n";
8461            pr "  py_r = Py_None;\n"
8462        | RInt _
8463        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8464        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8465        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8466        | RConstOptString _ ->
8467            pr "  if (r)\n";
8468            pr "    py_r = PyString_FromString (r);\n";
8469            pr "  else {\n";
8470            pr "    Py_INCREF (Py_None);\n";
8471            pr "    py_r = Py_None;\n";
8472            pr "  }\n"
8473        | RString _ ->
8474            pr "  py_r = PyString_FromString (r);\n";
8475            pr "  free (r);\n"
8476        | RStringList _ ->
8477            pr "  py_r = put_string_list (r);\n";
8478            pr "  free_strings (r);\n"
8479        | RStruct (_, typ) ->
8480            pr "  py_r = put_%s (r);\n" typ;
8481            pr "  guestfs_free_%s (r);\n" typ
8482        | RStructList (_, typ) ->
8483            pr "  py_r = put_%s_list (r);\n" typ;
8484            pr "  guestfs_free_%s_list (r);\n" typ
8485        | RHashtable n ->
8486            pr "  py_r = put_table (r);\n";
8487            pr "  free_strings (r);\n"
8488        | RBufferOut _ ->
8489            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8490            pr "  free (r);\n"
8491       );
8492
8493       pr "  return py_r;\n";
8494       pr "}\n";
8495       pr "\n"
8496   ) all_functions;
8497
8498   (* Table of functions. *)
8499   pr "static PyMethodDef methods[] = {\n";
8500   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8501   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8502   List.iter (
8503     fun (name, _, _, _, _, _, _) ->
8504       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8505         name name
8506   ) all_functions;
8507   pr "  { NULL, NULL, 0, NULL }\n";
8508   pr "};\n";
8509   pr "\n";
8510
8511   (* Init function. *)
8512   pr "\
8513 void
8514 initlibguestfsmod (void)
8515 {
8516   static int initialized = 0;
8517
8518   if (initialized) return;
8519   Py_InitModule ((char *) \"libguestfsmod\", methods);
8520   initialized = 1;
8521 }
8522 "
8523
8524 (* Generate Python module. *)
8525 and generate_python_py () =
8526   generate_header HashStyle LGPLv2;
8527
8528   pr "\
8529 u\"\"\"Python bindings for libguestfs
8530
8531 import guestfs
8532 g = guestfs.GuestFS ()
8533 g.add_drive (\"guest.img\")
8534 g.launch ()
8535 parts = g.list_partitions ()
8536
8537 The guestfs module provides a Python binding to the libguestfs API
8538 for examining and modifying virtual machine disk images.
8539
8540 Amongst the things this is good for: making batch configuration
8541 changes to guests, getting disk used/free statistics (see also:
8542 virt-df), migrating between virtualization systems (see also:
8543 virt-p2v), performing partial backups, performing partial guest
8544 clones, cloning guests and changing registry/UUID/hostname info, and
8545 much else besides.
8546
8547 Libguestfs uses Linux kernel and qemu code, and can access any type of
8548 guest filesystem that Linux and qemu can, including but not limited
8549 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8550 schemes, qcow, qcow2, vmdk.
8551
8552 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8553 LVs, what filesystem is in each LV, etc.).  It can also run commands
8554 in the context of the guest.  Also you can access filesystems over FTP.
8555
8556 Errors which happen while using the API are turned into Python
8557 RuntimeError exceptions.
8558
8559 To create a guestfs handle you usually have to perform the following
8560 sequence of calls:
8561
8562 # Create the handle, call add_drive at least once, and possibly
8563 # several times if the guest has multiple block devices:
8564 g = guestfs.GuestFS ()
8565 g.add_drive (\"guest.img\")
8566
8567 # Launch the qemu subprocess and wait for it to become ready:
8568 g.launch ()
8569
8570 # Now you can issue commands, for example:
8571 logvols = g.lvs ()
8572
8573 \"\"\"
8574
8575 import libguestfsmod
8576
8577 class GuestFS:
8578     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8579
8580     def __init__ (self):
8581         \"\"\"Create a new libguestfs handle.\"\"\"
8582         self._o = libguestfsmod.create ()
8583
8584     def __del__ (self):
8585         libguestfsmod.close (self._o)
8586
8587 ";
8588
8589   List.iter (
8590     fun (name, style, _, flags, _, _, longdesc) ->
8591       pr "    def %s " name;
8592       generate_py_call_args ~handle:"self" (snd style);
8593       pr ":\n";
8594
8595       if not (List.mem NotInDocs flags) then (
8596         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8597         let doc =
8598           match fst style with
8599           | RErr | RInt _ | RInt64 _ | RBool _
8600           | RConstOptString _ | RConstString _
8601           | RString _ | RBufferOut _ -> doc
8602           | RStringList _ ->
8603               doc ^ "\n\nThis function returns a list of strings."
8604           | RStruct (_, typ) ->
8605               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8606           | RStructList (_, typ) ->
8607               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8608           | RHashtable _ ->
8609               doc ^ "\n\nThis function returns a dictionary." in
8610         let doc =
8611           if List.mem ProtocolLimitWarning flags then
8612             doc ^ "\n\n" ^ protocol_limit_warning
8613           else doc in
8614         let doc =
8615           if List.mem DangerWillRobinson flags then
8616             doc ^ "\n\n" ^ danger_will_robinson
8617           else doc in
8618         let doc =
8619           match deprecation_notice flags with
8620           | None -> doc
8621           | Some txt -> doc ^ "\n\n" ^ txt in
8622         let doc = pod2text ~width:60 name doc in
8623         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8624         let doc = String.concat "\n        " doc in
8625         pr "        u\"\"\"%s\"\"\"\n" doc;
8626       );
8627       pr "        return libguestfsmod.%s " name;
8628       generate_py_call_args ~handle:"self._o" (snd style);
8629       pr "\n";
8630       pr "\n";
8631   ) all_functions
8632
8633 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8634 and generate_py_call_args ~handle args =
8635   pr "(%s" handle;
8636   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8637   pr ")"
8638
8639 (* Useful if you need the longdesc POD text as plain text.  Returns a
8640  * list of lines.
8641  *
8642  * Because this is very slow (the slowest part of autogeneration),
8643  * we memoize the results.
8644  *)
8645 and pod2text ~width name longdesc =
8646   let key = width, name, longdesc in
8647   try Hashtbl.find pod2text_memo key
8648   with Not_found ->
8649     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8650     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8651     close_out chan;
8652     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8653     let chan = Unix.open_process_in cmd in
8654     let lines = ref [] in
8655     let rec loop i =
8656       let line = input_line chan in
8657       if i = 1 then             (* discard the first line of output *)
8658         loop (i+1)
8659       else (
8660         let line = triml line in
8661         lines := line :: !lines;
8662         loop (i+1)
8663       ) in
8664     let lines = try loop 1 with End_of_file -> List.rev !lines in
8665     Unix.unlink filename;
8666     (match Unix.close_process_in chan with
8667      | Unix.WEXITED 0 -> ()
8668      | Unix.WEXITED i ->
8669          failwithf "pod2text: process exited with non-zero status (%d)" i
8670      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8671          failwithf "pod2text: process signalled or stopped by signal %d" i
8672     );
8673     Hashtbl.add pod2text_memo key lines;
8674     pod2text_memo_updated ();
8675     lines
8676
8677 (* Generate ruby bindings. *)
8678 and generate_ruby_c () =
8679   generate_header CStyle LGPLv2;
8680
8681   pr "\
8682 #include <stdio.h>
8683 #include <stdlib.h>
8684
8685 #include <ruby.h>
8686
8687 #include \"guestfs.h\"
8688
8689 #include \"extconf.h\"
8690
8691 /* For Ruby < 1.9 */
8692 #ifndef RARRAY_LEN
8693 #define RARRAY_LEN(r) (RARRAY((r))->len)
8694 #endif
8695
8696 static VALUE m_guestfs;                 /* guestfs module */
8697 static VALUE c_guestfs;                 /* guestfs_h handle */
8698 static VALUE e_Error;                   /* used for all errors */
8699
8700 static void ruby_guestfs_free (void *p)
8701 {
8702   if (!p) return;
8703   guestfs_close ((guestfs_h *) p);
8704 }
8705
8706 static VALUE ruby_guestfs_create (VALUE m)
8707 {
8708   guestfs_h *g;
8709
8710   g = guestfs_create ();
8711   if (!g)
8712     rb_raise (e_Error, \"failed to create guestfs handle\");
8713
8714   /* Don't print error messages to stderr by default. */
8715   guestfs_set_error_handler (g, NULL, NULL);
8716
8717   /* Wrap it, and make sure the close function is called when the
8718    * handle goes away.
8719    */
8720   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8721 }
8722
8723 static VALUE ruby_guestfs_close (VALUE gv)
8724 {
8725   guestfs_h *g;
8726   Data_Get_Struct (gv, guestfs_h, g);
8727
8728   ruby_guestfs_free (g);
8729   DATA_PTR (gv) = NULL;
8730
8731   return Qnil;
8732 }
8733
8734 ";
8735
8736   List.iter (
8737     fun (name, style, _, _, _, _, _) ->
8738       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8739       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8740       pr ")\n";
8741       pr "{\n";
8742       pr "  guestfs_h *g;\n";
8743       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8744       pr "  if (!g)\n";
8745       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8746         name;
8747       pr "\n";
8748
8749       List.iter (
8750         function
8751         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8752             pr "  Check_Type (%sv, T_STRING);\n" n;
8753             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8754             pr "  if (!%s)\n" n;
8755             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8756             pr "              \"%s\", \"%s\");\n" n name
8757         | OptString n ->
8758             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8759         | StringList n | DeviceList n ->
8760             pr "  char **%s;\n" n;
8761             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8762             pr "  {\n";
8763             pr "    int i, len;\n";
8764             pr "    len = RARRAY_LEN (%sv);\n" n;
8765             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8766               n;
8767             pr "    for (i = 0; i < len; ++i) {\n";
8768             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8769             pr "      %s[i] = StringValueCStr (v);\n" n;
8770             pr "    }\n";
8771             pr "    %s[len] = NULL;\n" n;
8772             pr "  }\n";
8773         | Bool n ->
8774             pr "  int %s = RTEST (%sv);\n" n n
8775         | Int n ->
8776             pr "  int %s = NUM2INT (%sv);\n" n n
8777         | Int64 n ->
8778             pr "  long long %s = NUM2LL (%sv);\n" n n
8779       ) (snd style);
8780       pr "\n";
8781
8782       let error_code =
8783         match fst style with
8784         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8785         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8786         | RConstString _ | RConstOptString _ ->
8787             pr "  const char *r;\n"; "NULL"
8788         | RString _ -> pr "  char *r;\n"; "NULL"
8789         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8790         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8791         | RStructList (_, typ) ->
8792             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8793         | RBufferOut _ ->
8794             pr "  char *r;\n";
8795             pr "  size_t size;\n";
8796             "NULL" in
8797       pr "\n";
8798
8799       pr "  r = guestfs_%s " name;
8800       generate_c_call_args ~handle:"g" style;
8801       pr ";\n";
8802
8803       List.iter (
8804         function
8805         | Pathname _ | Device _ | Dev_or_Path _ | String _
8806         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8807         | StringList n | DeviceList n ->
8808             pr "  free (%s);\n" n
8809       ) (snd style);
8810
8811       pr "  if (r == %s)\n" error_code;
8812       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8813       pr "\n";
8814
8815       (match fst style with
8816        | RErr ->
8817            pr "  return Qnil;\n"
8818        | RInt _ | RBool _ ->
8819            pr "  return INT2NUM (r);\n"
8820        | RInt64 _ ->
8821            pr "  return ULL2NUM (r);\n"
8822        | RConstString _ ->
8823            pr "  return rb_str_new2 (r);\n";
8824        | RConstOptString _ ->
8825            pr "  if (r)\n";
8826            pr "    return rb_str_new2 (r);\n";
8827            pr "  else\n";
8828            pr "    return Qnil;\n";
8829        | RString _ ->
8830            pr "  VALUE rv = rb_str_new2 (r);\n";
8831            pr "  free (r);\n";
8832            pr "  return rv;\n";
8833        | RStringList _ ->
8834            pr "  int i, len = 0;\n";
8835            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8836            pr "  VALUE rv = rb_ary_new2 (len);\n";
8837            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8838            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8839            pr "    free (r[i]);\n";
8840            pr "  }\n";
8841            pr "  free (r);\n";
8842            pr "  return rv;\n"
8843        | RStruct (_, typ) ->
8844            let cols = cols_of_struct typ in
8845            generate_ruby_struct_code typ cols
8846        | RStructList (_, typ) ->
8847            let cols = cols_of_struct typ in
8848            generate_ruby_struct_list_code typ cols
8849        | RHashtable _ ->
8850            pr "  VALUE rv = rb_hash_new ();\n";
8851            pr "  int i;\n";
8852            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8853            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8854            pr "    free (r[i]);\n";
8855            pr "    free (r[i+1]);\n";
8856            pr "  }\n";
8857            pr "  free (r);\n";
8858            pr "  return rv;\n"
8859        | RBufferOut _ ->
8860            pr "  VALUE rv = rb_str_new (r, size);\n";
8861            pr "  free (r);\n";
8862            pr "  return rv;\n";
8863       );
8864
8865       pr "}\n";
8866       pr "\n"
8867   ) all_functions;
8868
8869   pr "\
8870 /* Initialize the module. */
8871 void Init__guestfs ()
8872 {
8873   m_guestfs = rb_define_module (\"Guestfs\");
8874   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8875   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8876
8877   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8878   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8879
8880 ";
8881   (* Define the rest of the methods. *)
8882   List.iter (
8883     fun (name, style, _, _, _, _, _) ->
8884       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8885       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8886   ) all_functions;
8887
8888   pr "}\n"
8889
8890 (* Ruby code to return a struct. *)
8891 and generate_ruby_struct_code typ cols =
8892   pr "  VALUE rv = rb_hash_new ();\n";
8893   List.iter (
8894     function
8895     | name, FString ->
8896         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8897     | name, FBuffer ->
8898         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8899     | name, FUUID ->
8900         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8901     | name, (FBytes|FUInt64) ->
8902         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8903     | name, FInt64 ->
8904         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8905     | name, FUInt32 ->
8906         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8907     | name, FInt32 ->
8908         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8909     | name, FOptPercent ->
8910         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8911     | name, FChar -> (* XXX wrong? *)
8912         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8913   ) cols;
8914   pr "  guestfs_free_%s (r);\n" typ;
8915   pr "  return rv;\n"
8916
8917 (* Ruby code to return a struct list. *)
8918 and generate_ruby_struct_list_code typ cols =
8919   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8920   pr "  int i;\n";
8921   pr "  for (i = 0; i < r->len; ++i) {\n";
8922   pr "    VALUE hv = rb_hash_new ();\n";
8923   List.iter (
8924     function
8925     | name, FString ->
8926         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8927     | name, FBuffer ->
8928         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
8929     | name, FUUID ->
8930         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8931     | name, (FBytes|FUInt64) ->
8932         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8933     | name, FInt64 ->
8934         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8935     | name, FUInt32 ->
8936         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8937     | name, FInt32 ->
8938         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8939     | name, FOptPercent ->
8940         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8941     | name, FChar -> (* XXX wrong? *)
8942         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8943   ) cols;
8944   pr "    rb_ary_push (rv, hv);\n";
8945   pr "  }\n";
8946   pr "  guestfs_free_%s_list (r);\n" typ;
8947   pr "  return rv;\n"
8948
8949 (* Generate Java bindings GuestFS.java file. *)
8950 and generate_java_java () =
8951   generate_header CStyle LGPLv2;
8952
8953   pr "\
8954 package com.redhat.et.libguestfs;
8955
8956 import java.util.HashMap;
8957 import com.redhat.et.libguestfs.LibGuestFSException;
8958 import com.redhat.et.libguestfs.PV;
8959 import com.redhat.et.libguestfs.VG;
8960 import com.redhat.et.libguestfs.LV;
8961 import com.redhat.et.libguestfs.Stat;
8962 import com.redhat.et.libguestfs.StatVFS;
8963 import com.redhat.et.libguestfs.IntBool;
8964 import com.redhat.et.libguestfs.Dirent;
8965
8966 /**
8967  * The GuestFS object is a libguestfs handle.
8968  *
8969  * @author rjones
8970  */
8971 public class GuestFS {
8972   // Load the native code.
8973   static {
8974     System.loadLibrary (\"guestfs_jni\");
8975   }
8976
8977   /**
8978    * The native guestfs_h pointer.
8979    */
8980   long g;
8981
8982   /**
8983    * Create a libguestfs handle.
8984    *
8985    * @throws LibGuestFSException
8986    */
8987   public GuestFS () throws LibGuestFSException
8988   {
8989     g = _create ();
8990   }
8991   private native long _create () throws LibGuestFSException;
8992
8993   /**
8994    * Close a libguestfs handle.
8995    *
8996    * You can also leave handles to be collected by the garbage
8997    * collector, but this method ensures that the resources used
8998    * by the handle are freed up immediately.  If you call any
8999    * other methods after closing the handle, you will get an
9000    * exception.
9001    *
9002    * @throws LibGuestFSException
9003    */
9004   public void close () throws LibGuestFSException
9005   {
9006     if (g != 0)
9007       _close (g);
9008     g = 0;
9009   }
9010   private native void _close (long g) throws LibGuestFSException;
9011
9012   public void finalize () throws LibGuestFSException
9013   {
9014     close ();
9015   }
9016
9017 ";
9018
9019   List.iter (
9020     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9021       if not (List.mem NotInDocs flags); then (
9022         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9023         let doc =
9024           if List.mem ProtocolLimitWarning flags then
9025             doc ^ "\n\n" ^ protocol_limit_warning
9026           else doc in
9027         let doc =
9028           if List.mem DangerWillRobinson flags then
9029             doc ^ "\n\n" ^ danger_will_robinson
9030           else doc in
9031         let doc =
9032           match deprecation_notice flags with
9033           | None -> doc
9034           | Some txt -> doc ^ "\n\n" ^ txt in
9035         let doc = pod2text ~width:60 name doc in
9036         let doc = List.map (            (* RHBZ#501883 *)
9037           function
9038           | "" -> "<p>"
9039           | nonempty -> nonempty
9040         ) doc in
9041         let doc = String.concat "\n   * " doc in
9042
9043         pr "  /**\n";
9044         pr "   * %s\n" shortdesc;
9045         pr "   * <p>\n";
9046         pr "   * %s\n" doc;
9047         pr "   * @throws LibGuestFSException\n";
9048         pr "   */\n";
9049         pr "  ";
9050       );
9051       generate_java_prototype ~public:true ~semicolon:false name style;
9052       pr "\n";
9053       pr "  {\n";
9054       pr "    if (g == 0)\n";
9055       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9056         name;
9057       pr "    ";
9058       if fst style <> RErr then pr "return ";
9059       pr "_%s " name;
9060       generate_java_call_args ~handle:"g" (snd style);
9061       pr ";\n";
9062       pr "  }\n";
9063       pr "  ";
9064       generate_java_prototype ~privat:true ~native:true name style;
9065       pr "\n";
9066       pr "\n";
9067   ) all_functions;
9068
9069   pr "}\n"
9070
9071 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9072 and generate_java_call_args ~handle args =
9073   pr "(%s" handle;
9074   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9075   pr ")"
9076
9077 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9078     ?(semicolon=true) name style =
9079   if privat then pr "private ";
9080   if public then pr "public ";
9081   if native then pr "native ";
9082
9083   (* return type *)
9084   (match fst style with
9085    | RErr -> pr "void ";
9086    | RInt _ -> pr "int ";
9087    | RInt64 _ -> pr "long ";
9088    | RBool _ -> pr "boolean ";
9089    | RConstString _ | RConstOptString _ | RString _
9090    | RBufferOut _ -> pr "String ";
9091    | RStringList _ -> pr "String[] ";
9092    | RStruct (_, typ) ->
9093        let name = java_name_of_struct typ in
9094        pr "%s " name;
9095    | RStructList (_, typ) ->
9096        let name = java_name_of_struct typ in
9097        pr "%s[] " name;
9098    | RHashtable _ -> pr "HashMap<String,String> ";
9099   );
9100
9101   if native then pr "_%s " name else pr "%s " name;
9102   pr "(";
9103   let needs_comma = ref false in
9104   if native then (
9105     pr "long g";
9106     needs_comma := true
9107   );
9108
9109   (* args *)
9110   List.iter (
9111     fun arg ->
9112       if !needs_comma then pr ", ";
9113       needs_comma := true;
9114
9115       match arg with
9116       | Pathname n
9117       | Device n | Dev_or_Path n
9118       | String n
9119       | OptString n
9120       | FileIn n
9121       | FileOut n ->
9122           pr "String %s" n
9123       | StringList n | DeviceList n ->
9124           pr "String[] %s" n
9125       | Bool n ->
9126           pr "boolean %s" n
9127       | Int n ->
9128           pr "int %s" n
9129       | Int64 n ->
9130           pr "long %s" n
9131   ) (snd style);
9132
9133   pr ")\n";
9134   pr "    throws LibGuestFSException";
9135   if semicolon then pr ";"
9136
9137 and generate_java_struct jtyp cols =
9138   generate_header CStyle LGPLv2;
9139
9140   pr "\
9141 package com.redhat.et.libguestfs;
9142
9143 /**
9144  * Libguestfs %s structure.
9145  *
9146  * @author rjones
9147  * @see GuestFS
9148  */
9149 public class %s {
9150 " jtyp jtyp;
9151
9152   List.iter (
9153     function
9154     | name, FString
9155     | name, FUUID
9156     | name, FBuffer -> pr "  public String %s;\n" name
9157     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9158     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9159     | name, FChar -> pr "  public char %s;\n" name
9160     | name, FOptPercent ->
9161         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9162         pr "  public float %s;\n" name
9163   ) cols;
9164
9165   pr "}\n"
9166
9167 and generate_java_c () =
9168   generate_header CStyle LGPLv2;
9169
9170   pr "\
9171 #include <stdio.h>
9172 #include <stdlib.h>
9173 #include <string.h>
9174
9175 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9176 #include \"guestfs.h\"
9177
9178 /* Note that this function returns.  The exception is not thrown
9179  * until after the wrapper function returns.
9180  */
9181 static void
9182 throw_exception (JNIEnv *env, const char *msg)
9183 {
9184   jclass cl;
9185   cl = (*env)->FindClass (env,
9186                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9187   (*env)->ThrowNew (env, cl, msg);
9188 }
9189
9190 JNIEXPORT jlong JNICALL
9191 Java_com_redhat_et_libguestfs_GuestFS__1create
9192   (JNIEnv *env, jobject obj)
9193 {
9194   guestfs_h *g;
9195
9196   g = guestfs_create ();
9197   if (g == NULL) {
9198     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9199     return 0;
9200   }
9201   guestfs_set_error_handler (g, NULL, NULL);
9202   return (jlong) (long) g;
9203 }
9204
9205 JNIEXPORT void JNICALL
9206 Java_com_redhat_et_libguestfs_GuestFS__1close
9207   (JNIEnv *env, jobject obj, jlong jg)
9208 {
9209   guestfs_h *g = (guestfs_h *) (long) jg;
9210   guestfs_close (g);
9211 }
9212
9213 ";
9214
9215   List.iter (
9216     fun (name, style, _, _, _, _, _) ->
9217       pr "JNIEXPORT ";
9218       (match fst style with
9219        | RErr -> pr "void ";
9220        | RInt _ -> pr "jint ";
9221        | RInt64 _ -> pr "jlong ";
9222        | RBool _ -> pr "jboolean ";
9223        | RConstString _ | RConstOptString _ | RString _
9224        | RBufferOut _ -> pr "jstring ";
9225        | RStruct _ | RHashtable _ ->
9226            pr "jobject ";
9227        | RStringList _ | RStructList _ ->
9228            pr "jobjectArray ";
9229       );
9230       pr "JNICALL\n";
9231       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9232       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9233       pr "\n";
9234       pr "  (JNIEnv *env, jobject obj, jlong jg";
9235       List.iter (
9236         function
9237         | Pathname n
9238         | Device n | Dev_or_Path n
9239         | String n
9240         | OptString n
9241         | FileIn n
9242         | FileOut n ->
9243             pr ", jstring j%s" n
9244         | StringList n | DeviceList n ->
9245             pr ", jobjectArray j%s" n
9246         | Bool n ->
9247             pr ", jboolean j%s" n
9248         | Int n ->
9249             pr ", jint j%s" n
9250         | Int64 n ->
9251             pr ", jlong j%s" n
9252       ) (snd style);
9253       pr ")\n";
9254       pr "{\n";
9255       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9256       let error_code, no_ret =
9257         match fst style with
9258         | RErr -> pr "  int r;\n"; "-1", ""
9259         | RBool _
9260         | RInt _ -> pr "  int r;\n"; "-1", "0"
9261         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9262         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9263         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9264         | RString _ ->
9265             pr "  jstring jr;\n";
9266             pr "  char *r;\n"; "NULL", "NULL"
9267         | RStringList _ ->
9268             pr "  jobjectArray jr;\n";
9269             pr "  int r_len;\n";
9270             pr "  jclass cl;\n";
9271             pr "  jstring jstr;\n";
9272             pr "  char **r;\n"; "NULL", "NULL"
9273         | RStruct (_, typ) ->
9274             pr "  jobject jr;\n";
9275             pr "  jclass cl;\n";
9276             pr "  jfieldID fl;\n";
9277             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9278         | RStructList (_, typ) ->
9279             pr "  jobjectArray jr;\n";
9280             pr "  jclass cl;\n";
9281             pr "  jfieldID fl;\n";
9282             pr "  jobject jfl;\n";
9283             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9284         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9285         | RBufferOut _ ->
9286             pr "  jstring jr;\n";
9287             pr "  char *r;\n";
9288             pr "  size_t size;\n";
9289             "NULL", "NULL" in
9290       List.iter (
9291         function
9292         | Pathname n
9293         | Device n | Dev_or_Path n
9294         | String n
9295         | OptString n
9296         | FileIn n
9297         | FileOut n ->
9298             pr "  const char *%s;\n" n
9299         | StringList n | DeviceList n ->
9300             pr "  int %s_len;\n" n;
9301             pr "  const char **%s;\n" n
9302         | Bool n
9303         | Int n ->
9304             pr "  int %s;\n" n
9305         | Int64 n ->
9306             pr "  int64_t %s;\n" n
9307       ) (snd style);
9308
9309       let needs_i =
9310         (match fst style with
9311          | RStringList _ | RStructList _ -> true
9312          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9313          | RConstOptString _
9314          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9315           List.exists (function
9316                        | StringList _ -> true
9317                        | DeviceList _ -> true
9318                        | _ -> false) (snd style) in
9319       if needs_i then
9320         pr "  int i;\n";
9321
9322       pr "\n";
9323
9324       (* Get the parameters. *)
9325       List.iter (
9326         function
9327         | Pathname n
9328         | Device n | Dev_or_Path n
9329         | String n
9330         | FileIn n
9331         | FileOut n ->
9332             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9333         | OptString n ->
9334             (* This is completely undocumented, but Java null becomes
9335              * a NULL parameter.
9336              *)
9337             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9338         | StringList n | DeviceList n ->
9339             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9340             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n 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 "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9345             pr "  }\n";
9346             pr "  %s[%s_len] = NULL;\n" n n;
9347         | Bool n
9348         | Int n
9349         | Int64 n ->
9350             pr "  %s = j%s;\n" n n
9351       ) (snd style);
9352
9353       (* Make the call. *)
9354       pr "  r = guestfs_%s " name;
9355       generate_c_call_args ~handle:"g" style;
9356       pr ";\n";
9357
9358       (* Release the parameters. *)
9359       List.iter (
9360         function
9361         | Pathname n
9362         | Device n | Dev_or_Path n
9363         | String n
9364         | FileIn n
9365         | FileOut n ->
9366             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9367         | OptString n ->
9368             pr "  if (j%s)\n" n;
9369             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9370         | StringList n | DeviceList n ->
9371             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9372             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9373               n;
9374             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9375             pr "  }\n";
9376             pr "  free (%s);\n" n
9377         | Bool n
9378         | Int n
9379         | Int64 n -> ()
9380       ) (snd style);
9381
9382       (* Check for errors. *)
9383       pr "  if (r == %s) {\n" error_code;
9384       pr "    throw_exception (env, guestfs_last_error (g));\n";
9385       pr "    return %s;\n" no_ret;
9386       pr "  }\n";
9387
9388       (* Return value. *)
9389       (match fst style with
9390        | RErr -> ()
9391        | RInt _ -> pr "  return (jint) r;\n"
9392        | RBool _ -> pr "  return (jboolean) r;\n"
9393        | RInt64 _ -> pr "  return (jlong) r;\n"
9394        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9395        | RConstOptString _ ->
9396            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9397        | RString _ ->
9398            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9399            pr "  free (r);\n";
9400            pr "  return jr;\n"
9401        | RStringList _ ->
9402            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9403            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9404            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9405            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9406            pr "  for (i = 0; i < r_len; ++i) {\n";
9407            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9408            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9409            pr "    free (r[i]);\n";
9410            pr "  }\n";
9411            pr "  free (r);\n";
9412            pr "  return jr;\n"
9413        | RStruct (_, typ) ->
9414            let jtyp = java_name_of_struct typ in
9415            let cols = cols_of_struct typ in
9416            generate_java_struct_return typ jtyp cols
9417        | RStructList (_, typ) ->
9418            let jtyp = java_name_of_struct typ in
9419            let cols = cols_of_struct typ in
9420            generate_java_struct_list_return typ jtyp cols
9421        | RHashtable _ ->
9422            (* XXX *)
9423            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9424            pr "  return NULL;\n"
9425        | RBufferOut _ ->
9426            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9427            pr "  free (r);\n";
9428            pr "  return jr;\n"
9429       );
9430
9431       pr "}\n";
9432       pr "\n"
9433   ) all_functions
9434
9435 and generate_java_struct_return typ jtyp cols =
9436   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9437   pr "  jr = (*env)->AllocObject (env, cl);\n";
9438   List.iter (
9439     function
9440     | name, FString ->
9441         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9442         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9443     | name, FUUID ->
9444         pr "  {\n";
9445         pr "    char s[33];\n";
9446         pr "    memcpy (s, r->%s, 32);\n" name;
9447         pr "    s[32] = 0;\n";
9448         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9449         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9450         pr "  }\n";
9451     | name, FBuffer ->
9452         pr "  {\n";
9453         pr "    int len = r->%s_len;\n" name;
9454         pr "    char s[len+1];\n";
9455         pr "    memcpy (s, r->%s, len);\n" name;
9456         pr "    s[len] = 0;\n";
9457         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9458         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9459         pr "  }\n";
9460     | name, (FBytes|FUInt64|FInt64) ->
9461         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9462         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9463     | name, (FUInt32|FInt32) ->
9464         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9465         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9466     | name, FOptPercent ->
9467         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9468         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9469     | name, FChar ->
9470         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9471         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9472   ) cols;
9473   pr "  free (r);\n";
9474   pr "  return jr;\n"
9475
9476 and generate_java_struct_list_return typ jtyp cols =
9477   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9478   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9479   pr "  for (i = 0; i < r->len; ++i) {\n";
9480   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9481   List.iter (
9482     function
9483     | name, FString ->
9484         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9485         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9486     | name, FUUID ->
9487         pr "    {\n";
9488         pr "      char s[33];\n";
9489         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9490         pr "      s[32] = 0;\n";
9491         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9492         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9493         pr "    }\n";
9494     | name, FBuffer ->
9495         pr "    {\n";
9496         pr "      int len = r->val[i].%s_len;\n" name;
9497         pr "      char s[len+1];\n";
9498         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9499         pr "      s[len] = 0;\n";
9500         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9501         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9502         pr "    }\n";
9503     | name, (FBytes|FUInt64|FInt64) ->
9504         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9505         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9506     | name, (FUInt32|FInt32) ->
9507         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9508         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9509     | name, FOptPercent ->
9510         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9511         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9512     | name, FChar ->
9513         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9514         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9515   ) cols;
9516   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9517   pr "  }\n";
9518   pr "  guestfs_free_%s_list (r);\n" typ;
9519   pr "  return jr;\n"
9520
9521 and generate_java_makefile_inc () =
9522   generate_header HashStyle GPLv2;
9523
9524   pr "java_built_sources = \\\n";
9525   List.iter (
9526     fun (typ, jtyp) ->
9527         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9528   ) java_structs;
9529   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9530
9531 and generate_haskell_hs () =
9532   generate_header HaskellStyle LGPLv2;
9533
9534   (* XXX We only know how to generate partial FFI for Haskell
9535    * at the moment.  Please help out!
9536    *)
9537   let can_generate style =
9538     match style with
9539     | RErr, _
9540     | RInt _, _
9541     | RInt64 _, _ -> true
9542     | RBool _, _
9543     | RConstString _, _
9544     | RConstOptString _, _
9545     | RString _, _
9546     | RStringList _, _
9547     | RStruct _, _
9548     | RStructList _, _
9549     | RHashtable _, _
9550     | RBufferOut _, _ -> false in
9551
9552   pr "\
9553 {-# INCLUDE <guestfs.h> #-}
9554 {-# LANGUAGE ForeignFunctionInterface #-}
9555
9556 module Guestfs (
9557   create";
9558
9559   (* List out the names of the actions we want to export. *)
9560   List.iter (
9561     fun (name, style, _, _, _, _, _) ->
9562       if can_generate style then pr ",\n  %s" name
9563   ) all_functions;
9564
9565   pr "
9566   ) where
9567
9568 -- Unfortunately some symbols duplicate ones already present
9569 -- in Prelude.  We don't know which, so we hard-code a list
9570 -- here.
9571 import Prelude hiding (truncate)
9572
9573 import Foreign
9574 import Foreign.C
9575 import Foreign.C.Types
9576 import IO
9577 import Control.Exception
9578 import Data.Typeable
9579
9580 data GuestfsS = GuestfsS            -- represents the opaque C struct
9581 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9582 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9583
9584 -- XXX define properly later XXX
9585 data PV = PV
9586 data VG = VG
9587 data LV = LV
9588 data IntBool = IntBool
9589 data Stat = Stat
9590 data StatVFS = StatVFS
9591 data Hashtable = Hashtable
9592
9593 foreign import ccall unsafe \"guestfs_create\" c_create
9594   :: IO GuestfsP
9595 foreign import ccall unsafe \"&guestfs_close\" c_close
9596   :: FunPtr (GuestfsP -> IO ())
9597 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9598   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9599
9600 create :: IO GuestfsH
9601 create = do
9602   p <- c_create
9603   c_set_error_handler p nullPtr nullPtr
9604   h <- newForeignPtr c_close p
9605   return h
9606
9607 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9608   :: GuestfsP -> IO CString
9609
9610 -- last_error :: GuestfsH -> IO (Maybe String)
9611 -- last_error h = do
9612 --   str <- withForeignPtr h (\\p -> c_last_error p)
9613 --   maybePeek peekCString str
9614
9615 last_error :: GuestfsH -> IO (String)
9616 last_error h = do
9617   str <- withForeignPtr h (\\p -> c_last_error p)
9618   if (str == nullPtr)
9619     then return \"no error\"
9620     else peekCString str
9621
9622 ";
9623
9624   (* Generate wrappers for each foreign function. *)
9625   List.iter (
9626     fun (name, style, _, _, _, _, _) ->
9627       if can_generate style then (
9628         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9629         pr "  :: ";
9630         generate_haskell_prototype ~handle:"GuestfsP" style;
9631         pr "\n";
9632         pr "\n";
9633         pr "%s :: " name;
9634         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9635         pr "\n";
9636         pr "%s %s = do\n" name
9637           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9638         pr "  r <- ";
9639         (* Convert pointer arguments using with* functions. *)
9640         List.iter (
9641           function
9642           | FileIn n
9643           | FileOut n
9644           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9645           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9646           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9647           | Bool _ | Int _ | Int64 _ -> ()
9648         ) (snd style);
9649         (* Convert integer arguments. *)
9650         let args =
9651           List.map (
9652             function
9653             | Bool n -> sprintf "(fromBool %s)" n
9654             | Int n -> sprintf "(fromIntegral %s)" n
9655             | Int64 n -> sprintf "(fromIntegral %s)" n
9656             | FileIn n | FileOut n
9657             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9658           ) (snd style) in
9659         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9660           (String.concat " " ("p" :: args));
9661         (match fst style with
9662          | RErr | RInt _ | RInt64 _ | RBool _ ->
9663              pr "  if (r == -1)\n";
9664              pr "    then do\n";
9665              pr "      err <- last_error h\n";
9666              pr "      fail err\n";
9667          | RConstString _ | RConstOptString _ | RString _
9668          | RStringList _ | RStruct _
9669          | RStructList _ | RHashtable _ | RBufferOut _ ->
9670              pr "  if (r == nullPtr)\n";
9671              pr "    then do\n";
9672              pr "      err <- last_error h\n";
9673              pr "      fail err\n";
9674         );
9675         (match fst style with
9676          | RErr ->
9677              pr "    else return ()\n"
9678          | RInt _ ->
9679              pr "    else return (fromIntegral r)\n"
9680          | RInt64 _ ->
9681              pr "    else return (fromIntegral r)\n"
9682          | RBool _ ->
9683              pr "    else return (toBool r)\n"
9684          | RConstString _
9685          | RConstOptString _
9686          | RString _
9687          | RStringList _
9688          | RStruct _
9689          | RStructList _
9690          | RHashtable _
9691          | RBufferOut _ ->
9692              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9693         );
9694         pr "\n";
9695       )
9696   ) all_functions
9697
9698 and generate_haskell_prototype ~handle ?(hs = false) style =
9699   pr "%s -> " handle;
9700   let string = if hs then "String" else "CString" in
9701   let int = if hs then "Int" else "CInt" in
9702   let bool = if hs then "Bool" else "CInt" in
9703   let int64 = if hs then "Integer" else "Int64" in
9704   List.iter (
9705     fun arg ->
9706       (match arg with
9707        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9708        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9709        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9710        | Bool _ -> pr "%s" bool
9711        | Int _ -> pr "%s" int
9712        | Int64 _ -> pr "%s" int
9713        | FileIn _ -> pr "%s" string
9714        | FileOut _ -> pr "%s" string
9715       );
9716       pr " -> ";
9717   ) (snd style);
9718   pr "IO (";
9719   (match fst style with
9720    | RErr -> if not hs then pr "CInt"
9721    | RInt _ -> pr "%s" int
9722    | RInt64 _ -> pr "%s" int64
9723    | RBool _ -> pr "%s" bool
9724    | RConstString _ -> pr "%s" string
9725    | RConstOptString _ -> pr "Maybe %s" string
9726    | RString _ -> pr "%s" string
9727    | RStringList _ -> pr "[%s]" string
9728    | RStruct (_, typ) ->
9729        let name = java_name_of_struct typ in
9730        pr "%s" name
9731    | RStructList (_, typ) ->
9732        let name = java_name_of_struct typ in
9733        pr "[%s]" name
9734    | RHashtable _ -> pr "Hashtable"
9735    | RBufferOut _ -> pr "%s" string
9736   );
9737   pr ")"
9738
9739 and generate_bindtests () =
9740   generate_header CStyle LGPLv2;
9741
9742   pr "\
9743 #include <stdio.h>
9744 #include <stdlib.h>
9745 #include <inttypes.h>
9746 #include <string.h>
9747
9748 #include \"guestfs.h\"
9749 #include \"guestfs-internal.h\"
9750 #include \"guestfs-internal-actions.h\"
9751 #include \"guestfs_protocol.h\"
9752
9753 #define error guestfs_error
9754 #define safe_calloc guestfs_safe_calloc
9755 #define safe_malloc guestfs_safe_malloc
9756
9757 static void
9758 print_strings (char *const *argv)
9759 {
9760   int argc;
9761
9762   printf (\"[\");
9763   for (argc = 0; argv[argc] != NULL; ++argc) {
9764     if (argc > 0) printf (\", \");
9765     printf (\"\\\"%%s\\\"\", argv[argc]);
9766   }
9767   printf (\"]\\n\");
9768 }
9769
9770 /* The test0 function prints its parameters to stdout. */
9771 ";
9772
9773   let test0, tests =
9774     match test_functions with
9775     | [] -> assert false
9776     | test0 :: tests -> test0, tests in
9777
9778   let () =
9779     let (name, style, _, _, _, _, _) = test0 in
9780     generate_prototype ~extern:false ~semicolon:false ~newline:true
9781       ~handle:"g" ~prefix:"guestfs__" name style;
9782     pr "{\n";
9783     List.iter (
9784       function
9785       | Pathname n
9786       | Device n | Dev_or_Path n
9787       | String n
9788       | FileIn n
9789       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9790       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9791       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9792       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9793       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9794       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9795     ) (snd style);
9796     pr "  /* Java changes stdout line buffering so we need this: */\n";
9797     pr "  fflush (stdout);\n";
9798     pr "  return 0;\n";
9799     pr "}\n";
9800     pr "\n" in
9801
9802   List.iter (
9803     fun (name, style, _, _, _, _, _) ->
9804       if String.sub name (String.length name - 3) 3 <> "err" then (
9805         pr "/* Test normal return. */\n";
9806         generate_prototype ~extern:false ~semicolon:false ~newline:true
9807           ~handle:"g" ~prefix:"guestfs__" name style;
9808         pr "{\n";
9809         (match fst style with
9810          | RErr ->
9811              pr "  return 0;\n"
9812          | RInt _ ->
9813              pr "  int r;\n";
9814              pr "  sscanf (val, \"%%d\", &r);\n";
9815              pr "  return r;\n"
9816          | RInt64 _ ->
9817              pr "  int64_t r;\n";
9818              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9819              pr "  return r;\n"
9820          | RBool _ ->
9821              pr "  return STREQ (val, \"true\");\n"
9822          | RConstString _
9823          | RConstOptString _ ->
9824              (* Can't return the input string here.  Return a static
9825               * string so we ensure we get a segfault if the caller
9826               * tries to free it.
9827               *)
9828              pr "  return \"static string\";\n"
9829          | RString _ ->
9830              pr "  return strdup (val);\n"
9831          | RStringList _ ->
9832              pr "  char **strs;\n";
9833              pr "  int n, i;\n";
9834              pr "  sscanf (val, \"%%d\", &n);\n";
9835              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9836              pr "  for (i = 0; i < n; ++i) {\n";
9837              pr "    strs[i] = safe_malloc (g, 16);\n";
9838              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9839              pr "  }\n";
9840              pr "  strs[n] = NULL;\n";
9841              pr "  return strs;\n"
9842          | RStruct (_, typ) ->
9843              pr "  struct guestfs_%s *r;\n" typ;
9844              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9845              pr "  return r;\n"
9846          | RStructList (_, typ) ->
9847              pr "  struct guestfs_%s_list *r;\n" typ;
9848              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9849              pr "  sscanf (val, \"%%d\", &r->len);\n";
9850              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9851              pr "  return r;\n"
9852          | RHashtable _ ->
9853              pr "  char **strs;\n";
9854              pr "  int n, i;\n";
9855              pr "  sscanf (val, \"%%d\", &n);\n";
9856              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9857              pr "  for (i = 0; i < n; ++i) {\n";
9858              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9859              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9860              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9861              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9862              pr "  }\n";
9863              pr "  strs[n*2] = NULL;\n";
9864              pr "  return strs;\n"
9865          | RBufferOut _ ->
9866              pr "  return strdup (val);\n"
9867         );
9868         pr "}\n";
9869         pr "\n"
9870       ) else (
9871         pr "/* Test error return. */\n";
9872         generate_prototype ~extern:false ~semicolon:false ~newline:true
9873           ~handle:"g" ~prefix:"guestfs__" name style;
9874         pr "{\n";
9875         pr "  error (g, \"error\");\n";
9876         (match fst style with
9877          | RErr | RInt _ | RInt64 _ | RBool _ ->
9878              pr "  return -1;\n"
9879          | RConstString _ | RConstOptString _
9880          | RString _ | RStringList _ | RStruct _
9881          | RStructList _
9882          | RHashtable _
9883          | RBufferOut _ ->
9884              pr "  return NULL;\n"
9885         );
9886         pr "}\n";
9887         pr "\n"
9888       )
9889   ) tests
9890
9891 and generate_ocaml_bindtests () =
9892   generate_header OCamlStyle GPLv2;
9893
9894   pr "\
9895 let () =
9896   let g = Guestfs.create () in
9897 ";
9898
9899   let mkargs args =
9900     String.concat " " (
9901       List.map (
9902         function
9903         | CallString s -> "\"" ^ s ^ "\""
9904         | CallOptString None -> "None"
9905         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9906         | CallStringList xs ->
9907             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9908         | CallInt i when i >= 0 -> string_of_int i
9909         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9910         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9911         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9912         | CallBool b -> string_of_bool b
9913       ) args
9914     )
9915   in
9916
9917   generate_lang_bindtests (
9918     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9919   );
9920
9921   pr "print_endline \"EOF\"\n"
9922
9923 and generate_perl_bindtests () =
9924   pr "#!/usr/bin/perl -w\n";
9925   generate_header HashStyle GPLv2;
9926
9927   pr "\
9928 use strict;
9929
9930 use Sys::Guestfs;
9931
9932 my $g = Sys::Guestfs->new ();
9933 ";
9934
9935   let mkargs args =
9936     String.concat ", " (
9937       List.map (
9938         function
9939         | CallString s -> "\"" ^ s ^ "\""
9940         | CallOptString None -> "undef"
9941         | CallOptString (Some s) -> sprintf "\"%s\"" s
9942         | CallStringList xs ->
9943             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9944         | CallInt i -> string_of_int i
9945         | CallInt64 i -> Int64.to_string i
9946         | CallBool b -> if b then "1" else "0"
9947       ) args
9948     )
9949   in
9950
9951   generate_lang_bindtests (
9952     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9953   );
9954
9955   pr "print \"EOF\\n\"\n"
9956
9957 and generate_python_bindtests () =
9958   generate_header HashStyle GPLv2;
9959
9960   pr "\
9961 import guestfs
9962
9963 g = guestfs.GuestFS ()
9964 ";
9965
9966   let mkargs args =
9967     String.concat ", " (
9968       List.map (
9969         function
9970         | CallString s -> "\"" ^ s ^ "\""
9971         | CallOptString None -> "None"
9972         | CallOptString (Some s) -> sprintf "\"%s\"" s
9973         | CallStringList xs ->
9974             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9975         | CallInt i -> string_of_int i
9976         | CallInt64 i -> Int64.to_string i
9977         | CallBool b -> if b then "1" else "0"
9978       ) args
9979     )
9980   in
9981
9982   generate_lang_bindtests (
9983     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9984   );
9985
9986   pr "print \"EOF\"\n"
9987
9988 and generate_ruby_bindtests () =
9989   generate_header HashStyle GPLv2;
9990
9991   pr "\
9992 require 'guestfs'
9993
9994 g = Guestfs::create()
9995 ";
9996
9997   let mkargs args =
9998     String.concat ", " (
9999       List.map (
10000         function
10001         | CallString s -> "\"" ^ s ^ "\""
10002         | CallOptString None -> "nil"
10003         | CallOptString (Some s) -> sprintf "\"%s\"" s
10004         | CallStringList xs ->
10005             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10006         | CallInt i -> string_of_int i
10007         | CallInt64 i -> Int64.to_string i
10008         | CallBool b -> string_of_bool b
10009       ) args
10010     )
10011   in
10012
10013   generate_lang_bindtests (
10014     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10015   );
10016
10017   pr "print \"EOF\\n\"\n"
10018
10019 and generate_java_bindtests () =
10020   generate_header CStyle GPLv2;
10021
10022   pr "\
10023 import com.redhat.et.libguestfs.*;
10024
10025 public class Bindtests {
10026     public static void main (String[] argv)
10027     {
10028         try {
10029             GuestFS g = new GuestFS ();
10030 ";
10031
10032   let mkargs args =
10033     String.concat ", " (
10034       List.map (
10035         function
10036         | CallString s -> "\"" ^ s ^ "\""
10037         | CallOptString None -> "null"
10038         | CallOptString (Some s) -> sprintf "\"%s\"" s
10039         | CallStringList xs ->
10040             "new String[]{" ^
10041               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10042         | CallInt i -> string_of_int i
10043         | CallInt64 i -> Int64.to_string i
10044         | CallBool b -> string_of_bool b
10045       ) args
10046     )
10047   in
10048
10049   generate_lang_bindtests (
10050     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10051   );
10052
10053   pr "
10054             System.out.println (\"EOF\");
10055         }
10056         catch (Exception exn) {
10057             System.err.println (exn);
10058             System.exit (1);
10059         }
10060     }
10061 }
10062 "
10063
10064 and generate_haskell_bindtests () =
10065   generate_header HaskellStyle GPLv2;
10066
10067   pr "\
10068 module Bindtests where
10069 import qualified Guestfs
10070
10071 main = do
10072   g <- Guestfs.create
10073 ";
10074
10075   let mkargs args =
10076     String.concat " " (
10077       List.map (
10078         function
10079         | CallString s -> "\"" ^ s ^ "\""
10080         | CallOptString None -> "Nothing"
10081         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10082         | CallStringList xs ->
10083             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10084         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10085         | CallInt i -> string_of_int i
10086         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10087         | CallInt64 i -> Int64.to_string i
10088         | CallBool true -> "True"
10089         | CallBool false -> "False"
10090       ) args
10091     )
10092   in
10093
10094   generate_lang_bindtests (
10095     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10096   );
10097
10098   pr "  putStrLn \"EOF\"\n"
10099
10100 (* Language-independent bindings tests - we do it this way to
10101  * ensure there is parity in testing bindings across all languages.
10102  *)
10103 and generate_lang_bindtests call =
10104   call "test0" [CallString "abc"; CallOptString (Some "def");
10105                 CallStringList []; CallBool false;
10106                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10107   call "test0" [CallString "abc"; CallOptString None;
10108                 CallStringList []; CallBool false;
10109                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10110   call "test0" [CallString ""; CallOptString (Some "def");
10111                 CallStringList []; CallBool false;
10112                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10113   call "test0" [CallString ""; CallOptString (Some "");
10114                 CallStringList []; CallBool false;
10115                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10116   call "test0" [CallString "abc"; CallOptString (Some "def");
10117                 CallStringList ["1"]; CallBool false;
10118                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10119   call "test0" [CallString "abc"; CallOptString (Some "def");
10120                 CallStringList ["1"; "2"]; CallBool false;
10121                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10122   call "test0" [CallString "abc"; CallOptString (Some "def");
10123                 CallStringList ["1"]; CallBool true;
10124                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10125   call "test0" [CallString "abc"; CallOptString (Some "def");
10126                 CallStringList ["1"]; CallBool false;
10127                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10128   call "test0" [CallString "abc"; CallOptString (Some "def");
10129                 CallStringList ["1"]; CallBool false;
10130                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10131   call "test0" [CallString "abc"; CallOptString (Some "def");
10132                 CallStringList ["1"]; CallBool false;
10133                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10134   call "test0" [CallString "abc"; CallOptString (Some "def");
10135                 CallStringList ["1"]; CallBool false;
10136                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10137   call "test0" [CallString "abc"; CallOptString (Some "def");
10138                 CallStringList ["1"]; CallBool false;
10139                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10140   call "test0" [CallString "abc"; CallOptString (Some "def");
10141                 CallStringList ["1"]; CallBool false;
10142                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10143
10144 (* XXX Add here tests of the return and error functions. *)
10145
10146 (* This is used to generate the src/MAX_PROC_NR file which
10147  * contains the maximum procedure number, a surrogate for the
10148  * ABI version number.  See src/Makefile.am for the details.
10149  *)
10150 and generate_max_proc_nr () =
10151   let proc_nrs = List.map (
10152     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10153   ) daemon_functions in
10154
10155   let max_proc_nr = List.fold_left max 0 proc_nrs in
10156
10157   pr "%d\n" max_proc_nr
10158
10159 let output_to filename =
10160   let filename_new = filename ^ ".new" in
10161   chan := open_out filename_new;
10162   let close () =
10163     close_out !chan;
10164     chan := stdout;
10165
10166     (* Is the new file different from the current file? *)
10167     if Sys.file_exists filename && files_equal filename filename_new then
10168       Unix.unlink filename_new          (* same, so skip it *)
10169     else (
10170       (* different, overwrite old one *)
10171       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
10172       Unix.rename filename_new filename;
10173       Unix.chmod filename 0o444;
10174       printf "written %s\n%!" filename;
10175     )
10176   in
10177   close
10178
10179 (* Main program. *)
10180 let () =
10181   check_functions ();
10182
10183   if not (Sys.file_exists "HACKING") then (
10184     eprintf "\
10185 You are probably running this from the wrong directory.
10186 Run it from the top source directory using the command
10187   src/generator.ml
10188 ";
10189     exit 1
10190   );
10191
10192   let close = output_to "src/guestfs_protocol.x" in
10193   generate_xdr ();
10194   close ();
10195
10196   let close = output_to "src/guestfs-structs.h" in
10197   generate_structs_h ();
10198   close ();
10199
10200   let close = output_to "src/guestfs-actions.h" in
10201   generate_actions_h ();
10202   close ();
10203
10204   let close = output_to "src/guestfs-internal-actions.h" in
10205   generate_internal_actions_h ();
10206   close ();
10207
10208   let close = output_to "src/guestfs-actions.c" in
10209   generate_client_actions ();
10210   close ();
10211
10212   let close = output_to "daemon/actions.h" in
10213   generate_daemon_actions_h ();
10214   close ();
10215
10216   let close = output_to "daemon/stubs.c" in
10217   generate_daemon_actions ();
10218   close ();
10219
10220   let close = output_to "daemon/names.c" in
10221   generate_daemon_names ();
10222   close ();
10223
10224   let close = output_to "capitests/tests.c" in
10225   generate_tests ();
10226   close ();
10227
10228   let close = output_to "src/guestfs-bindtests.c" in
10229   generate_bindtests ();
10230   close ();
10231
10232   let close = output_to "fish/cmds.c" in
10233   generate_fish_cmds ();
10234   close ();
10235
10236   let close = output_to "fish/completion.c" in
10237   generate_fish_completion ();
10238   close ();
10239
10240   let close = output_to "guestfs-structs.pod" in
10241   generate_structs_pod ();
10242   close ();
10243
10244   let close = output_to "guestfs-actions.pod" in
10245   generate_actions_pod ();
10246   close ();
10247
10248   let close = output_to "guestfish-actions.pod" in
10249   generate_fish_actions_pod ();
10250   close ();
10251
10252   let close = output_to "ocaml/guestfs.mli" in
10253   generate_ocaml_mli ();
10254   close ();
10255
10256   let close = output_to "ocaml/guestfs.ml" in
10257   generate_ocaml_ml ();
10258   close ();
10259
10260   let close = output_to "ocaml/guestfs_c_actions.c" in
10261   generate_ocaml_c ();
10262   close ();
10263
10264   let close = output_to "ocaml/bindtests.ml" in
10265   generate_ocaml_bindtests ();
10266   close ();
10267
10268   let close = output_to "perl/Guestfs.xs" in
10269   generate_perl_xs ();
10270   close ();
10271
10272   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10273   generate_perl_pm ();
10274   close ();
10275
10276   let close = output_to "perl/bindtests.pl" in
10277   generate_perl_bindtests ();
10278   close ();
10279
10280   let close = output_to "python/guestfs-py.c" in
10281   generate_python_c ();
10282   close ();
10283
10284   let close = output_to "python/guestfs.py" in
10285   generate_python_py ();
10286   close ();
10287
10288   let close = output_to "python/bindtests.py" in
10289   generate_python_bindtests ();
10290   close ();
10291
10292   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10293   generate_ruby_c ();
10294   close ();
10295
10296   let close = output_to "ruby/bindtests.rb" in
10297   generate_ruby_bindtests ();
10298   close ();
10299
10300   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10301   generate_java_java ();
10302   close ();
10303
10304   List.iter (
10305     fun (typ, jtyp) ->
10306       let cols = cols_of_struct typ in
10307       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10308       let close = output_to filename in
10309       generate_java_struct jtyp cols;
10310       close ();
10311   ) java_structs;
10312
10313   let close = output_to "java/Makefile.inc" in
10314   generate_java_makefile_inc ();
10315   close ();
10316
10317   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10318   generate_java_c ();
10319   close ();
10320
10321   let close = output_to "java/Bindtests.java" in
10322   generate_java_bindtests ();
10323   close ();
10324
10325   let close = output_to "haskell/Guestfs.hs" in
10326   generate_haskell_hs ();
10327   close ();
10328
10329   let close = output_to "haskell/Bindtests.hs" in
10330   generate_haskell_bindtests ();
10331   close ();
10332
10333   let close = output_to "src/MAX_PROC_NR" in
10334   generate_max_proc_nr ();
10335   close ();
10336
10337   (* Always generate this file last, and unconditionally.  It's used
10338    * by the Makefile to know when we must re-run the generator.
10339    *)
10340   let chan = open_out "src/stamp-generator" in
10341   fprintf chan "1\n";
10342   close_out chan