New API calls: lstatlist, lxattrlist, readlinklist.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145   | Int64 of string     (* any 64 bit int *)
146     (* These are treated as filenames (simple string parameters) in
147      * the C API and bindings.  But in the RPC protocol, we transfer
148      * the actual file content up to or down from the daemon.
149      * FileIn: local machine -> daemon (in request)
150      * FileOut: daemon -> local machine (in reply)
151      * In guestfish (only), the special name "-" means read from
152      * stdin or write to stdout.
153      *)
154   | FileIn of string
155   | FileOut of string
156 (* Not implemented:
157     (* Opaque buffer which can contain arbitrary 8 bit data.
158      * In the C API, this is expressed as <char *, int> pair.
159      * Most other languages have a string type which can contain
160      * ASCII NUL.  We use whatever type is appropriate for each
161      * language.
162      * Buffers are limited by the total message size.  To transfer
163      * large blocks of data, use FileIn/FileOut parameters instead.
164      * To return an arbitrary buffer, use RBufferOut.
165      *)
166   | BufferIn of string
167 *)
168
169 type flags =
170   | ProtocolLimitWarning  (* display warning about protocol size limits *)
171   | DangerWillRobinson    (* flags particularly dangerous commands *)
172   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
173   | FishAction of string  (* call this function in guestfish *)
174   | NotInFish             (* do not export via guestfish *)
175   | NotInDocs             (* do not add this function to documentation *)
176   | DeprecatedBy of string (* function is deprecated, use .. instead *)
177
178 (* You can supply zero or as many tests as you want per API call.
179  *
180  * Note that the test environment has 3 block devices, of size 500MB,
181  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
182  * a fourth ISO block device with some known files on it (/dev/sdd).
183  *
184  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
185  * Number of cylinders was 63 for IDE emulated disks with precisely
186  * the same size.  How exactly this is calculated is a mystery.
187  *
188  * The ISO block device (/dev/sdd) comes from images/test.iso.
189  *
190  * To be able to run the tests in a reasonable amount of time,
191  * the virtual machine and block devices are reused between tests.
192  * So don't try testing kill_subprocess :-x
193  *
194  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
195  *
196  * Don't assume anything about the previous contents of the block
197  * devices.  Use 'Init*' to create some initial scenarios.
198  *
199  * You can add a prerequisite clause to any individual test.  This
200  * is a run-time check, which, if it fails, causes the test to be
201  * skipped.  Useful if testing a command which might not work on
202  * all variations of libguestfs builds.  A test that has prerequisite
203  * of 'Always' is run unconditionally.
204  *
205  * In addition, packagers can skip individual tests by setting the
206  * environment variables:     eg:
207  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
208  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
209  *)
210 type tests = (test_init * test_prereq * test) list
211 and test =
212     (* Run the command sequence and just expect nothing to fail. *)
213   | TestRun of seq
214
215     (* Run the command sequence and expect the output of the final
216      * command to be the string.
217      *)
218   | TestOutput of seq * string
219
220     (* Run the command sequence and expect the output of the final
221      * command to be the list of strings.
222      *)
223   | TestOutputList of seq * string list
224
225     (* Run the command sequence and expect the output of the final
226      * command to be the list of block devices (could be either
227      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
228      * character of each string).
229      *)
230   | TestOutputListOfDevices of seq * string list
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the integer.
234      *)
235   | TestOutputInt of seq * int
236
237     (* Run the command sequence and expect the output of the final
238      * command to be <op> <int>, eg. ">=", "1".
239      *)
240   | TestOutputIntOp of seq * string * int
241
242     (* Run the command sequence and expect the output of the final
243      * command to be a true value (!= 0 or != NULL).
244      *)
245   | TestOutputTrue of seq
246
247     (* Run the command sequence and expect the output of the final
248      * command to be a false value (== 0 or == NULL, but not an error).
249      *)
250   | TestOutputFalse of seq
251
252     (* Run the command sequence and expect the output of the final
253      * command to be a list of the given length (but don't care about
254      * content).
255      *)
256   | TestOutputLength of seq * int
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a buffer (RBufferOut), ie. string + size.
260      *)
261   | TestOutputBuffer of seq * string
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a structure.
265      *)
266   | TestOutputStruct of seq * test_field_compare list
267
268     (* Run the command sequence and expect the final command (only)
269      * to fail.
270      *)
271   | TestLastFail of seq
272
273 and test_field_compare =
274   | CompareWithInt of string * int
275   | CompareWithIntOp of string * string * int
276   | CompareWithString of string * string
277   | CompareFieldsIntEq of string * string
278   | CompareFieldsStrEq of string * string
279
280 (* Test prerequisites. *)
281 and test_prereq =
282     (* Test always runs. *)
283   | Always
284
285     (* Test is currently disabled - eg. it fails, or it tests some
286      * unimplemented feature.
287      *)
288   | Disabled
289
290     (* 'string' is some C code (a function body) that should return
291      * true or false.  The test will run if the code returns true.
292      *)
293   | If of string
294
295     (* As for 'If' but the test runs _unless_ the code returns true. *)
296   | Unless of string
297
298 (* Some initial scenarios for testing. *)
299 and test_init =
300     (* Do nothing, block devices could contain random stuff including
301      * LVM PVs, and some filesystems might be mounted.  This is usually
302      * a bad idea.
303      *)
304   | InitNone
305
306     (* Block devices are empty and no filesystems are mounted. *)
307   | InitEmpty
308
309     (* /dev/sda contains a single partition /dev/sda1, with random
310      * content.  /dev/sdb and /dev/sdc may have random content.
311      * No LVM.
312      *)
313   | InitPartition
314
315     (* /dev/sda contains a single partition /dev/sda1, which is formatted
316      * as ext2, empty [except for lost+found] and mounted on /.
317      * /dev/sdb and /dev/sdc may have random content.
318      * No LVM.
319      *)
320   | InitBasicFS
321
322     (* /dev/sda:
323      *   /dev/sda1 (is a PV):
324      *     /dev/VG/LV (size 8MB):
325      *       formatted as ext2, empty [except for lost+found], mounted on /
326      * /dev/sdb and /dev/sdc may have random content.
327      *)
328   | InitBasicFSonLVM
329
330     (* /dev/sdd (the ISO, see images/ directory in source)
331      * is mounted on /
332      *)
333   | InitISOFS
334
335 (* Sequence of commands for testing. *)
336 and seq = cmd list
337 and cmd = string list
338
339 (* Note about long descriptions: When referring to another
340  * action, use the format C<guestfs_other> (ie. the full name of
341  * the C function).  This will be replaced as appropriate in other
342  * language bindings.
343  *
344  * Apart from that, long descriptions are just perldoc paragraphs.
345  *)
346
347 (* Generate a random UUID (used in tests). *)
348 let uuidgen () =
349   let chan = Unix.open_process_in "uuidgen" in
350   let uuid = input_line chan in
351   (match Unix.close_process_in chan with
352    | Unix.WEXITED 0 -> ()
353    | Unix.WEXITED _ ->
354        failwith "uuidgen: process exited with non-zero status"
355    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
356        failwith "uuidgen: process signalled or stopped by signal"
357   );
358   uuid
359
360 (* These test functions are used in the language binding tests. *)
361
362 let test_all_args = [
363   String "str";
364   OptString "optstr";
365   StringList "strlist";
366   Bool "b";
367   Int "integer";
368   Int64 "integer64";
369   FileIn "filein";
370   FileOut "fileout";
371 ]
372
373 let test_all_rets = [
374   (* except for RErr, which is tested thoroughly elsewhere *)
375   "test0rint",         RInt "valout";
376   "test0rint64",       RInt64 "valout";
377   "test0rbool",        RBool "valout";
378   "test0rconststring", RConstString "valout";
379   "test0rconstoptstring", RConstOptString "valout";
380   "test0rstring",      RString "valout";
381   "test0rstringlist",  RStringList "valout";
382   "test0rstruct",      RStruct ("valout", "lvm_pv");
383   "test0rstructlist",  RStructList ("valout", "lvm_pv");
384   "test0rhashtable",   RHashtable "valout";
385 ]
386
387 let test_functions = [
388   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
389    [],
390    "internal test function - do not use",
391    "\
392 This is an internal test function which is used to test whether
393 the automatically generated bindings can handle every possible
394 parameter type correctly.
395
396 It echos the contents of each parameter to stdout.
397
398 You probably don't want to call this function.");
399 ] @ List.flatten (
400   List.map (
401     fun (name, ret) ->
402       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
403         [],
404         "internal test function - do not use",
405         "\
406 This is an internal test function which is used to test whether
407 the automatically generated bindings can handle every possible
408 return type correctly.
409
410 It converts string C<val> to the return type.
411
412 You probably don't want to call this function.");
413        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
414         [],
415         "internal test function - do not use",
416         "\
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
420
421 This function always returns an error.
422
423 You probably don't want to call this function.")]
424   ) test_all_rets
425 )
426
427 (* non_daemon_functions are any functions which don't get processed
428  * in the daemon, eg. functions for setting and getting local
429  * configuration values.
430  *)
431
432 let non_daemon_functions = test_functions @ [
433   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
434    [],
435    "launch the qemu subprocess",
436    "\
437 Internally libguestfs is implemented by running a virtual machine
438 using L<qemu(1)>.
439
440 You should call this after configuring the handle
441 (eg. adding drives) but before performing any actions.");
442
443   ("wait_ready", (RErr, []), -1, [NotInFish],
444    [],
445    "wait until the qemu subprocess launches (no op)",
446    "\
447 This function is a no op.
448
449 In versions of the API E<lt> 1.0.71 you had to call this function
450 just after calling C<guestfs_launch> to wait for the launch
451 to complete.  However this is no longer necessary because
452 C<guestfs_launch> now does the waiting.
453
454 If you see any calls to this function in code then you can just
455 remove them, unless you want to retain compatibility with older
456 versions of the API.");
457
458   ("kill_subprocess", (RErr, []), -1, [],
459    [],
460    "kill the qemu subprocess",
461    "\
462 This kills the qemu subprocess.  You should never need to call this.");
463
464   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
465    [],
466    "add an image to examine or modify",
467    "\
468 This function adds a virtual machine disk image C<filename> to the
469 guest.  The first time you call this function, the disk appears as IDE
470 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
471 so on.
472
473 You don't necessarily need to be root when using libguestfs.  However
474 you obviously do need sufficient permissions to access the filename
475 for whatever operations you want to perform (ie. read access if you
476 just want to read the image or write access if you want to modify the
477 image).
478
479 This is equivalent to the qemu parameter
480 C<-drive file=filename,cache=off,if=...>.
481 C<cache=off> is omitted in cases where it is not supported by
482 the underlying filesystem.
483
484 Note that this call checks for the existence of C<filename>.  This
485 stops you from specifying other types of drive which are supported
486 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
487 the general C<guestfs_config> call instead.");
488
489   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
490    [],
491    "add a CD-ROM disk image to examine",
492    "\
493 This function adds a virtual CD-ROM disk image to the guest.
494
495 This is equivalent to the qemu parameter C<-cdrom filename>.
496
497 Note that this call checks for the existence of C<filename>.  This
498 stops you from specifying other types of drive which are supported
499 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
500 the general C<guestfs_config> call instead.");
501
502   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
503    [],
504    "add a drive in snapshot mode (read-only)",
505    "\
506 This adds a drive in snapshot mode, making it effectively
507 read-only.
508
509 Note that writes to the device are allowed, and will be seen for
510 the duration of the guestfs handle, but they are written
511 to a temporary file which is discarded as soon as the guestfs
512 handle is closed.  We don't currently have any method to enable
513 changes to be committed, although qemu can support this.
514
515 This is equivalent to the qemu parameter
516 C<-drive file=filename,snapshot=on,if=...>.
517
518 Note that this call checks for the existence of C<filename>.  This
519 stops you from specifying other types of drive which are supported
520 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
521 the general C<guestfs_config> call instead.");
522
523   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
524    [],
525    "add qemu parameters",
526    "\
527 This can be used to add arbitrary qemu command line parameters
528 of the form C<-param value>.  Actually it's not quite arbitrary - we
529 prevent you from setting some parameters which would interfere with
530 parameters that we use.
531
532 The first character of C<param> string must be a C<-> (dash).
533
534 C<value> can be NULL.");
535
536   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
537    [],
538    "set the qemu binary",
539    "\
540 Set the qemu binary that we will use.
541
542 The default is chosen when the library was compiled by the
543 configure script.
544
545 You can also override this by setting the C<LIBGUESTFS_QEMU>
546 environment variable.
547
548 Setting C<qemu> to C<NULL> restores the default qemu binary.");
549
550   ("get_qemu", (RConstString "qemu", []), -1, [],
551    [InitNone, Always, TestRun (
552       [["get_qemu"]])],
553    "get the qemu binary",
554    "\
555 Return the current qemu binary.
556
557 This is always non-NULL.  If it wasn't set already, then this will
558 return the default qemu binary name.");
559
560   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
561    [],
562    "set the search path",
563    "\
564 Set the path that libguestfs searches for kernel and initrd.img.
565
566 The default is C<$libdir/guestfs> unless overridden by setting
567 C<LIBGUESTFS_PATH> environment variable.
568
569 Setting C<path> to C<NULL> restores the default path.");
570
571   ("get_path", (RConstString "path", []), -1, [],
572    [InitNone, Always, TestRun (
573       [["get_path"]])],
574    "get the search path",
575    "\
576 Return the current search path.
577
578 This is always non-NULL.  If it wasn't set already, then this will
579 return the default path.");
580
581   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
582    [],
583    "add options to kernel command line",
584    "\
585 This function is used to add additional options to the
586 guest kernel command line.
587
588 The default is C<NULL> unless overridden by setting
589 C<LIBGUESTFS_APPEND> environment variable.
590
591 Setting C<append> to C<NULL> means I<no> additional options
592 are passed (libguestfs always adds a few of its own).");
593
594   ("get_append", (RConstOptString "append", []), -1, [],
595    (* This cannot be tested with the current framework.  The
596     * function can return NULL in normal operations, which the
597     * test framework interprets as an error.
598     *)
599    [],
600    "get the additional kernel options",
601    "\
602 Return the additional kernel options which are added to the
603 guest kernel command line.
604
605 If C<NULL> then no options are added.");
606
607   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
608    [],
609    "set autosync mode",
610    "\
611 If C<autosync> is true, this enables autosync.  Libguestfs will make a
612 best effort attempt to run C<guestfs_umount_all> followed by
613 C<guestfs_sync> when the handle is closed
614 (also if the program exits without closing handles).
615
616 This is disabled by default (except in guestfish where it is
617 enabled by default).");
618
619   ("get_autosync", (RBool "autosync", []), -1, [],
620    [InitNone, Always, TestRun (
621       [["get_autosync"]])],
622    "get autosync mode",
623    "\
624 Get the autosync flag.");
625
626   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
627    [],
628    "set verbose mode",
629    "\
630 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
631
632 Verbose messages are disabled unless the environment variable
633 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
634
635   ("get_verbose", (RBool "verbose", []), -1, [],
636    [],
637    "get verbose mode",
638    "\
639 This returns the verbose messages flag.");
640
641   ("is_ready", (RBool "ready", []), -1, [],
642    [InitNone, Always, TestOutputTrue (
643       [["is_ready"]])],
644    "is ready to accept commands",
645    "\
646 This returns true iff this handle is ready to accept commands
647 (in the C<READY> state).
648
649 For more information on states, see L<guestfs(3)>.");
650
651   ("is_config", (RBool "config", []), -1, [],
652    [InitNone, Always, TestOutputFalse (
653       [["is_config"]])],
654    "is in configuration state",
655    "\
656 This returns true iff this handle is being configured
657 (in the C<CONFIG> state).
658
659 For more information on states, see L<guestfs(3)>.");
660
661   ("is_launching", (RBool "launching", []), -1, [],
662    [InitNone, Always, TestOutputFalse (
663       [["is_launching"]])],
664    "is launching subprocess",
665    "\
666 This returns true iff this handle is launching the subprocess
667 (in the C<LAUNCHING> state).
668
669 For more information on states, see L<guestfs(3)>.");
670
671   ("is_busy", (RBool "busy", []), -1, [],
672    [InitNone, Always, TestOutputFalse (
673       [["is_busy"]])],
674    "is busy processing a command",
675    "\
676 This returns true iff this handle is busy processing a command
677 (in the C<BUSY> state).
678
679 For more information on states, see L<guestfs(3)>.");
680
681   ("get_state", (RInt "state", []), -1, [],
682    [],
683    "get the current state",
684    "\
685 This returns the current state as an opaque integer.  This is
686 only useful for printing debug and internal error messages.
687
688 For more information on states, see L<guestfs(3)>.");
689
690   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
691    [InitNone, Always, TestOutputInt (
692       [["set_memsize"; "500"];
693        ["get_memsize"]], 500)],
694    "set memory allocated to the qemu subprocess",
695    "\
696 This sets the memory size in megabytes allocated to the
697 qemu subprocess.  This only has any effect if called before
698 C<guestfs_launch>.
699
700 You can also change this by setting the environment
701 variable C<LIBGUESTFS_MEMSIZE> before the handle is
702 created.
703
704 For more information on the architecture of libguestfs,
705 see L<guestfs(3)>.");
706
707   ("get_memsize", (RInt "memsize", []), -1, [],
708    [InitNone, Always, TestOutputIntOp (
709       [["get_memsize"]], ">=", 256)],
710    "get memory allocated to the qemu subprocess",
711    "\
712 This gets the memory size in megabytes allocated to the
713 qemu subprocess.
714
715 If C<guestfs_set_memsize> was not called
716 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
717 then this returns the compiled-in default value for memsize.
718
719 For more information on the architecture of libguestfs,
720 see L<guestfs(3)>.");
721
722   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
723    [InitNone, Always, TestOutputIntOp (
724       [["get_pid"]], ">=", 1)],
725    "get PID of qemu subprocess",
726    "\
727 Return the process ID of the qemu subprocess.  If there is no
728 qemu subprocess, then this will return an error.
729
730 This is an internal call used for debugging and testing.");
731
732   ("version", (RStruct ("version", "version"), []), -1, [],
733    [InitNone, Always, TestOutputStruct (
734       [["version"]], [CompareWithInt ("major", 1)])],
735    "get the library version number",
736    "\
737 Return the libguestfs version number that the program is linked
738 against.
739
740 Note that because of dynamic linking this is not necessarily
741 the version of libguestfs that you compiled against.  You can
742 compile the program, and then at runtime dynamically link
743 against a completely different C<libguestfs.so> library.
744
745 This call was added in version C<1.0.58>.  In previous
746 versions of libguestfs there was no way to get the version
747 number.  From C code you can use ELF weak linking tricks to find out if
748 this symbol exists (if it doesn't, then it's an earlier version).
749
750 The call returns a structure with four elements.  The first
751 three (C<major>, C<minor> and C<release>) are numbers and
752 correspond to the usual version triplet.  The fourth element
753 (C<extra>) is a string and is normally empty, but may be
754 used for distro-specific information.
755
756 To construct the original version string:
757 C<$major.$minor.$release$extra>
758
759 I<Note:> Don't use this call to test for availability
760 of features.  Distro backports makes this unreliable.");
761
762   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
763    [InitNone, Always, TestOutputTrue (
764       [["set_selinux"; "true"];
765        ["get_selinux"]])],
766    "set SELinux enabled or disabled at appliance boot",
767    "\
768 This sets the selinux flag that is passed to the appliance
769 at boot time.  The default is C<selinux=0> (disabled).
770
771 Note that if SELinux is enabled, it is always in
772 Permissive mode (C<enforcing=0>).
773
774 For more information on the architecture of libguestfs,
775 see L<guestfs(3)>.");
776
777   ("get_selinux", (RBool "selinux", []), -1, [],
778    [],
779    "get SELinux enabled flag",
780    "\
781 This returns the current setting of the selinux flag which
782 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
783
784 For more information on the architecture of libguestfs,
785 see L<guestfs(3)>.");
786
787   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
788    [InitNone, Always, TestOutputFalse (
789       [["set_trace"; "false"];
790        ["get_trace"]])],
791    "enable or disable command traces",
792    "\
793 If the command trace flag is set to 1, then commands are
794 printed on stdout before they are executed in a format
795 which is very similar to the one used by guestfish.  In
796 other words, you can run a program with this enabled, and
797 you will get out a script which you can feed to guestfish
798 to perform the same set of actions.
799
800 If you want to trace C API calls into libguestfs (and
801 other libraries) then possibly a better way is to use
802 the external ltrace(1) command.
803
804 Command traces are disabled unless the environment variable
805 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
806
807   ("get_trace", (RBool "trace", []), -1, [],
808    [],
809    "get command trace enabled flag",
810    "\
811 Return the command trace flag.");
812
813   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
814    [InitNone, Always, TestOutputFalse (
815       [["set_direct"; "false"];
816        ["get_direct"]])],
817    "enable or disable direct appliance mode",
818    "\
819 If the direct appliance mode flag is enabled, then stdin and
820 stdout are passed directly through to the appliance once it
821 is launched.
822
823 One consequence of this is that log messages aren't caught
824 by the library and handled by C<guestfs_set_log_message_callback>,
825 but go straight to stdout.
826
827 You probably don't want to use this unless you know what you
828 are doing.
829
830 The default is disabled.");
831
832   ("get_direct", (RBool "direct", []), -1, [],
833    [],
834    "get direct appliance mode flag",
835    "\
836 Return the direct appliance mode flag.");
837
838 ]
839
840 (* daemon_functions are any functions which cause some action
841  * to take place in the daemon.
842  *)
843
844 let daemon_functions = [
845   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
846    [InitEmpty, Always, TestOutput (
847       [["sfdiskM"; "/dev/sda"; ","];
848        ["mkfs"; "ext2"; "/dev/sda1"];
849        ["mount"; "/dev/sda1"; "/"];
850        ["write_file"; "/new"; "new file contents"; "0"];
851        ["cat"; "/new"]], "new file contents")],
852    "mount a guest disk at a position in the filesystem",
853    "\
854 Mount a guest disk at a position in the filesystem.  Block devices
855 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
856 the guest.  If those block devices contain partitions, they will have
857 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
858 names can be used.
859
860 The rules are the same as for L<mount(2)>:  A filesystem must
861 first be mounted on C</> before others can be mounted.  Other
862 filesystems can only be mounted on directories which already
863 exist.
864
865 The mounted filesystem is writable, if we have sufficient permissions
866 on the underlying device.
867
868 The filesystem options C<sync> and C<noatime> are set with this
869 call, in order to improve reliability.");
870
871   ("sync", (RErr, []), 2, [],
872    [ InitEmpty, Always, TestRun [["sync"]]],
873    "sync disks, writes are flushed through to the disk image",
874    "\
875 This syncs the disk, so that any writes are flushed through to the
876 underlying disk image.
877
878 You should always call this if you have modified a disk image, before
879 closing the handle.");
880
881   ("touch", (RErr, [Pathname "path"]), 3, [],
882    [InitBasicFS, Always, TestOutputTrue (
883       [["touch"; "/new"];
884        ["exists"; "/new"]])],
885    "update file timestamps or create a new file",
886    "\
887 Touch acts like the L<touch(1)> command.  It can be used to
888 update the timestamps on a file, or, if the file does not exist,
889 to create a new zero-length file.");
890
891   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
892    [InitISOFS, Always, TestOutput (
893       [["cat"; "/known-2"]], "abcdef\n")],
894    "list the contents of a file",
895    "\
896 Return the contents of the file named C<path>.
897
898 Note that this function cannot correctly handle binary files
899 (specifically, files containing C<\\0> character which is treated
900 as end of string).  For those you need to use the C<guestfs_read_file>
901 or C<guestfs_download> functions which have a more complex interface.");
902
903   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
904    [], (* XXX Tricky to test because it depends on the exact format
905         * of the 'ls -l' command, which changes between F10 and F11.
906         *)
907    "list the files in a directory (long format)",
908    "\
909 List the files in C<directory> (relative to the root directory,
910 there is no cwd) in the format of 'ls -la'.
911
912 This command is mostly useful for interactive sessions.  It
913 is I<not> intended that you try to parse the output string.");
914
915   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
916    [InitBasicFS, Always, TestOutputList (
917       [["touch"; "/new"];
918        ["touch"; "/newer"];
919        ["touch"; "/newest"];
920        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
921    "list the files in a directory",
922    "\
923 List the files in C<directory> (relative to the root directory,
924 there is no cwd).  The '.' and '..' entries are not returned, but
925 hidden files are shown.
926
927 This command is mostly useful for interactive sessions.  Programs
928 should probably use C<guestfs_readdir> instead.");
929
930   ("list_devices", (RStringList "devices", []), 7, [],
931    [InitEmpty, Always, TestOutputListOfDevices (
932       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
933    "list the block devices",
934    "\
935 List all the block devices.
936
937 The full block device names are returned, eg. C</dev/sda>");
938
939   ("list_partitions", (RStringList "partitions", []), 8, [],
940    [InitBasicFS, Always, TestOutputListOfDevices (
941       [["list_partitions"]], ["/dev/sda1"]);
942     InitEmpty, Always, TestOutputListOfDevices (
943       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
944        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
945    "list the partitions",
946    "\
947 List all the partitions detected on all block devices.
948
949 The full partition device names are returned, eg. C</dev/sda1>
950
951 This does not return logical volumes.  For that you will need to
952 call C<guestfs_lvs>.");
953
954   ("pvs", (RStringList "physvols", []), 9, [],
955    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
956       [["pvs"]], ["/dev/sda1"]);
957     InitEmpty, Always, TestOutputListOfDevices (
958       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
959        ["pvcreate"; "/dev/sda1"];
960        ["pvcreate"; "/dev/sda2"];
961        ["pvcreate"; "/dev/sda3"];
962        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
963    "list the LVM physical volumes (PVs)",
964    "\
965 List all the physical volumes detected.  This is the equivalent
966 of the L<pvs(8)> command.
967
968 This returns a list of just the device names that contain
969 PVs (eg. C</dev/sda2>).
970
971 See also C<guestfs_pvs_full>.");
972
973   ("vgs", (RStringList "volgroups", []), 10, [],
974    [InitBasicFSonLVM, Always, TestOutputList (
975       [["vgs"]], ["VG"]);
976     InitEmpty, Always, TestOutputList (
977       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
978        ["pvcreate"; "/dev/sda1"];
979        ["pvcreate"; "/dev/sda2"];
980        ["pvcreate"; "/dev/sda3"];
981        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
982        ["vgcreate"; "VG2"; "/dev/sda3"];
983        ["vgs"]], ["VG1"; "VG2"])],
984    "list the LVM volume groups (VGs)",
985    "\
986 List all the volumes groups detected.  This is the equivalent
987 of the L<vgs(8)> command.
988
989 This returns a list of just the volume group names that were
990 detected (eg. C<VolGroup00>).
991
992 See also C<guestfs_vgs_full>.");
993
994   ("lvs", (RStringList "logvols", []), 11, [],
995    [InitBasicFSonLVM, Always, TestOutputList (
996       [["lvs"]], ["/dev/VG/LV"]);
997     InitEmpty, Always, TestOutputList (
998       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
999        ["pvcreate"; "/dev/sda1"];
1000        ["pvcreate"; "/dev/sda2"];
1001        ["pvcreate"; "/dev/sda3"];
1002        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1003        ["vgcreate"; "VG2"; "/dev/sda3"];
1004        ["lvcreate"; "LV1"; "VG1"; "50"];
1005        ["lvcreate"; "LV2"; "VG1"; "50"];
1006        ["lvcreate"; "LV3"; "VG2"; "50"];
1007        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1008    "list the LVM logical volumes (LVs)",
1009    "\
1010 List all the logical volumes detected.  This is the equivalent
1011 of the L<lvs(8)> command.
1012
1013 This returns a list of the logical volume device names
1014 (eg. C</dev/VolGroup00/LogVol00>).
1015
1016 See also C<guestfs_lvs_full>.");
1017
1018   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1019    [], (* XXX how to test? *)
1020    "list the LVM physical volumes (PVs)",
1021    "\
1022 List all the physical volumes detected.  This is the equivalent
1023 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1024
1025   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1026    [], (* XXX how to test? *)
1027    "list the LVM volume groups (VGs)",
1028    "\
1029 List all the volumes groups detected.  This is the equivalent
1030 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1031
1032   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1033    [], (* XXX how to test? *)
1034    "list the LVM logical volumes (LVs)",
1035    "\
1036 List all the logical volumes detected.  This is the equivalent
1037 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1038
1039   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1040    [InitISOFS, Always, TestOutputList (
1041       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1042     InitISOFS, Always, TestOutputList (
1043       [["read_lines"; "/empty"]], [])],
1044    "read file as lines",
1045    "\
1046 Return the contents of the file named C<path>.
1047
1048 The file contents are returned as a list of lines.  Trailing
1049 C<LF> and C<CRLF> character sequences are I<not> returned.
1050
1051 Note that this function cannot correctly handle binary files
1052 (specifically, files containing C<\\0> character which is treated
1053 as end of line).  For those you need to use the C<guestfs_read_file>
1054 function which has a more complex interface.");
1055
1056   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1057    [], (* XXX Augeas code needs tests. *)
1058    "create a new Augeas handle",
1059    "\
1060 Create a new Augeas handle for editing configuration files.
1061 If there was any previous Augeas handle associated with this
1062 guestfs session, then it is closed.
1063
1064 You must call this before using any other C<guestfs_aug_*>
1065 commands.
1066
1067 C<root> is the filesystem root.  C<root> must not be NULL,
1068 use C</> instead.
1069
1070 The flags are the same as the flags defined in
1071 E<lt>augeas.hE<gt>, the logical I<or> of the following
1072 integers:
1073
1074 =over 4
1075
1076 =item C<AUG_SAVE_BACKUP> = 1
1077
1078 Keep the original file with a C<.augsave> extension.
1079
1080 =item C<AUG_SAVE_NEWFILE> = 2
1081
1082 Save changes into a file with extension C<.augnew>, and
1083 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1084
1085 =item C<AUG_TYPE_CHECK> = 4
1086
1087 Typecheck lenses (can be expensive).
1088
1089 =item C<AUG_NO_STDINC> = 8
1090
1091 Do not use standard load path for modules.
1092
1093 =item C<AUG_SAVE_NOOP> = 16
1094
1095 Make save a no-op, just record what would have been changed.
1096
1097 =item C<AUG_NO_LOAD> = 32
1098
1099 Do not load the tree in C<guestfs_aug_init>.
1100
1101 =back
1102
1103 To close the handle, you can call C<guestfs_aug_close>.
1104
1105 To find out more about Augeas, see L<http://augeas.net/>.");
1106
1107   ("aug_close", (RErr, []), 26, [],
1108    [], (* XXX Augeas code needs tests. *)
1109    "close the current Augeas handle",
1110    "\
1111 Close the current Augeas handle and free up any resources
1112 used by it.  After calling this, you have to call
1113 C<guestfs_aug_init> again before you can use any other
1114 Augeas functions.");
1115
1116   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1117    [], (* XXX Augeas code needs tests. *)
1118    "define an Augeas variable",
1119    "\
1120 Defines an Augeas variable C<name> whose value is the result
1121 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1122 undefined.
1123
1124 On success this returns the number of nodes in C<expr>, or
1125 C<0> if C<expr> evaluates to something which is not a nodeset.");
1126
1127   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1128    [], (* XXX Augeas code needs tests. *)
1129    "define an Augeas node",
1130    "\
1131 Defines a variable C<name> whose value is the result of
1132 evaluating C<expr>.
1133
1134 If C<expr> evaluates to an empty nodeset, a node is created,
1135 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1136 C<name> will be the nodeset containing that single node.
1137
1138 On success this returns a pair containing the
1139 number of nodes in the nodeset, and a boolean flag
1140 if a node was created.");
1141
1142   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1143    [], (* XXX Augeas code needs tests. *)
1144    "look up the value of an Augeas path",
1145    "\
1146 Look up the value associated with C<path>.  If C<path>
1147 matches exactly one node, the C<value> is returned.");
1148
1149   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1150    [], (* XXX Augeas code needs tests. *)
1151    "set Augeas path to value",
1152    "\
1153 Set the value associated with C<path> to C<value>.");
1154
1155   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1156    [], (* XXX Augeas code needs tests. *)
1157    "insert a sibling Augeas node",
1158    "\
1159 Create a new sibling C<label> for C<path>, inserting it into
1160 the tree before or after C<path> (depending on the boolean
1161 flag C<before>).
1162
1163 C<path> must match exactly one existing node in the tree, and
1164 C<label> must be a label, ie. not contain C</>, C<*> or end
1165 with a bracketed index C<[N]>.");
1166
1167   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1168    [], (* XXX Augeas code needs tests. *)
1169    "remove an Augeas path",
1170    "\
1171 Remove C<path> and all of its children.
1172
1173 On success this returns the number of entries which were removed.");
1174
1175   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1176    [], (* XXX Augeas code needs tests. *)
1177    "move Augeas node",
1178    "\
1179 Move the node C<src> to C<dest>.  C<src> must match exactly
1180 one node.  C<dest> is overwritten if it exists.");
1181
1182   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1183    [], (* XXX Augeas code needs tests. *)
1184    "return Augeas nodes which match augpath",
1185    "\
1186 Returns a list of paths which match the path expression C<path>.
1187 The returned paths are sufficiently qualified so that they match
1188 exactly one node in the current tree.");
1189
1190   ("aug_save", (RErr, []), 25, [],
1191    [], (* XXX Augeas code needs tests. *)
1192    "write all pending Augeas changes to disk",
1193    "\
1194 This writes all pending changes to disk.
1195
1196 The flags which were passed to C<guestfs_aug_init> affect exactly
1197 how files are saved.");
1198
1199   ("aug_load", (RErr, []), 27, [],
1200    [], (* XXX Augeas code needs tests. *)
1201    "load files into the tree",
1202    "\
1203 Load files into the tree.
1204
1205 See C<aug_load> in the Augeas documentation for the full gory
1206 details.");
1207
1208   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1209    [], (* XXX Augeas code needs tests. *)
1210    "list Augeas nodes under augpath",
1211    "\
1212 This is just a shortcut for listing C<guestfs_aug_match>
1213 C<path/*> and sorting the resulting nodes into alphabetical order.");
1214
1215   ("rm", (RErr, [Pathname "path"]), 29, [],
1216    [InitBasicFS, Always, TestRun
1217       [["touch"; "/new"];
1218        ["rm"; "/new"]];
1219     InitBasicFS, Always, TestLastFail
1220       [["rm"; "/new"]];
1221     InitBasicFS, Always, TestLastFail
1222       [["mkdir"; "/new"];
1223        ["rm"; "/new"]]],
1224    "remove a file",
1225    "\
1226 Remove the single file C<path>.");
1227
1228   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1229    [InitBasicFS, Always, TestRun
1230       [["mkdir"; "/new"];
1231        ["rmdir"; "/new"]];
1232     InitBasicFS, Always, TestLastFail
1233       [["rmdir"; "/new"]];
1234     InitBasicFS, Always, TestLastFail
1235       [["touch"; "/new"];
1236        ["rmdir"; "/new"]]],
1237    "remove a directory",
1238    "\
1239 Remove the single directory C<path>.");
1240
1241   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1242    [InitBasicFS, Always, TestOutputFalse
1243       [["mkdir"; "/new"];
1244        ["mkdir"; "/new/foo"];
1245        ["touch"; "/new/foo/bar"];
1246        ["rm_rf"; "/new"];
1247        ["exists"; "/new"]]],
1248    "remove a file or directory recursively",
1249    "\
1250 Remove the file or directory C<path>, recursively removing the
1251 contents if its a directory.  This is like the C<rm -rf> shell
1252 command.");
1253
1254   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1255    [InitBasicFS, Always, TestOutputTrue
1256       [["mkdir"; "/new"];
1257        ["is_dir"; "/new"]];
1258     InitBasicFS, Always, TestLastFail
1259       [["mkdir"; "/new/foo/bar"]]],
1260    "create a directory",
1261    "\
1262 Create a directory named C<path>.");
1263
1264   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1265    [InitBasicFS, Always, TestOutputTrue
1266       [["mkdir_p"; "/new/foo/bar"];
1267        ["is_dir"; "/new/foo/bar"]];
1268     InitBasicFS, Always, TestOutputTrue
1269       [["mkdir_p"; "/new/foo/bar"];
1270        ["is_dir"; "/new/foo"]];
1271     InitBasicFS, Always, TestOutputTrue
1272       [["mkdir_p"; "/new/foo/bar"];
1273        ["is_dir"; "/new"]];
1274     (* Regression tests for RHBZ#503133: *)
1275     InitBasicFS, Always, TestRun
1276       [["mkdir"; "/new"];
1277        ["mkdir_p"; "/new"]];
1278     InitBasicFS, Always, TestLastFail
1279       [["touch"; "/new"];
1280        ["mkdir_p"; "/new"]]],
1281    "create a directory and parents",
1282    "\
1283 Create a directory named C<path>, creating any parent directories
1284 as necessary.  This is like the C<mkdir -p> shell command.");
1285
1286   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1287    [], (* XXX Need stat command to test *)
1288    "change file mode",
1289    "\
1290 Change the mode (permissions) of C<path> to C<mode>.  Only
1291 numeric modes are supported.");
1292
1293   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1294    [], (* XXX Need stat command to test *)
1295    "change file owner and group",
1296    "\
1297 Change the file owner to C<owner> and group to C<group>.
1298
1299 Only numeric uid and gid are supported.  If you want to use
1300 names, you will need to locate and parse the password file
1301 yourself (Augeas support makes this relatively easy).");
1302
1303   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1304    [InitISOFS, Always, TestOutputTrue (
1305       [["exists"; "/empty"]]);
1306     InitISOFS, Always, TestOutputTrue (
1307       [["exists"; "/directory"]])],
1308    "test if file or directory exists",
1309    "\
1310 This returns C<true> if and only if there is a file, directory
1311 (or anything) with the given C<path> name.
1312
1313 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1314
1315   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1316    [InitISOFS, Always, TestOutputTrue (
1317       [["is_file"; "/known-1"]]);
1318     InitISOFS, Always, TestOutputFalse (
1319       [["is_file"; "/directory"]])],
1320    "test if file exists",
1321    "\
1322 This returns C<true> if and only if there is a file
1323 with the given C<path> name.  Note that it returns false for
1324 other objects like directories.
1325
1326 See also C<guestfs_stat>.");
1327
1328   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1329    [InitISOFS, Always, TestOutputFalse (
1330       [["is_dir"; "/known-3"]]);
1331     InitISOFS, Always, TestOutputTrue (
1332       [["is_dir"; "/directory"]])],
1333    "test if file exists",
1334    "\
1335 This returns C<true> if and only if there is a directory
1336 with the given C<path> name.  Note that it returns false for
1337 other objects like files.
1338
1339 See also C<guestfs_stat>.");
1340
1341   ("pvcreate", (RErr, [Device "device"]), 39, [],
1342    [InitEmpty, Always, TestOutputListOfDevices (
1343       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1344        ["pvcreate"; "/dev/sda1"];
1345        ["pvcreate"; "/dev/sda2"];
1346        ["pvcreate"; "/dev/sda3"];
1347        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1348    "create an LVM physical volume",
1349    "\
1350 This creates an LVM physical volume on the named C<device>,
1351 where C<device> should usually be a partition name such
1352 as C</dev/sda1>.");
1353
1354   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1355    [InitEmpty, Always, TestOutputList (
1356       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1357        ["pvcreate"; "/dev/sda1"];
1358        ["pvcreate"; "/dev/sda2"];
1359        ["pvcreate"; "/dev/sda3"];
1360        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1361        ["vgcreate"; "VG2"; "/dev/sda3"];
1362        ["vgs"]], ["VG1"; "VG2"])],
1363    "create an LVM volume group",
1364    "\
1365 This creates an LVM volume group called C<volgroup>
1366 from the non-empty list of physical volumes C<physvols>.");
1367
1368   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1369    [InitEmpty, Always, TestOutputList (
1370       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1371        ["pvcreate"; "/dev/sda1"];
1372        ["pvcreate"; "/dev/sda2"];
1373        ["pvcreate"; "/dev/sda3"];
1374        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1375        ["vgcreate"; "VG2"; "/dev/sda3"];
1376        ["lvcreate"; "LV1"; "VG1"; "50"];
1377        ["lvcreate"; "LV2"; "VG1"; "50"];
1378        ["lvcreate"; "LV3"; "VG2"; "50"];
1379        ["lvcreate"; "LV4"; "VG2"; "50"];
1380        ["lvcreate"; "LV5"; "VG2"; "50"];
1381        ["lvs"]],
1382       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1383        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1384    "create an LVM volume group",
1385    "\
1386 This creates an LVM volume group called C<logvol>
1387 on the volume group C<volgroup>, with C<size> megabytes.");
1388
1389   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1390    [InitEmpty, Always, TestOutput (
1391       [["sfdiskM"; "/dev/sda"; ","];
1392        ["mkfs"; "ext2"; "/dev/sda1"];
1393        ["mount"; "/dev/sda1"; "/"];
1394        ["write_file"; "/new"; "new file contents"; "0"];
1395        ["cat"; "/new"]], "new file contents")],
1396    "make a filesystem",
1397    "\
1398 This creates a filesystem on C<device> (usually a partition
1399 or LVM logical volume).  The filesystem type is C<fstype>, for
1400 example C<ext3>.");
1401
1402   ("sfdisk", (RErr, [Device "device";
1403                      Int "cyls"; Int "heads"; Int "sectors";
1404                      StringList "lines"]), 43, [DangerWillRobinson],
1405    [],
1406    "create partitions on a block device",
1407    "\
1408 This is a direct interface to the L<sfdisk(8)> program for creating
1409 partitions on block devices.
1410
1411 C<device> should be a block device, for example C</dev/sda>.
1412
1413 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1414 and sectors on the device, which are passed directly to sfdisk as
1415 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1416 of these, then the corresponding parameter is omitted.  Usually for
1417 'large' disks, you can just pass C<0> for these, but for small
1418 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1419 out the right geometry and you will need to tell it.
1420
1421 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1422 information refer to the L<sfdisk(8)> manpage.
1423
1424 To create a single partition occupying the whole disk, you would
1425 pass C<lines> as a single element list, when the single element being
1426 the string C<,> (comma).
1427
1428 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1429
1430   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1431    [InitBasicFS, Always, TestOutput (
1432       [["write_file"; "/new"; "new file contents"; "0"];
1433        ["cat"; "/new"]], "new file contents");
1434     InitBasicFS, Always, TestOutput (
1435       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1436        ["cat"; "/new"]], "\nnew file contents\n");
1437     InitBasicFS, Always, TestOutput (
1438       [["write_file"; "/new"; "\n\n"; "0"];
1439        ["cat"; "/new"]], "\n\n");
1440     InitBasicFS, Always, TestOutput (
1441       [["write_file"; "/new"; ""; "0"];
1442        ["cat"; "/new"]], "");
1443     InitBasicFS, Always, TestOutput (
1444       [["write_file"; "/new"; "\n\n\n"; "0"];
1445        ["cat"; "/new"]], "\n\n\n");
1446     InitBasicFS, Always, TestOutput (
1447       [["write_file"; "/new"; "\n"; "0"];
1448        ["cat"; "/new"]], "\n")],
1449    "create a file",
1450    "\
1451 This call creates a file called C<path>.  The contents of the
1452 file is the string C<content> (which can contain any 8 bit data),
1453 with length C<size>.
1454
1455 As a special case, if C<size> is C<0>
1456 then the length is calculated using C<strlen> (so in this case
1457 the content cannot contain embedded ASCII NULs).
1458
1459 I<NB.> Owing to a bug, writing content containing ASCII NUL
1460 characters does I<not> work, even if the length is specified.
1461 We hope to resolve this bug in a future version.  In the meantime
1462 use C<guestfs_upload>.");
1463
1464   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1465    [InitEmpty, Always, TestOutputListOfDevices (
1466       [["sfdiskM"; "/dev/sda"; ","];
1467        ["mkfs"; "ext2"; "/dev/sda1"];
1468        ["mount"; "/dev/sda1"; "/"];
1469        ["mounts"]], ["/dev/sda1"]);
1470     InitEmpty, Always, TestOutputList (
1471       [["sfdiskM"; "/dev/sda"; ","];
1472        ["mkfs"; "ext2"; "/dev/sda1"];
1473        ["mount"; "/dev/sda1"; "/"];
1474        ["umount"; "/"];
1475        ["mounts"]], [])],
1476    "unmount a filesystem",
1477    "\
1478 This unmounts the given filesystem.  The filesystem may be
1479 specified either by its mountpoint (path) or the device which
1480 contains the filesystem.");
1481
1482   ("mounts", (RStringList "devices", []), 46, [],
1483    [InitBasicFS, Always, TestOutputListOfDevices (
1484       [["mounts"]], ["/dev/sda1"])],
1485    "show mounted filesystems",
1486    "\
1487 This returns the list of currently mounted filesystems.  It returns
1488 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1489
1490 Some internal mounts are not shown.
1491
1492 See also: C<guestfs_mountpoints>");
1493
1494   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1495    [InitBasicFS, Always, TestOutputList (
1496       [["umount_all"];
1497        ["mounts"]], []);
1498     (* check that umount_all can unmount nested mounts correctly: *)
1499     InitEmpty, Always, TestOutputList (
1500       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mkfs"; "ext2"; "/dev/sda2"];
1503        ["mkfs"; "ext2"; "/dev/sda3"];
1504        ["mount"; "/dev/sda1"; "/"];
1505        ["mkdir"; "/mp1"];
1506        ["mount"; "/dev/sda2"; "/mp1"];
1507        ["mkdir"; "/mp1/mp2"];
1508        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1509        ["mkdir"; "/mp1/mp2/mp3"];
1510        ["umount_all"];
1511        ["mounts"]], [])],
1512    "unmount all filesystems",
1513    "\
1514 This unmounts all mounted filesystems.
1515
1516 Some internal mounts are not unmounted by this call.");
1517
1518   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1519    [],
1520    "remove all LVM LVs, VGs and PVs",
1521    "\
1522 This command removes all LVM logical volumes, volume groups
1523 and physical volumes.");
1524
1525   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1526    [InitISOFS, Always, TestOutput (
1527       [["file"; "/empty"]], "empty");
1528     InitISOFS, Always, TestOutput (
1529       [["file"; "/known-1"]], "ASCII text");
1530     InitISOFS, Always, TestLastFail (
1531       [["file"; "/notexists"]])],
1532    "determine file type",
1533    "\
1534 This call uses the standard L<file(1)> command to determine
1535 the type or contents of the file.  This also works on devices,
1536 for example to find out whether a partition contains a filesystem.
1537
1538 This call will also transparently look inside various types
1539 of compressed file.
1540
1541 The exact command which runs is C<file -zbsL path>.  Note in
1542 particular that the filename is not prepended to the output
1543 (the C<-b> option).");
1544
1545   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1546    [InitBasicFS, Always, TestOutput (
1547       [["upload"; "test-command"; "/test-command"];
1548        ["chmod"; "0o755"; "/test-command"];
1549        ["command"; "/test-command 1"]], "Result1");
1550     InitBasicFS, Always, TestOutput (
1551       [["upload"; "test-command"; "/test-command"];
1552        ["chmod"; "0o755"; "/test-command"];
1553        ["command"; "/test-command 2"]], "Result2\n");
1554     InitBasicFS, Always, TestOutput (
1555       [["upload"; "test-command"; "/test-command"];
1556        ["chmod"; "0o755"; "/test-command"];
1557        ["command"; "/test-command 3"]], "\nResult3");
1558     InitBasicFS, Always, TestOutput (
1559       [["upload"; "test-command"; "/test-command"];
1560        ["chmod"; "0o755"; "/test-command"];
1561        ["command"; "/test-command 4"]], "\nResult4\n");
1562     InitBasicFS, Always, TestOutput (
1563       [["upload"; "test-command"; "/test-command"];
1564        ["chmod"; "0o755"; "/test-command"];
1565        ["command"; "/test-command 5"]], "\nResult5\n\n");
1566     InitBasicFS, Always, TestOutput (
1567       [["upload"; "test-command"; "/test-command"];
1568        ["chmod"; "0o755"; "/test-command"];
1569        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1570     InitBasicFS, Always, TestOutput (
1571       [["upload"; "test-command"; "/test-command"];
1572        ["chmod"; "0o755"; "/test-command"];
1573        ["command"; "/test-command 7"]], "");
1574     InitBasicFS, Always, TestOutput (
1575       [["upload"; "test-command"; "/test-command"];
1576        ["chmod"; "0o755"; "/test-command"];
1577        ["command"; "/test-command 8"]], "\n");
1578     InitBasicFS, Always, TestOutput (
1579       [["upload"; "test-command"; "/test-command"];
1580        ["chmod"; "0o755"; "/test-command"];
1581        ["command"; "/test-command 9"]], "\n\n");
1582     InitBasicFS, Always, TestOutput (
1583       [["upload"; "test-command"; "/test-command"];
1584        ["chmod"; "0o755"; "/test-command"];
1585        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1586     InitBasicFS, Always, TestOutput (
1587       [["upload"; "test-command"; "/test-command"];
1588        ["chmod"; "0o755"; "/test-command"];
1589        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1590     InitBasicFS, Always, TestLastFail (
1591       [["upload"; "test-command"; "/test-command"];
1592        ["chmod"; "0o755"; "/test-command"];
1593        ["command"; "/test-command"]])],
1594    "run a command from the guest filesystem",
1595    "\
1596 This call runs a command from the guest filesystem.  The
1597 filesystem must be mounted, and must contain a compatible
1598 operating system (ie. something Linux, with the same
1599 or compatible processor architecture).
1600
1601 The single parameter is an argv-style list of arguments.
1602 The first element is the name of the program to run.
1603 Subsequent elements are parameters.  The list must be
1604 non-empty (ie. must contain a program name).  Note that
1605 the command runs directly, and is I<not> invoked via
1606 the shell (see C<guestfs_sh>).
1607
1608 The return value is anything printed to I<stdout> by
1609 the command.
1610
1611 If the command returns a non-zero exit status, then
1612 this function returns an error message.  The error message
1613 string is the content of I<stderr> from the command.
1614
1615 The C<$PATH> environment variable will contain at least
1616 C</usr/bin> and C</bin>.  If you require a program from
1617 another location, you should provide the full path in the
1618 first parameter.
1619
1620 Shared libraries and data files required by the program
1621 must be available on filesystems which are mounted in the
1622 correct places.  It is the caller's responsibility to ensure
1623 all filesystems that are needed are mounted at the right
1624 locations.");
1625
1626   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1627    [InitBasicFS, Always, TestOutputList (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command_lines"; "/test-command 1"]], ["Result1"]);
1631     InitBasicFS, Always, TestOutputList (
1632       [["upload"; "test-command"; "/test-command"];
1633        ["chmod"; "0o755"; "/test-command"];
1634        ["command_lines"; "/test-command 2"]], ["Result2"]);
1635     InitBasicFS, Always, TestOutputList (
1636       [["upload"; "test-command"; "/test-command"];
1637        ["chmod"; "0o755"; "/test-command"];
1638        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1639     InitBasicFS, Always, TestOutputList (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1643     InitBasicFS, Always, TestOutputList (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1647     InitBasicFS, Always, TestOutputList (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1651     InitBasicFS, Always, TestOutputList (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command_lines"; "/test-command 7"]], []);
1655     InitBasicFS, Always, TestOutputList (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command_lines"; "/test-command 8"]], [""]);
1659     InitBasicFS, Always, TestOutputList (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command_lines"; "/test-command 9"]], ["";""]);
1663     InitBasicFS, Always, TestOutputList (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1667     InitBasicFS, Always, TestOutputList (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1671    "run a command, returning lines",
1672    "\
1673 This is the same as C<guestfs_command>, but splits the
1674 result into a list of lines.
1675
1676 See also: C<guestfs_sh_lines>");
1677
1678   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1679    [InitISOFS, Always, TestOutputStruct (
1680       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1681    "get file information",
1682    "\
1683 Returns file information for the given C<path>.
1684
1685 This is the same as the C<stat(2)> system call.");
1686
1687   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1688    [InitISOFS, Always, TestOutputStruct (
1689       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1690    "get file information for a symbolic link",
1691    "\
1692 Returns file information for the given C<path>.
1693
1694 This is the same as C<guestfs_stat> except that if C<path>
1695 is a symbolic link, then the link is stat-ed, not the file it
1696 refers to.
1697
1698 This is the same as the C<lstat(2)> system call.");
1699
1700   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1701    [InitISOFS, Always, TestOutputStruct (
1702       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1703    "get file system statistics",
1704    "\
1705 Returns file system statistics for any mounted file system.
1706 C<path> should be a file or directory in the mounted file system
1707 (typically it is the mount point itself, but it doesn't need to be).
1708
1709 This is the same as the C<statvfs(2)> system call.");
1710
1711   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1712    [], (* XXX test *)
1713    "get ext2/ext3/ext4 superblock details",
1714    "\
1715 This returns the contents of the ext2, ext3 or ext4 filesystem
1716 superblock on C<device>.
1717
1718 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1719 manpage for more details.  The list of fields returned isn't
1720 clearly defined, and depends on both the version of C<tune2fs>
1721 that libguestfs was built against, and the filesystem itself.");
1722
1723   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1724    [InitEmpty, Always, TestOutputTrue (
1725       [["blockdev_setro"; "/dev/sda"];
1726        ["blockdev_getro"; "/dev/sda"]])],
1727    "set block device to read-only",
1728    "\
1729 Sets the block device named C<device> to read-only.
1730
1731 This uses the L<blockdev(8)> command.");
1732
1733   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1734    [InitEmpty, Always, TestOutputFalse (
1735       [["blockdev_setrw"; "/dev/sda"];
1736        ["blockdev_getro"; "/dev/sda"]])],
1737    "set block device to read-write",
1738    "\
1739 Sets the block device named C<device> to read-write.
1740
1741 This uses the L<blockdev(8)> command.");
1742
1743   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1744    [InitEmpty, Always, TestOutputTrue (
1745       [["blockdev_setro"; "/dev/sda"];
1746        ["blockdev_getro"; "/dev/sda"]])],
1747    "is block device set to read-only",
1748    "\
1749 Returns a boolean indicating if the block device is read-only
1750 (true if read-only, false if not).
1751
1752 This uses the L<blockdev(8)> command.");
1753
1754   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1755    [InitEmpty, Always, TestOutputInt (
1756       [["blockdev_getss"; "/dev/sda"]], 512)],
1757    "get sectorsize of block device",
1758    "\
1759 This returns the size of sectors on a block device.
1760 Usually 512, but can be larger for modern devices.
1761
1762 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1763 for that).
1764
1765 This uses the L<blockdev(8)> command.");
1766
1767   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1768    [InitEmpty, Always, TestOutputInt (
1769       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1770    "get blocksize of block device",
1771    "\
1772 This returns the block size of a device.
1773
1774 (Note this is different from both I<size in blocks> and
1775 I<filesystem block size>).
1776
1777 This uses the L<blockdev(8)> command.");
1778
1779   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1780    [], (* XXX test *)
1781    "set blocksize of block device",
1782    "\
1783 This sets the block size of a device.
1784
1785 (Note this is different from both I<size in blocks> and
1786 I<filesystem block size>).
1787
1788 This uses the L<blockdev(8)> command.");
1789
1790   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1791    [InitEmpty, Always, TestOutputInt (
1792       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1793    "get total size of device in 512-byte sectors",
1794    "\
1795 This returns the size of the device in units of 512-byte sectors
1796 (even if the sectorsize isn't 512 bytes ... weird).
1797
1798 See also C<guestfs_blockdev_getss> for the real sector size of
1799 the device, and C<guestfs_blockdev_getsize64> for the more
1800 useful I<size in bytes>.
1801
1802 This uses the L<blockdev(8)> command.");
1803
1804   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1805    [InitEmpty, Always, TestOutputInt (
1806       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1807    "get total size of device in bytes",
1808    "\
1809 This returns the size of the device in bytes.
1810
1811 See also C<guestfs_blockdev_getsz>.
1812
1813 This uses the L<blockdev(8)> command.");
1814
1815   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1816    [InitEmpty, Always, TestRun
1817       [["blockdev_flushbufs"; "/dev/sda"]]],
1818    "flush device buffers",
1819    "\
1820 This tells the kernel to flush internal buffers associated
1821 with C<device>.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1826    [InitEmpty, Always, TestRun
1827       [["blockdev_rereadpt"; "/dev/sda"]]],
1828    "reread partition table",
1829    "\
1830 Reread the partition table on C<device>.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1835    [InitBasicFS, Always, TestOutput (
1836       (* Pick a file from cwd which isn't likely to change. *)
1837       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1838        ["checksum"; "md5"; "/COPYING.LIB"]],
1839         Digest.to_hex (Digest.file "COPYING.LIB"))],
1840    "upload a file from the local machine",
1841    "\
1842 Upload local file C<filename> to C<remotefilename> on the
1843 filesystem.
1844
1845 C<filename> can also be a named pipe.
1846
1847 See also C<guestfs_download>.");
1848
1849   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1850    [InitBasicFS, Always, TestOutput (
1851       (* Pick a file from cwd which isn't likely to change. *)
1852       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1853        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1854        ["upload"; "testdownload.tmp"; "/upload"];
1855        ["checksum"; "md5"; "/upload"]],
1856         Digest.to_hex (Digest.file "COPYING.LIB"))],
1857    "download a file to the local machine",
1858    "\
1859 Download file C<remotefilename> and save it as C<filename>
1860 on the local machine.
1861
1862 C<filename> can also be a named pipe.
1863
1864 See also C<guestfs_upload>, C<guestfs_cat>.");
1865
1866   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1867    [InitISOFS, Always, TestOutput (
1868       [["checksum"; "crc"; "/known-3"]], "2891671662");
1869     InitISOFS, Always, TestLastFail (
1870       [["checksum"; "crc"; "/notexists"]]);
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1879     InitISOFS, Always, TestOutput (
1880       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1881     InitISOFS, Always, TestOutput (
1882       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1883    "compute MD5, SHAx or CRC checksum of file",
1884    "\
1885 This call computes the MD5, SHAx or CRC checksum of the
1886 file named C<path>.
1887
1888 The type of checksum to compute is given by the C<csumtype>
1889 parameter which must have one of the following values:
1890
1891 =over 4
1892
1893 =item C<crc>
1894
1895 Compute the cyclic redundancy check (CRC) specified by POSIX
1896 for the C<cksum> command.
1897
1898 =item C<md5>
1899
1900 Compute the MD5 hash (using the C<md5sum> program).
1901
1902 =item C<sha1>
1903
1904 Compute the SHA1 hash (using the C<sha1sum> program).
1905
1906 =item C<sha224>
1907
1908 Compute the SHA224 hash (using the C<sha224sum> program).
1909
1910 =item C<sha256>
1911
1912 Compute the SHA256 hash (using the C<sha256sum> program).
1913
1914 =item C<sha384>
1915
1916 Compute the SHA384 hash (using the C<sha384sum> program).
1917
1918 =item C<sha512>
1919
1920 Compute the SHA512 hash (using the C<sha512sum> program).
1921
1922 =back
1923
1924 The checksum is returned as a printable string.");
1925
1926   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1927    [InitBasicFS, Always, TestOutput (
1928       [["tar_in"; "../images/helloworld.tar"; "/"];
1929        ["cat"; "/hello"]], "hello\n")],
1930    "unpack tarfile to directory",
1931    "\
1932 This command uploads and unpacks local file C<tarfile> (an
1933 I<uncompressed> tar file) into C<directory>.
1934
1935 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1936
1937   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1938    [],
1939    "pack directory into tarfile",
1940    "\
1941 This command packs the contents of C<directory> and downloads
1942 it to local file C<tarfile>.
1943
1944 To download a compressed tarball, use C<guestfs_tgz_out>.");
1945
1946   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1947    [InitBasicFS, Always, TestOutput (
1948       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1949        ["cat"; "/hello"]], "hello\n")],
1950    "unpack compressed tarball to directory",
1951    "\
1952 This command uploads and unpacks local file C<tarball> (a
1953 I<gzip compressed> tar file) into C<directory>.
1954
1955 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1956
1957   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1958    [],
1959    "pack directory into compressed tarball",
1960    "\
1961 This command packs the contents of C<directory> and downloads
1962 it to local file C<tarball>.
1963
1964 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1965
1966   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1967    [InitBasicFS, Always, TestLastFail (
1968       [["umount"; "/"];
1969        ["mount_ro"; "/dev/sda1"; "/"];
1970        ["touch"; "/new"]]);
1971     InitBasicFS, Always, TestOutput (
1972       [["write_file"; "/new"; "data"; "0"];
1973        ["umount"; "/"];
1974        ["mount_ro"; "/dev/sda1"; "/"];
1975        ["cat"; "/new"]], "data")],
1976    "mount a guest disk, read-only",
1977    "\
1978 This is the same as the C<guestfs_mount> command, but it
1979 mounts the filesystem with the read-only (I<-o ro>) flag.");
1980
1981   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1982    [],
1983    "mount a guest disk with mount options",
1984    "\
1985 This is the same as the C<guestfs_mount> command, but it
1986 allows you to set the mount options as for the
1987 L<mount(8)> I<-o> flag.");
1988
1989   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1990    [],
1991    "mount a guest disk with mount options and vfstype",
1992    "\
1993 This is the same as the C<guestfs_mount> command, but it
1994 allows you to set both the mount options and the vfstype
1995 as for the L<mount(8)> I<-o> and I<-t> flags.");
1996
1997   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1998    [],
1999    "debugging and internals",
2000    "\
2001 The C<guestfs_debug> command exposes some internals of
2002 C<guestfsd> (the guestfs daemon) that runs inside the
2003 qemu subprocess.
2004
2005 There is no comprehensive help for this command.  You have
2006 to look at the file C<daemon/debug.c> in the libguestfs source
2007 to find out what you can do.");
2008
2009   ("lvremove", (RErr, [Device "device"]), 77, [],
2010    [InitEmpty, Always, TestOutputList (
2011       [["sfdiskM"; "/dev/sda"; ","];
2012        ["pvcreate"; "/dev/sda1"];
2013        ["vgcreate"; "VG"; "/dev/sda1"];
2014        ["lvcreate"; "LV1"; "VG"; "50"];
2015        ["lvcreate"; "LV2"; "VG"; "50"];
2016        ["lvremove"; "/dev/VG/LV1"];
2017        ["lvs"]], ["/dev/VG/LV2"]);
2018     InitEmpty, Always, TestOutputList (
2019       [["sfdiskM"; "/dev/sda"; ","];
2020        ["pvcreate"; "/dev/sda1"];
2021        ["vgcreate"; "VG"; "/dev/sda1"];
2022        ["lvcreate"; "LV1"; "VG"; "50"];
2023        ["lvcreate"; "LV2"; "VG"; "50"];
2024        ["lvremove"; "/dev/VG"];
2025        ["lvs"]], []);
2026     InitEmpty, Always, TestOutputList (
2027       [["sfdiskM"; "/dev/sda"; ","];
2028        ["pvcreate"; "/dev/sda1"];
2029        ["vgcreate"; "VG"; "/dev/sda1"];
2030        ["lvcreate"; "LV1"; "VG"; "50"];
2031        ["lvcreate"; "LV2"; "VG"; "50"];
2032        ["lvremove"; "/dev/VG"];
2033        ["vgs"]], ["VG"])],
2034    "remove an LVM logical volume",
2035    "\
2036 Remove an LVM logical volume C<device>, where C<device> is
2037 the path to the LV, such as C</dev/VG/LV>.
2038
2039 You can also remove all LVs in a volume group by specifying
2040 the VG name, C</dev/VG>.");
2041
2042   ("vgremove", (RErr, [String "vgname"]), 78, [],
2043    [InitEmpty, Always, TestOutputList (
2044       [["sfdiskM"; "/dev/sda"; ","];
2045        ["pvcreate"; "/dev/sda1"];
2046        ["vgcreate"; "VG"; "/dev/sda1"];
2047        ["lvcreate"; "LV1"; "VG"; "50"];
2048        ["lvcreate"; "LV2"; "VG"; "50"];
2049        ["vgremove"; "VG"];
2050        ["lvs"]], []);
2051     InitEmpty, Always, TestOutputList (
2052       [["sfdiskM"; "/dev/sda"; ","];
2053        ["pvcreate"; "/dev/sda1"];
2054        ["vgcreate"; "VG"; "/dev/sda1"];
2055        ["lvcreate"; "LV1"; "VG"; "50"];
2056        ["lvcreate"; "LV2"; "VG"; "50"];
2057        ["vgremove"; "VG"];
2058        ["vgs"]], [])],
2059    "remove an LVM volume group",
2060    "\
2061 Remove an LVM volume group C<vgname>, (for example C<VG>).
2062
2063 This also forcibly removes all logical volumes in the volume
2064 group (if any).");
2065
2066   ("pvremove", (RErr, [Device "device"]), 79, [],
2067    [InitEmpty, Always, TestOutputListOfDevices (
2068       [["sfdiskM"; "/dev/sda"; ","];
2069        ["pvcreate"; "/dev/sda1"];
2070        ["vgcreate"; "VG"; "/dev/sda1"];
2071        ["lvcreate"; "LV1"; "VG"; "50"];
2072        ["lvcreate"; "LV2"; "VG"; "50"];
2073        ["vgremove"; "VG"];
2074        ["pvremove"; "/dev/sda1"];
2075        ["lvs"]], []);
2076     InitEmpty, Always, TestOutputListOfDevices (
2077       [["sfdiskM"; "/dev/sda"; ","];
2078        ["pvcreate"; "/dev/sda1"];
2079        ["vgcreate"; "VG"; "/dev/sda1"];
2080        ["lvcreate"; "LV1"; "VG"; "50"];
2081        ["lvcreate"; "LV2"; "VG"; "50"];
2082        ["vgremove"; "VG"];
2083        ["pvremove"; "/dev/sda1"];
2084        ["vgs"]], []);
2085     InitEmpty, Always, TestOutputListOfDevices (
2086       [["sfdiskM"; "/dev/sda"; ","];
2087        ["pvcreate"; "/dev/sda1"];
2088        ["vgcreate"; "VG"; "/dev/sda1"];
2089        ["lvcreate"; "LV1"; "VG"; "50"];
2090        ["lvcreate"; "LV2"; "VG"; "50"];
2091        ["vgremove"; "VG"];
2092        ["pvremove"; "/dev/sda1"];
2093        ["pvs"]], [])],
2094    "remove an LVM physical volume",
2095    "\
2096 This wipes a physical volume C<device> so that LVM will no longer
2097 recognise it.
2098
2099 The implementation uses the C<pvremove> command which refuses to
2100 wipe physical volumes that contain any volume groups, so you have
2101 to remove those first.");
2102
2103   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2104    [InitBasicFS, Always, TestOutput (
2105       [["set_e2label"; "/dev/sda1"; "testlabel"];
2106        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2107    "set the ext2/3/4 filesystem label",
2108    "\
2109 This sets the ext2/3/4 filesystem label of the filesystem on
2110 C<device> to C<label>.  Filesystem labels are limited to
2111 16 characters.
2112
2113 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2114 to return the existing label on a filesystem.");
2115
2116   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2117    [],
2118    "get the ext2/3/4 filesystem label",
2119    "\
2120 This returns the ext2/3/4 filesystem label of the filesystem on
2121 C<device>.");
2122
2123   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2124    (let uuid = uuidgen () in
2125     [InitBasicFS, Always, TestOutput (
2126        [["set_e2uuid"; "/dev/sda1"; uuid];
2127         ["get_e2uuid"; "/dev/sda1"]], uuid);
2128      InitBasicFS, Always, TestOutput (
2129        [["set_e2uuid"; "/dev/sda1"; "clear"];
2130         ["get_e2uuid"; "/dev/sda1"]], "");
2131      (* We can't predict what UUIDs will be, so just check the commands run. *)
2132      InitBasicFS, Always, TestRun (
2133        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2134      InitBasicFS, Always, TestRun (
2135        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2136    "set the ext2/3/4 filesystem UUID",
2137    "\
2138 This sets the ext2/3/4 filesystem UUID of the filesystem on
2139 C<device> to C<uuid>.  The format of the UUID and alternatives
2140 such as C<clear>, C<random> and C<time> are described in the
2141 L<tune2fs(8)> manpage.
2142
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2144 to return the existing UUID of a filesystem.");
2145
2146   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2147    [],
2148    "get the ext2/3/4 filesystem UUID",
2149    "\
2150 This returns the ext2/3/4 filesystem UUID of the filesystem on
2151 C<device>.");
2152
2153   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2154    [InitBasicFS, Always, TestOutputInt (
2155       [["umount"; "/dev/sda1"];
2156        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2157     InitBasicFS, Always, TestOutputInt (
2158       [["umount"; "/dev/sda1"];
2159        ["zero"; "/dev/sda1"];
2160        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2161    "run the filesystem checker",
2162    "\
2163 This runs the filesystem checker (fsck) on C<device> which
2164 should have filesystem type C<fstype>.
2165
2166 The returned integer is the status.  See L<fsck(8)> for the
2167 list of status codes from C<fsck>.
2168
2169 Notes:
2170
2171 =over 4
2172
2173 =item *
2174
2175 Multiple status codes can be summed together.
2176
2177 =item *
2178
2179 A non-zero return code can mean \"success\", for example if
2180 errors have been corrected on the filesystem.
2181
2182 =item *
2183
2184 Checking or repairing NTFS volumes is not supported
2185 (by linux-ntfs).
2186
2187 =back
2188
2189 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2190
2191   ("zero", (RErr, [Device "device"]), 85, [],
2192    [InitBasicFS, Always, TestOutput (
2193       [["umount"; "/dev/sda1"];
2194        ["zero"; "/dev/sda1"];
2195        ["file"; "/dev/sda1"]], "data")],
2196    "write zeroes to the device",
2197    "\
2198 This command writes zeroes over the first few blocks of C<device>.
2199
2200 How many blocks are zeroed isn't specified (but it's I<not> enough
2201 to securely wipe the device).  It should be sufficient to remove
2202 any partition tables, filesystem superblocks and so on.
2203
2204 See also: C<guestfs_scrub_device>.");
2205
2206   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2207    (* Test disabled because grub-install incompatible with virtio-blk driver.
2208     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2209     *)
2210    [InitBasicFS, Disabled, TestOutputTrue (
2211       [["grub_install"; "/"; "/dev/sda1"];
2212        ["is_dir"; "/boot"]])],
2213    "install GRUB",
2214    "\
2215 This command installs GRUB (the Grand Unified Bootloader) on
2216 C<device>, with the root directory being C<root>.");
2217
2218   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2219    [InitBasicFS, Always, TestOutput (
2220       [["write_file"; "/old"; "file content"; "0"];
2221        ["cp"; "/old"; "/new"];
2222        ["cat"; "/new"]], "file content");
2223     InitBasicFS, Always, TestOutputTrue (
2224       [["write_file"; "/old"; "file content"; "0"];
2225        ["cp"; "/old"; "/new"];
2226        ["is_file"; "/old"]]);
2227     InitBasicFS, Always, TestOutput (
2228       [["write_file"; "/old"; "file content"; "0"];
2229        ["mkdir"; "/dir"];
2230        ["cp"; "/old"; "/dir/new"];
2231        ["cat"; "/dir/new"]], "file content")],
2232    "copy a file",
2233    "\
2234 This copies a file from C<src> to C<dest> where C<dest> is
2235 either a destination filename or destination directory.");
2236
2237   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2238    [InitBasicFS, Always, TestOutput (
2239       [["mkdir"; "/olddir"];
2240        ["mkdir"; "/newdir"];
2241        ["write_file"; "/olddir/file"; "file content"; "0"];
2242        ["cp_a"; "/olddir"; "/newdir"];
2243        ["cat"; "/newdir/olddir/file"]], "file content")],
2244    "copy a file or directory recursively",
2245    "\
2246 This copies a file or directory from C<src> to C<dest>
2247 recursively using the C<cp -a> command.");
2248
2249   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2250    [InitBasicFS, Always, TestOutput (
2251       [["write_file"; "/old"; "file content"; "0"];
2252        ["mv"; "/old"; "/new"];
2253        ["cat"; "/new"]], "file content");
2254     InitBasicFS, Always, TestOutputFalse (
2255       [["write_file"; "/old"; "file content"; "0"];
2256        ["mv"; "/old"; "/new"];
2257        ["is_file"; "/old"]])],
2258    "move a file",
2259    "\
2260 This moves a file from C<src> to C<dest> where C<dest> is
2261 either a destination filename or destination directory.");
2262
2263   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2264    [InitEmpty, Always, TestRun (
2265       [["drop_caches"; "3"]])],
2266    "drop kernel page cache, dentries and inodes",
2267    "\
2268 This instructs the guest kernel to drop its page cache,
2269 and/or dentries and inode caches.  The parameter C<whattodrop>
2270 tells the kernel what precisely to drop, see
2271 L<http://linux-mm.org/Drop_Caches>
2272
2273 Setting C<whattodrop> to 3 should drop everything.
2274
2275 This automatically calls L<sync(2)> before the operation,
2276 so that the maximum guest memory is freed.");
2277
2278   ("dmesg", (RString "kmsgs", []), 91, [],
2279    [InitEmpty, Always, TestRun (
2280       [["dmesg"]])],
2281    "return kernel messages",
2282    "\
2283 This returns the kernel messages (C<dmesg> output) from
2284 the guest kernel.  This is sometimes useful for extended
2285 debugging of problems.
2286
2287 Another way to get the same information is to enable
2288 verbose messages with C<guestfs_set_verbose> or by setting
2289 the environment variable C<LIBGUESTFS_DEBUG=1> before
2290 running the program.");
2291
2292   ("ping_daemon", (RErr, []), 92, [],
2293    [InitEmpty, Always, TestRun (
2294       [["ping_daemon"]])],
2295    "ping the guest daemon",
2296    "\
2297 This is a test probe into the guestfs daemon running inside
2298 the qemu subprocess.  Calling this function checks that the
2299 daemon responds to the ping message, without affecting the daemon
2300 or attached block device(s) in any other way.");
2301
2302   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2303    [InitBasicFS, Always, TestOutputTrue (
2304       [["write_file"; "/file1"; "contents of a file"; "0"];
2305        ["cp"; "/file1"; "/file2"];
2306        ["equal"; "/file1"; "/file2"]]);
2307     InitBasicFS, Always, TestOutputFalse (
2308       [["write_file"; "/file1"; "contents of a file"; "0"];
2309        ["write_file"; "/file2"; "contents of another file"; "0"];
2310        ["equal"; "/file1"; "/file2"]]);
2311     InitBasicFS, Always, TestLastFail (
2312       [["equal"; "/file1"; "/file2"]])],
2313    "test if two files have equal contents",
2314    "\
2315 This compares the two files C<file1> and C<file2> and returns
2316 true if their content is exactly equal, or false otherwise.
2317
2318 The external L<cmp(1)> program is used for the comparison.");
2319
2320   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2321    [InitISOFS, Always, TestOutputList (
2322       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2323     InitISOFS, Always, TestOutputList (
2324       [["strings"; "/empty"]], [])],
2325    "print the printable strings in a file",
2326    "\
2327 This runs the L<strings(1)> command on a file and returns
2328 the list of printable strings found.");
2329
2330   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2331    [InitISOFS, Always, TestOutputList (
2332       [["strings_e"; "b"; "/known-5"]], []);
2333     InitBasicFS, Disabled, TestOutputList (
2334       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2335        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2336    "print the printable strings in a file",
2337    "\
2338 This is like the C<guestfs_strings> command, but allows you to
2339 specify the encoding.
2340
2341 See the L<strings(1)> manpage for the full list of encodings.
2342
2343 Commonly useful encodings are C<l> (lower case L) which will
2344 show strings inside Windows/x86 files.
2345
2346 The returned strings are transcoded to UTF-8.");
2347
2348   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2349    [InitISOFS, Always, TestOutput (
2350       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2351     (* Test for RHBZ#501888c2 regression which caused large hexdump
2352      * commands to segfault.
2353      *)
2354     InitISOFS, Always, TestRun (
2355       [["hexdump"; "/100krandom"]])],
2356    "dump a file in hexadecimal",
2357    "\
2358 This runs C<hexdump -C> on the given C<path>.  The result is
2359 the human-readable, canonical hex dump of the file.");
2360
2361   ("zerofree", (RErr, [Device "device"]), 97, [],
2362    [InitNone, Always, TestOutput (
2363       [["sfdiskM"; "/dev/sda"; ","];
2364        ["mkfs"; "ext3"; "/dev/sda1"];
2365        ["mount"; "/dev/sda1"; "/"];
2366        ["write_file"; "/new"; "test file"; "0"];
2367        ["umount"; "/dev/sda1"];
2368        ["zerofree"; "/dev/sda1"];
2369        ["mount"; "/dev/sda1"; "/"];
2370        ["cat"; "/new"]], "test file")],
2371    "zero unused inodes and disk blocks on ext2/3 filesystem",
2372    "\
2373 This runs the I<zerofree> program on C<device>.  This program
2374 claims to zero unused inodes and disk blocks on an ext2/3
2375 filesystem, thus making it possible to compress the filesystem
2376 more effectively.
2377
2378 You should B<not> run this program if the filesystem is
2379 mounted.
2380
2381 It is possible that using this program can damage the filesystem
2382 or data on the filesystem.");
2383
2384   ("pvresize", (RErr, [Device "device"]), 98, [],
2385    [],
2386    "resize an LVM physical volume",
2387    "\
2388 This resizes (expands or shrinks) an existing LVM physical
2389 volume to match the new size of the underlying device.");
2390
2391   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2392                        Int "cyls"; Int "heads"; Int "sectors";
2393                        String "line"]), 99, [DangerWillRobinson],
2394    [],
2395    "modify a single partition on a block device",
2396    "\
2397 This runs L<sfdisk(8)> option to modify just the single
2398 partition C<n> (note: C<n> counts from 1).
2399
2400 For other parameters, see C<guestfs_sfdisk>.  You should usually
2401 pass C<0> for the cyls/heads/sectors parameters.");
2402
2403   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2404    [],
2405    "display the partition table",
2406    "\
2407 This displays the partition table on C<device>, in the
2408 human-readable output of the L<sfdisk(8)> command.  It is
2409 not intended to be parsed.");
2410
2411   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2412    [],
2413    "display the kernel geometry",
2414    "\
2415 This displays the kernel's idea of the geometry of C<device>.
2416
2417 The result is in human-readable format, and not designed to
2418 be parsed.");
2419
2420   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2421    [],
2422    "display the disk geometry from the partition table",
2423    "\
2424 This displays the disk geometry of C<device> read from the
2425 partition table.  Especially in the case where the underlying
2426 block device has been resized, this can be different from the
2427 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2428
2429 The result is in human-readable format, and not designed to
2430 be parsed.");
2431
2432   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2433    [],
2434    "activate or deactivate all volume groups",
2435    "\
2436 This command activates or (if C<activate> is false) deactivates
2437 all logical volumes in all volume groups.
2438 If activated, then they are made known to the
2439 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2440 then those devices disappear.
2441
2442 This command is the same as running C<vgchange -a y|n>");
2443
2444   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2445    [],
2446    "activate or deactivate some volume groups",
2447    "\
2448 This command activates or (if C<activate> is false) deactivates
2449 all logical volumes in the listed volume groups C<volgroups>.
2450 If activated, then they are made known to the
2451 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2452 then those devices disappear.
2453
2454 This command is the same as running C<vgchange -a y|n volgroups...>
2455
2456 Note that if C<volgroups> is an empty list then B<all> volume groups
2457 are activated or deactivated.");
2458
2459   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2460    [InitNone, Always, TestOutput (
2461       [["sfdiskM"; "/dev/sda"; ","];
2462        ["pvcreate"; "/dev/sda1"];
2463        ["vgcreate"; "VG"; "/dev/sda1"];
2464        ["lvcreate"; "LV"; "VG"; "10"];
2465        ["mkfs"; "ext2"; "/dev/VG/LV"];
2466        ["mount"; "/dev/VG/LV"; "/"];
2467        ["write_file"; "/new"; "test content"; "0"];
2468        ["umount"; "/"];
2469        ["lvresize"; "/dev/VG/LV"; "20"];
2470        ["e2fsck_f"; "/dev/VG/LV"];
2471        ["resize2fs"; "/dev/VG/LV"];
2472        ["mount"; "/dev/VG/LV"; "/"];
2473        ["cat"; "/new"]], "test content")],
2474    "resize an LVM logical volume",
2475    "\
2476 This resizes (expands or shrinks) an existing LVM logical
2477 volume to C<mbytes>.  When reducing, data in the reduced part
2478 is lost.");
2479
2480   ("resize2fs", (RErr, [Device "device"]), 106, [],
2481    [], (* lvresize tests this *)
2482    "resize an ext2/ext3 filesystem",
2483    "\
2484 This resizes an ext2 or ext3 filesystem to match the size of
2485 the underlying device.
2486
2487 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2488 on the C<device> before calling this command.  For unknown reasons
2489 C<resize2fs> sometimes gives an error about this and sometimes not.
2490 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2491 calling this function.");
2492
2493   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2494    [InitBasicFS, Always, TestOutputList (
2495       [["find"; "/"]], ["lost+found"]);
2496     InitBasicFS, Always, TestOutputList (
2497       [["touch"; "/a"];
2498        ["mkdir"; "/b"];
2499        ["touch"; "/b/c"];
2500        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2501     InitBasicFS, Always, TestOutputList (
2502       [["mkdir_p"; "/a/b/c"];
2503        ["touch"; "/a/b/c/d"];
2504        ["find"; "/a/b/"]], ["c"; "c/d"])],
2505    "find all files and directories",
2506    "\
2507 This command lists out all files and directories, recursively,
2508 starting at C<directory>.  It is essentially equivalent to
2509 running the shell command C<find directory -print> but some
2510 post-processing happens on the output, described below.
2511
2512 This returns a list of strings I<without any prefix>.  Thus
2513 if the directory structure was:
2514
2515  /tmp/a
2516  /tmp/b
2517  /tmp/c/d
2518
2519 then the returned list from C<guestfs_find> C</tmp> would be
2520 4 elements:
2521
2522  a
2523  b
2524  c
2525  c/d
2526
2527 If C<directory> is not a directory, then this command returns
2528 an error.
2529
2530 The returned list is sorted.
2531
2532 See also C<guestfs_find0>.");
2533
2534   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2535    [], (* lvresize tests this *)
2536    "check an ext2/ext3 filesystem",
2537    "\
2538 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2539 filesystem checker on C<device>, noninteractively (C<-p>),
2540 even if the filesystem appears to be clean (C<-f>).
2541
2542 This command is only needed because of C<guestfs_resize2fs>
2543 (q.v.).  Normally you should use C<guestfs_fsck>.");
2544
2545   ("sleep", (RErr, [Int "secs"]), 109, [],
2546    [InitNone, Always, TestRun (
2547       [["sleep"; "1"]])],
2548    "sleep for some seconds",
2549    "\
2550 Sleep for C<secs> seconds.");
2551
2552   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2553    [InitNone, Always, TestOutputInt (
2554       [["sfdiskM"; "/dev/sda"; ","];
2555        ["mkfs"; "ntfs"; "/dev/sda1"];
2556        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2557     InitNone, Always, TestOutputInt (
2558       [["sfdiskM"; "/dev/sda"; ","];
2559        ["mkfs"; "ext2"; "/dev/sda1"];
2560        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2561    "probe NTFS volume",
2562    "\
2563 This command runs the L<ntfs-3g.probe(8)> command which probes
2564 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2565 be mounted read-write, and some cannot be mounted at all).
2566
2567 C<rw> is a boolean flag.  Set it to true if you want to test
2568 if the volume can be mounted read-write.  Set it to false if
2569 you want to test if the volume can be mounted read-only.
2570
2571 The return value is an integer which C<0> if the operation
2572 would succeed, or some non-zero value documented in the
2573 L<ntfs-3g.probe(8)> manual page.");
2574
2575   ("sh", (RString "output", [String "command"]), 111, [],
2576    [], (* XXX needs tests *)
2577    "run a command via the shell",
2578    "\
2579 This call runs a command from the guest filesystem via the
2580 guest's C</bin/sh>.
2581
2582 This is like C<guestfs_command>, but passes the command to:
2583
2584  /bin/sh -c \"command\"
2585
2586 Depending on the guest's shell, this usually results in
2587 wildcards being expanded, shell expressions being interpolated
2588 and so on.
2589
2590 All the provisos about C<guestfs_command> apply to this call.");
2591
2592   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2593    [], (* XXX needs tests *)
2594    "run a command via the shell returning lines",
2595    "\
2596 This is the same as C<guestfs_sh>, but splits the result
2597 into a list of lines.
2598
2599 See also: C<guestfs_command_lines>");
2600
2601   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2602    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2603     * code in stubs.c, since all valid glob patterns must start with "/".
2604     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2605     *)
2606    [InitBasicFS, Always, TestOutputList (
2607       [["mkdir_p"; "/a/b/c"];
2608        ["touch"; "/a/b/c/d"];
2609        ["touch"; "/a/b/c/e"];
2610        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2611     InitBasicFS, Always, TestOutputList (
2612       [["mkdir_p"; "/a/b/c"];
2613        ["touch"; "/a/b/c/d"];
2614        ["touch"; "/a/b/c/e"];
2615        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2616     InitBasicFS, Always, TestOutputList (
2617       [["mkdir_p"; "/a/b/c"];
2618        ["touch"; "/a/b/c/d"];
2619        ["touch"; "/a/b/c/e"];
2620        ["glob_expand"; "/a/*/x/*"]], [])],
2621    "expand a wildcard path",
2622    "\
2623 This command searches for all the pathnames matching
2624 C<pattern> according to the wildcard expansion rules
2625 used by the shell.
2626
2627 If no paths match, then this returns an empty list
2628 (note: not an error).
2629
2630 It is just a wrapper around the C L<glob(3)> function
2631 with flags C<GLOB_MARK|GLOB_BRACE>.
2632 See that manual page for more details.");
2633
2634   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2635    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2636       [["scrub_device"; "/dev/sdc"]])],
2637    "scrub (securely wipe) a device",
2638    "\
2639 This command writes patterns over C<device> to make data retrieval
2640 more difficult.
2641
2642 It is an interface to the L<scrub(1)> program.  See that
2643 manual page for more details.");
2644
2645   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2646    [InitBasicFS, Always, TestRun (
2647       [["write_file"; "/file"; "content"; "0"];
2648        ["scrub_file"; "/file"]])],
2649    "scrub (securely wipe) a file",
2650    "\
2651 This command writes patterns over a file to make data retrieval
2652 more difficult.
2653
2654 The file is I<removed> after scrubbing.
2655
2656 It is an interface to the L<scrub(1)> program.  See that
2657 manual page for more details.");
2658
2659   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2660    [], (* XXX needs testing *)
2661    "scrub (securely wipe) free space",
2662    "\
2663 This command creates the directory C<dir> and then fills it
2664 with files until the filesystem is full, and scrubs the files
2665 as for C<guestfs_scrub_file>, and deletes them.
2666 The intention is to scrub any free space on the partition
2667 containing C<dir>.
2668
2669 It is an interface to the L<scrub(1)> program.  See that
2670 manual page for more details.");
2671
2672   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2673    [InitBasicFS, Always, TestRun (
2674       [["mkdir"; "/tmp"];
2675        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2676    "create a temporary directory",
2677    "\
2678 This command creates a temporary directory.  The
2679 C<template> parameter should be a full pathname for the
2680 temporary directory name with the final six characters being
2681 \"XXXXXX\".
2682
2683 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2684 the second one being suitable for Windows filesystems.
2685
2686 The name of the temporary directory that was created
2687 is returned.
2688
2689 The temporary directory is created with mode 0700
2690 and is owned by root.
2691
2692 The caller is responsible for deleting the temporary
2693 directory and its contents after use.
2694
2695 See also: L<mkdtemp(3)>");
2696
2697   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2698    [InitISOFS, Always, TestOutputInt (
2699       [["wc_l"; "/10klines"]], 10000)],
2700    "count lines in a file",
2701    "\
2702 This command counts the lines in a file, using the
2703 C<wc -l> external command.");
2704
2705   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2706    [InitISOFS, Always, TestOutputInt (
2707       [["wc_w"; "/10klines"]], 10000)],
2708    "count words in a file",
2709    "\
2710 This command counts the words in a file, using the
2711 C<wc -w> external command.");
2712
2713   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2714    [InitISOFS, Always, TestOutputInt (
2715       [["wc_c"; "/100kallspaces"]], 102400)],
2716    "count characters in a file",
2717    "\
2718 This command counts the characters in a file, using the
2719 C<wc -c> external command.");
2720
2721   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2722    [InitISOFS, Always, TestOutputList (
2723       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2724    "return first 10 lines of a file",
2725    "\
2726 This command returns up to the first 10 lines of a file as
2727 a list of strings.");
2728
2729   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2730    [InitISOFS, Always, TestOutputList (
2731       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732     InitISOFS, Always, TestOutputList (
2733       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2734     InitISOFS, Always, TestOutputList (
2735       [["head_n"; "0"; "/10klines"]], [])],
2736    "return first N lines of a file",
2737    "\
2738 If the parameter C<nrlines> is a positive number, this returns the first
2739 C<nrlines> lines of the file C<path>.
2740
2741 If the parameter C<nrlines> is a negative number, this returns lines
2742 from the file C<path>, excluding the last C<nrlines> lines.
2743
2744 If the parameter C<nrlines> is zero, this returns an empty list.");
2745
2746   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2747    [InitISOFS, Always, TestOutputList (
2748       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2749    "return last 10 lines of a file",
2750    "\
2751 This command returns up to the last 10 lines of a file as
2752 a list of strings.");
2753
2754   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2755    [InitISOFS, Always, TestOutputList (
2756       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757     InitISOFS, Always, TestOutputList (
2758       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2759     InitISOFS, Always, TestOutputList (
2760       [["tail_n"; "0"; "/10klines"]], [])],
2761    "return last N lines of a file",
2762    "\
2763 If the parameter C<nrlines> is a positive number, this returns the last
2764 C<nrlines> lines of the file C<path>.
2765
2766 If the parameter C<nrlines> is a negative number, this returns lines
2767 from the file C<path>, starting with the C<-nrlines>th line.
2768
2769 If the parameter C<nrlines> is zero, this returns an empty list.");
2770
2771   ("df", (RString "output", []), 125, [],
2772    [], (* XXX Tricky to test because it depends on the exact format
2773         * of the 'df' command and other imponderables.
2774         *)
2775    "report file system disk space usage",
2776    "\
2777 This command runs the C<df> command to report disk space used.
2778
2779 This command is mostly useful for interactive sessions.  It
2780 is I<not> intended that you try to parse the output string.
2781 Use C<statvfs> from programs.");
2782
2783   ("df_h", (RString "output", []), 126, [],
2784    [], (* XXX Tricky to test because it depends on the exact format
2785         * of the 'df' command and other imponderables.
2786         *)
2787    "report file system disk space usage (human readable)",
2788    "\
2789 This command runs the C<df -h> command to report disk space used
2790 in human-readable format.
2791
2792 This command is mostly useful for interactive sessions.  It
2793 is I<not> intended that you try to parse the output string.
2794 Use C<statvfs> from programs.");
2795
2796   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2799    "estimate file space usage",
2800    "\
2801 This command runs the C<du -s> command to estimate file space
2802 usage for C<path>.
2803
2804 C<path> can be a file or a directory.  If C<path> is a directory
2805 then the estimate includes the contents of the directory and all
2806 subdirectories (recursively).
2807
2808 The result is the estimated size in I<kilobytes>
2809 (ie. units of 1024 bytes).");
2810
2811   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2812    [InitISOFS, Always, TestOutputList (
2813       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2814    "list files in an initrd",
2815    "\
2816 This command lists out files contained in an initrd.
2817
2818 The files are listed without any initial C</> character.  The
2819 files are listed in the order they appear (not necessarily
2820 alphabetical).  Directory names are listed as separate items.
2821
2822 Old Linux kernels (2.4 and earlier) used a compressed ext2
2823 filesystem as initrd.  We I<only> support the newer initramfs
2824 format (compressed cpio files).");
2825
2826   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2827    [],
2828    "mount a file using the loop device",
2829    "\
2830 This command lets you mount C<file> (a filesystem image
2831 in a file) on a mount point.  It is entirely equivalent to
2832 the command C<mount -o loop file mountpoint>.");
2833
2834   ("mkswap", (RErr, [Device "device"]), 130, [],
2835    [InitEmpty, Always, TestRun (
2836       [["sfdiskM"; "/dev/sda"; ","];
2837        ["mkswap"; "/dev/sda1"]])],
2838    "create a swap partition",
2839    "\
2840 Create a swap partition on C<device>.");
2841
2842   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2843    [InitEmpty, Always, TestRun (
2844       [["sfdiskM"; "/dev/sda"; ","];
2845        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2846    "create a swap partition with a label",
2847    "\
2848 Create a swap partition on C<device> with label C<label>.
2849
2850 Note that you cannot attach a swap label to a block device
2851 (eg. C</dev/sda>), just to a partition.  This appears to be
2852 a limitation of the kernel or swap tools.");
2853
2854   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2855    (let uuid = uuidgen () in
2856     [InitEmpty, Always, TestRun (
2857        [["sfdiskM"; "/dev/sda"; ","];
2858         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2859    "create a swap partition with an explicit UUID",
2860    "\
2861 Create a swap partition on C<device> with UUID C<uuid>.");
2862
2863   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2864    [InitBasicFS, Always, TestOutputStruct (
2865       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2866        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2867        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2868     InitBasicFS, Always, TestOutputStruct (
2869       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2870        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2871    "make block, character or FIFO devices",
2872    "\
2873 This call creates block or character special devices, or
2874 named pipes (FIFOs).
2875
2876 The C<mode> parameter should be the mode, using the standard
2877 constants.  C<devmajor> and C<devminor> are the
2878 device major and minor numbers, only used when creating block
2879 and character special devices.");
2880
2881   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2882    [InitBasicFS, Always, TestOutputStruct (
2883       [["mkfifo"; "0o777"; "/node"];
2884        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2885    "make FIFO (named pipe)",
2886    "\
2887 This call creates a FIFO (named pipe) called C<path> with
2888 mode C<mode>.  It is just a convenient wrapper around
2889 C<guestfs_mknod>.");
2890
2891   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2892    [InitBasicFS, Always, TestOutputStruct (
2893       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2894        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2895    "make block device node",
2896    "\
2897 This call creates a block device node called C<path> with
2898 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2899 It is just a convenient wrapper around C<guestfs_mknod>.");
2900
2901   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2902    [InitBasicFS, Always, TestOutputStruct (
2903       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2904        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2905    "make char device node",
2906    "\
2907 This call creates a char device node called C<path> with
2908 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2909 It is just a convenient wrapper around C<guestfs_mknod>.");
2910
2911   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2912    [], (* XXX umask is one of those stateful things that we should
2913         * reset between each test.
2914         *)
2915    "set file mode creation mask (umask)",
2916    "\
2917 This function sets the mask used for creating new files and
2918 device nodes to C<mask & 0777>.
2919
2920 Typical umask values would be C<022> which creates new files
2921 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2922 C<002> which creates new files with permissions like
2923 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2924
2925 The default umask is C<022>.  This is important because it
2926 means that directories and device nodes will be created with
2927 C<0644> or C<0755> mode even if you specify C<0777>.
2928
2929 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2930
2931 This call returns the previous umask.");
2932
2933   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2934    [],
2935    "read directories entries",
2936    "\
2937 This returns the list of directory entries in directory C<dir>.
2938
2939 All entries in the directory are returned, including C<.> and
2940 C<..>.  The entries are I<not> sorted, but returned in the same
2941 order as the underlying filesystem.
2942
2943 Also this call returns basic file type information about each
2944 file.  The C<ftyp> field will contain one of the following characters:
2945
2946 =over 4
2947
2948 =item 'b'
2949
2950 Block special
2951
2952 =item 'c'
2953
2954 Char special
2955
2956 =item 'd'
2957
2958 Directory
2959
2960 =item 'f'
2961
2962 FIFO (named pipe)
2963
2964 =item 'l'
2965
2966 Symbolic link
2967
2968 =item 'r'
2969
2970 Regular file
2971
2972 =item 's'
2973
2974 Socket
2975
2976 =item 'u'
2977
2978 Unknown file type
2979
2980 =item '?'
2981
2982 The L<readdir(3)> returned a C<d_type> field with an
2983 unexpected value
2984
2985 =back
2986
2987 This function is primarily intended for use by programs.  To
2988 get a simple list of names, use C<guestfs_ls>.  To get a printable
2989 directory for human consumption, use C<guestfs_ll>.");
2990
2991   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2992    [],
2993    "create partitions on a block device",
2994    "\
2995 This is a simplified interface to the C<guestfs_sfdisk>
2996 command, where partition sizes are specified in megabytes
2997 only (rounded to the nearest cylinder) and you don't need
2998 to specify the cyls, heads and sectors parameters which
2999 were rarely if ever used anyway.
3000
3001 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3002
3003   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3004    [],
3005    "determine file type inside a compressed file",
3006    "\
3007 This command runs C<file> after first decompressing C<path>
3008 using C<method>.
3009
3010 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3011
3012 Since 1.0.63, use C<guestfs_file> instead which can now
3013 process compressed files.");
3014
3015   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3016    [],
3017    "list extended attributes of a file or directory",
3018    "\
3019 This call lists the extended attributes of the file or directory
3020 C<path>.
3021
3022 At the system call level, this is a combination of the
3023 L<listxattr(2)> and L<getxattr(2)> calls.
3024
3025 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3026
3027   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3028    [],
3029    "list extended attributes of a file or directory",
3030    "\
3031 This is the same as C<guestfs_getxattrs>, but if C<path>
3032 is a symbolic link, then it returns the extended attributes
3033 of the link itself.");
3034
3035   ("setxattr", (RErr, [String "xattr";
3036                        String "val"; Int "vallen"; (* will be BufferIn *)
3037                        Pathname "path"]), 143, [],
3038    [],
3039    "set extended attribute of a file or directory",
3040    "\
3041 This call sets the extended attribute named C<xattr>
3042 of the file C<path> to the value C<val> (of length C<vallen>).
3043 The value is arbitrary 8 bit data.
3044
3045 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3046
3047   ("lsetxattr", (RErr, [String "xattr";
3048                         String "val"; Int "vallen"; (* will be BufferIn *)
3049                         Pathname "path"]), 144, [],
3050    [],
3051    "set extended attribute of a file or directory",
3052    "\
3053 This is the same as C<guestfs_setxattr>, but if C<path>
3054 is a symbolic link, then it sets an extended attribute
3055 of the link itself.");
3056
3057   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3058    [],
3059    "remove extended attribute of a file or directory",
3060    "\
3061 This call removes the extended attribute named C<xattr>
3062 of the file C<path>.
3063
3064 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3065
3066   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3067    [],
3068    "remove extended attribute of a file or directory",
3069    "\
3070 This is the same as C<guestfs_removexattr>, but if C<path>
3071 is a symbolic link, then it removes an extended attribute
3072 of the link itself.");
3073
3074   ("mountpoints", (RHashtable "mps", []), 147, [],
3075    [],
3076    "show mountpoints",
3077    "\
3078 This call is similar to C<guestfs_mounts>.  That call returns
3079 a list of devices.  This one returns a hash table (map) of
3080 device name to directory where the device is mounted.");
3081
3082   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3083   (* This is a special case: while you would expect a parameter
3084    * of type "Pathname", that doesn't work, because it implies
3085    * NEED_ROOT in the generated calling code in stubs.c, and
3086    * this function cannot use NEED_ROOT.
3087    *)
3088    [],
3089    "create a mountpoint",
3090    "\
3091 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3092 specialized calls that can be used to create extra mountpoints
3093 before mounting the first filesystem.
3094
3095 These calls are I<only> necessary in some very limited circumstances,
3096 mainly the case where you want to mount a mix of unrelated and/or
3097 read-only filesystems together.
3098
3099 For example, live CDs often contain a \"Russian doll\" nest of
3100 filesystems, an ISO outer layer, with a squashfs image inside, with
3101 an ext2/3 image inside that.  You can unpack this as follows
3102 in guestfish:
3103
3104  add-ro Fedora-11-i686-Live.iso
3105  run
3106  mkmountpoint /cd
3107  mkmountpoint /squash
3108  mkmountpoint /ext3
3109  mount /dev/sda /cd
3110  mount-loop /cd/LiveOS/squashfs.img /squash
3111  mount-loop /squash/LiveOS/ext3fs.img /ext3
3112
3113 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3114
3115   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3116    [],
3117    "remove a mountpoint",
3118    "\
3119 This calls removes a mountpoint that was previously created
3120 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3121 for full details.");
3122
3123   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3124    [InitISOFS, Always, TestOutputBuffer (
3125       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3126    "read a file",
3127    "\
3128 This calls returns the contents of the file C<path> as a
3129 buffer.
3130
3131 Unlike C<guestfs_cat>, this function can correctly
3132 handle files that contain embedded ASCII NUL characters.
3133 However unlike C<guestfs_download>, this function is limited
3134 in the total size of file that can be handled.");
3135
3136   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3137    [InitISOFS, Always, TestOutputList (
3138       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3139     InitISOFS, Always, TestOutputList (
3140       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3141    "return lines matching a pattern",
3142    "\
3143 This calls the external C<grep> program and returns the
3144 matching lines.");
3145
3146   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3147    [InitISOFS, Always, TestOutputList (
3148       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3149    "return lines matching a pattern",
3150    "\
3151 This calls the external C<egrep> program and returns the
3152 matching lines.");
3153
3154   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3155    [InitISOFS, Always, TestOutputList (
3156       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3157    "return lines matching a pattern",
3158    "\
3159 This calls the external C<fgrep> program and returns the
3160 matching lines.");
3161
3162   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3163    [InitISOFS, Always, TestOutputList (
3164       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3165    "return lines matching a pattern",
3166    "\
3167 This calls the external C<grep -i> program and returns the
3168 matching lines.");
3169
3170   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3171    [InitISOFS, Always, TestOutputList (
3172       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3173    "return lines matching a pattern",
3174    "\
3175 This calls the external C<egrep -i> program and returns the
3176 matching lines.");
3177
3178   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3179    [InitISOFS, Always, TestOutputList (
3180       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3181    "return lines matching a pattern",
3182    "\
3183 This calls the external C<fgrep -i> program and returns the
3184 matching lines.");
3185
3186   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3187    [InitISOFS, Always, TestOutputList (
3188       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3189    "return lines matching a pattern",
3190    "\
3191 This calls the external C<zgrep> program and returns the
3192 matching lines.");
3193
3194   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3195    [InitISOFS, Always, TestOutputList (
3196       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3197    "return lines matching a pattern",
3198    "\
3199 This calls the external C<zegrep> program and returns the
3200 matching lines.");
3201
3202   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3203    [InitISOFS, Always, TestOutputList (
3204       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3205    "return lines matching a pattern",
3206    "\
3207 This calls the external C<zfgrep> program and returns the
3208 matching lines.");
3209
3210   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3211    [InitISOFS, Always, TestOutputList (
3212       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3213    "return lines matching a pattern",
3214    "\
3215 This calls the external C<zgrep -i> program and returns the
3216 matching lines.");
3217
3218   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3219    [InitISOFS, Always, TestOutputList (
3220       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3221    "return lines matching a pattern",
3222    "\
3223 This calls the external C<zegrep -i> program and returns the
3224 matching lines.");
3225
3226   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3227    [InitISOFS, Always, TestOutputList (
3228       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3229    "return lines matching a pattern",
3230    "\
3231 This calls the external C<zfgrep -i> program and returns the
3232 matching lines.");
3233
3234   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3235    [InitISOFS, Always, TestOutput (
3236       [["realpath"; "/../directory"]], "/directory")],
3237    "canonicalized absolute pathname",
3238    "\
3239 Return the canonicalized absolute pathname of C<path>.  The
3240 returned path has no C<.>, C<..> or symbolic link path elements.");
3241
3242   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3243    [InitBasicFS, Always, TestOutputStruct (
3244       [["touch"; "/a"];
3245        ["ln"; "/a"; "/b"];
3246        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3247    "create a hard link",
3248    "\
3249 This command creates a hard link using the C<ln> command.");
3250
3251   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3252    [InitBasicFS, Always, TestOutputStruct (
3253       [["touch"; "/a"];
3254        ["touch"; "/b"];
3255        ["ln_f"; "/a"; "/b"];
3256        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3257    "create a hard link",
3258    "\
3259 This command creates a hard link using the C<ln -f> command.
3260 The C<-f> option removes the link (C<linkname>) if it exists already.");
3261
3262   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3263    [InitBasicFS, Always, TestOutputStruct (
3264       [["touch"; "/a"];
3265        ["ln_s"; "a"; "/b"];
3266        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3267    "create a symbolic link",
3268    "\
3269 This command creates a symbolic link using the C<ln -s> command.");
3270
3271   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3272    [InitBasicFS, Always, TestOutput (
3273       [["mkdir_p"; "/a/b"];
3274        ["touch"; "/a/b/c"];
3275        ["ln_sf"; "../d"; "/a/b/c"];
3276        ["readlink"; "/a/b/c"]], "../d")],
3277    "create a symbolic link",
3278    "\
3279 This command creates a symbolic link using the C<ln -sf> command,
3280 The C<-f> option removes the link (C<linkname>) if it exists already.");
3281
3282   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3283    [] (* XXX tested above *),
3284    "read the target of a symbolic link",
3285    "\
3286 This command reads the target of a symbolic link.");
3287
3288   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3289    [InitBasicFS, Always, TestOutputStruct (
3290       [["fallocate"; "/a"; "1000000"];
3291        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3292    "preallocate a file in the guest filesystem",
3293    "\
3294 This command preallocates a file (containing zero bytes) named
3295 C<path> of size C<len> bytes.  If the file exists already, it
3296 is overwritten.
3297
3298 Do not confuse this with the guestfish-specific
3299 C<alloc> command which allocates a file in the host and
3300 attaches it as a device.");
3301
3302   ("swapon_device", (RErr, [Device "device"]), 170, [],
3303    [InitPartition, Always, TestRun (
3304       [["mkswap"; "/dev/sda1"];
3305        ["swapon_device"; "/dev/sda1"];
3306        ["swapoff_device"; "/dev/sda1"]])],
3307    "enable swap on device",
3308    "\
3309 This command enables the libguestfs appliance to use the
3310 swap device or partition named C<device>.  The increased
3311 memory is made available for all commands, for example
3312 those run using C<guestfs_command> or C<guestfs_sh>.
3313
3314 Note that you should not swap to existing guest swap
3315 partitions unless you know what you are doing.  They may
3316 contain hibernation information, or other information that
3317 the guest doesn't want you to trash.  You also risk leaking
3318 information about the host to the guest this way.  Instead,
3319 attach a new host device to the guest and swap on that.");
3320
3321   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3322    [], (* XXX tested by swapon_device *)
3323    "disable swap on device",
3324    "\
3325 This command disables the libguestfs appliance swap
3326 device or partition named C<device>.
3327 See C<guestfs_swapon_device>.");
3328
3329   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3330    [InitBasicFS, Always, TestRun (
3331       [["fallocate"; "/swap"; "8388608"];
3332        ["mkswap_file"; "/swap"];
3333        ["swapon_file"; "/swap"];
3334        ["swapoff_file"; "/swap"]])],
3335    "enable swap on file",
3336    "\
3337 This command enables swap to a file.
3338 See C<guestfs_swapon_device> for other notes.");
3339
3340   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3341    [], (* XXX tested by swapon_file *)
3342    "disable swap on file",
3343    "\
3344 This command disables the libguestfs appliance swap on file.");
3345
3346   ("swapon_label", (RErr, [String "label"]), 174, [],
3347    [InitEmpty, Always, TestRun (
3348       [["sfdiskM"; "/dev/sdb"; ","];
3349        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3350        ["swapon_label"; "swapit"];
3351        ["swapoff_label"; "swapit"];
3352        ["zero"; "/dev/sdb"];
3353        ["blockdev_rereadpt"; "/dev/sdb"]])],
3354    "enable swap on labeled swap partition",
3355    "\
3356 This command enables swap to a labeled swap partition.
3357 See C<guestfs_swapon_device> for other notes.");
3358
3359   ("swapoff_label", (RErr, [String "label"]), 175, [],
3360    [], (* XXX tested by swapon_label *)
3361    "disable swap on labeled swap partition",
3362    "\
3363 This command disables the libguestfs appliance swap on
3364 labeled swap partition.");
3365
3366   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3367    (let uuid = uuidgen () in
3368     [InitEmpty, Always, TestRun (
3369        [["mkswap_U"; uuid; "/dev/sdb"];
3370         ["swapon_uuid"; uuid];
3371         ["swapoff_uuid"; uuid]])]),
3372    "enable swap on swap partition by UUID",
3373    "\
3374 This command enables swap to a swap partition with the given UUID.
3375 See C<guestfs_swapon_device> for other notes.");
3376
3377   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3378    [], (* XXX tested by swapon_uuid *)
3379    "disable swap on swap partition by UUID",
3380    "\
3381 This command disables the libguestfs appliance swap partition
3382 with the given UUID.");
3383
3384   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3385    [InitBasicFS, Always, TestRun (
3386       [["fallocate"; "/swap"; "8388608"];
3387        ["mkswap_file"; "/swap"]])],
3388    "create a swap file",
3389    "\
3390 Create a swap file.
3391
3392 This command just writes a swap file signature to an existing
3393 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3394
3395   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3396    [InitISOFS, Always, TestRun (
3397       [["inotify_init"; "0"]])],
3398    "create an inotify handle",
3399    "\
3400 This command creates a new inotify handle.
3401 The inotify subsystem can be used to notify events which happen to
3402 objects in the guest filesystem.
3403
3404 C<maxevents> is the maximum number of events which will be
3405 queued up between calls to C<guestfs_inotify_read> or
3406 C<guestfs_inotify_files>.
3407 If this is passed as C<0>, then the kernel (or previously set)
3408 default is used.  For Linux 2.6.29 the default was 16384 events.
3409 Beyond this limit, the kernel throws away events, but records
3410 the fact that it threw them away by setting a flag
3411 C<IN_Q_OVERFLOW> in the returned structure list (see
3412 C<guestfs_inotify_read>).
3413
3414 Before any events are generated, you have to add some
3415 watches to the internal watch list.  See:
3416 C<guestfs_inotify_add_watch>,
3417 C<guestfs_inotify_rm_watch> and
3418 C<guestfs_inotify_watch_all>.
3419
3420 Queued up events should be read periodically by calling
3421 C<guestfs_inotify_read>
3422 (or C<guestfs_inotify_files> which is just a helpful
3423 wrapper around C<guestfs_inotify_read>).  If you don't
3424 read the events out often enough then you risk the internal
3425 queue overflowing.
3426
3427 The handle should be closed after use by calling
3428 C<guestfs_inotify_close>.  This also removes any
3429 watches automatically.
3430
3431 See also L<inotify(7)> for an overview of the inotify interface
3432 as exposed by the Linux kernel, which is roughly what we expose
3433 via libguestfs.  Note that there is one global inotify handle
3434 per libguestfs instance.");
3435
3436   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3437    [InitBasicFS, Always, TestOutputList (
3438       [["inotify_init"; "0"];
3439        ["inotify_add_watch"; "/"; "1073741823"];
3440        ["touch"; "/a"];
3441        ["touch"; "/b"];
3442        ["inotify_files"]], ["a"; "b"])],
3443    "add an inotify watch",
3444    "\
3445 Watch C<path> for the events listed in C<mask>.
3446
3447 Note that if C<path> is a directory then events within that
3448 directory are watched, but this does I<not> happen recursively
3449 (in subdirectories).
3450
3451 Note for non-C or non-Linux callers: the inotify events are
3452 defined by the Linux kernel ABI and are listed in
3453 C</usr/include/sys/inotify.h>.");
3454
3455   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3456    [],
3457    "remove an inotify watch",
3458    "\
3459 Remove a previously defined inotify watch.
3460 See C<guestfs_inotify_add_watch>.");
3461
3462   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3463    [],
3464    "return list of inotify events",
3465    "\
3466 Return the complete queue of events that have happened
3467 since the previous read call.
3468
3469 If no events have happened, this returns an empty list.
3470
3471 I<Note>: In order to make sure that all events have been
3472 read, you must call this function repeatedly until it
3473 returns an empty list.  The reason is that the call will
3474 read events up to the maximum appliance-to-host message
3475 size and leave remaining events in the queue.");
3476
3477   ("inotify_files", (RStringList "paths", []), 183, [],
3478    [],
3479    "return list of watched files that had events",
3480    "\
3481 This function is a helpful wrapper around C<guestfs_inotify_read>
3482 which just returns a list of pathnames of objects that were
3483 touched.  The returned pathnames are sorted and deduplicated.");
3484
3485   ("inotify_close", (RErr, []), 184, [],
3486    [],
3487    "close the inotify handle",
3488    "\
3489 This closes the inotify handle which was previously
3490 opened by inotify_init.  It removes all watches, throws
3491 away any pending events, and deallocates all resources.");
3492
3493   ("setcon", (RErr, [String "context"]), 185, [],
3494    [],
3495    "set SELinux security context",
3496    "\
3497 This sets the SELinux security context of the daemon
3498 to the string C<context>.
3499
3500 See the documentation about SELINUX in L<guestfs(3)>.");
3501
3502   ("getcon", (RString "context", []), 186, [],
3503    [],
3504    "get SELinux security context",
3505    "\
3506 This gets the SELinux security context of the daemon.
3507
3508 See the documentation about SELINUX in L<guestfs(3)>,
3509 and C<guestfs_setcon>");
3510
3511   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3512    [InitEmpty, Always, TestOutput (
3513       [["sfdiskM"; "/dev/sda"; ","];
3514        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3515        ["mount"; "/dev/sda1"; "/"];
3516        ["write_file"; "/new"; "new file contents"; "0"];
3517        ["cat"; "/new"]], "new file contents")],
3518    "make a filesystem with block size",
3519    "\
3520 This call is similar to C<guestfs_mkfs>, but it allows you to
3521 control the block size of the resulting filesystem.  Supported
3522 block sizes depend on the filesystem type, but typically they
3523 are C<1024>, C<2048> or C<4096> only.");
3524
3525   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3526    [InitEmpty, Always, TestOutput (
3527       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3528        ["mke2journal"; "4096"; "/dev/sda1"];
3529        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3530        ["mount"; "/dev/sda2"; "/"];
3531        ["write_file"; "/new"; "new file contents"; "0"];
3532        ["cat"; "/new"]], "new file contents")],
3533    "make ext2/3/4 external journal",
3534    "\
3535 This creates an ext2 external journal on C<device>.  It is equivalent
3536 to the command:
3537
3538  mke2fs -O journal_dev -b blocksize device");
3539
3540   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3541    [InitEmpty, Always, TestOutput (
3542       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3543        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3544        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3545        ["mount"; "/dev/sda2"; "/"];
3546        ["write_file"; "/new"; "new file contents"; "0"];
3547        ["cat"; "/new"]], "new file contents")],
3548    "make ext2/3/4 external journal with label",
3549    "\
3550 This creates an ext2 external journal on C<device> with label C<label>.");
3551
3552   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3553    (let uuid = uuidgen () in
3554     [InitEmpty, Always, TestOutput (
3555        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3556         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3557         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3558         ["mount"; "/dev/sda2"; "/"];
3559         ["write_file"; "/new"; "new file contents"; "0"];
3560         ["cat"; "/new"]], "new file contents")]),
3561    "make ext2/3/4 external journal with UUID",
3562    "\
3563 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3564
3565   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3566    [],
3567    "make ext2/3/4 filesystem with external journal",
3568    "\
3569 This creates an ext2/3/4 filesystem on C<device> with
3570 an external journal on C<journal>.  It is equivalent
3571 to the command:
3572
3573  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3574
3575 See also C<guestfs_mke2journal>.");
3576
3577   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3578    [],
3579    "make ext2/3/4 filesystem with external journal",
3580    "\
3581 This creates an ext2/3/4 filesystem on C<device> with
3582 an external journal on the journal labeled C<label>.
3583
3584 See also C<guestfs_mke2journal_L>.");
3585
3586   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3587    [],
3588    "make ext2/3/4 filesystem with external journal",
3589    "\
3590 This creates an ext2/3/4 filesystem on C<device> with
3591 an external journal on the journal with UUID C<uuid>.
3592
3593 See also C<guestfs_mke2journal_U>.");
3594
3595   ("modprobe", (RErr, [String "modulename"]), 194, [],
3596    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3597    "load a kernel module",
3598    "\
3599 This loads a kernel module in the appliance.
3600
3601 The kernel module must have been whitelisted when libguestfs
3602 was built (see C<appliance/kmod.whitelist.in> in the source).");
3603
3604   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3605    [InitNone, Always, TestOutput (
3606      [["echo_daemon"; "This is a test"]], "This is a test"
3607    )],
3608    "echo arguments back to the client",
3609    "\
3610 This command concatenate the list of C<words> passed with single spaces between
3611 them and returns the resulting string.
3612
3613 You can use this command to test the connection through to the daemon.
3614
3615 See also C<guestfs_ping_daemon>.");
3616
3617   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3618    [], (* There is a regression test for this. *)
3619    "find all files and directories, returning NUL-separated list",
3620    "\
3621 This command lists out all files and directories, recursively,
3622 starting at C<directory>, placing the resulting list in the
3623 external file called C<files>.
3624
3625 This command works the same way as C<guestfs_find> with the
3626 following exceptions:
3627
3628 =over 4
3629
3630 =item *
3631
3632 The resulting list is written to an external file.
3633
3634 =item *
3635
3636 Items (filenames) in the result are separated
3637 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3638
3639 =item *
3640
3641 This command is not limited in the number of names that it
3642 can return.
3643
3644 =item *
3645
3646 The result list is not sorted.
3647
3648 =back");
3649
3650   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3651    [InitISOFS, Always, TestOutput (
3652       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3653     InitISOFS, Always, TestOutput (
3654       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3655     InitISOFS, Always, TestOutput (
3656       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3657     InitISOFS, Always, TestLastFail (
3658       [["case_sensitive_path"; "/Known-1/"]]);
3659     InitBasicFS, Always, TestOutput (
3660       [["mkdir"; "/a"];
3661        ["mkdir"; "/a/bbb"];
3662        ["touch"; "/a/bbb/c"];
3663        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3664     InitBasicFS, Always, TestOutput (
3665       [["mkdir"; "/a"];
3666        ["mkdir"; "/a/bbb"];
3667        ["touch"; "/a/bbb/c"];
3668        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3669     InitBasicFS, Always, TestLastFail (
3670       [["mkdir"; "/a"];
3671        ["mkdir"; "/a/bbb"];
3672        ["touch"; "/a/bbb/c"];
3673        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3674    "return true path on case-insensitive filesystem",
3675    "\
3676 This can be used to resolve case insensitive paths on
3677 a filesystem which is case sensitive.  The use case is
3678 to resolve paths which you have read from Windows configuration
3679 files or the Windows Registry, to the true path.
3680
3681 The command handles a peculiarity of the Linux ntfs-3g
3682 filesystem driver (and probably others), which is that although
3683 the underlying filesystem is case-insensitive, the driver
3684 exports the filesystem to Linux as case-sensitive.
3685
3686 One consequence of this is that special directories such
3687 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3688 (or other things) depending on the precise details of how
3689 they were created.  In Windows itself this would not be
3690 a problem.
3691
3692 Bug or feature?  You decide:
3693 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3694
3695 This function resolves the true case of each element in the
3696 path and returns the case-sensitive path.
3697
3698 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3699 might return C<\"/WINDOWS/system32\"> (the exact return value
3700 would depend on details of how the directories were originally
3701 created under Windows).
3702
3703 I<Note>:
3704 This function does not handle drive names, backslashes etc.
3705
3706 See also C<guestfs_realpath>.");
3707
3708   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3709    [InitBasicFS, Always, TestOutput (
3710       [["vfs_type"; "/dev/sda1"]], "ext2")],
3711    "get the Linux VFS type corresponding to a mounted device",
3712    "\
3713 This command gets the block device type corresponding to
3714 a mounted device called C<device>.
3715
3716 Usually the result is the name of the Linux VFS module that
3717 is used to mount this device (probably determined automatically
3718 if you used the C<guestfs_mount> call).");
3719
3720   ("truncate", (RErr, [Pathname "path"]), 199, [],
3721    [InitBasicFS, Always, TestOutputStruct (
3722       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3723        ["truncate"; "/test"];
3724        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3725    "truncate a file to zero size",
3726    "\
3727 This command truncates C<path> to a zero-length file.  The
3728 file must exist already.");
3729
3730   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3731    [InitBasicFS, Always, TestOutputStruct (
3732       [["touch"; "/test"];
3733        ["truncate_size"; "/test"; "1000"];
3734        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3735    "truncate a file to a particular size",
3736    "\
3737 This command truncates C<path> to size C<size> bytes.  The file
3738 must exist already.  If the file is smaller than C<size> then
3739 the file is extended to the required size with null bytes.");
3740
3741   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3742    [InitBasicFS, Always, TestOutputStruct (
3743       [["touch"; "/test"];
3744        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3745        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3746    "set timestamp of a file with nanosecond precision",
3747    "\
3748 This command sets the timestamps of a file with nanosecond
3749 precision.
3750
3751 C<atsecs, atnsecs> are the last access time (atime) in secs and
3752 nanoseconds from the epoch.
3753
3754 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3755 secs and nanoseconds from the epoch.
3756
3757 If the C<*nsecs> field contains the special value C<-1> then
3758 the corresponding timestamp is set to the current time.  (The
3759 C<*secs> field is ignored in this case).
3760
3761 If the C<*nsecs> field contains the special value C<-2> then
3762 the corresponding timestamp is left unchanged.  (The
3763 C<*secs> field is ignored in this case).");
3764
3765   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3766    [InitBasicFS, Always, TestOutputStruct (
3767       [["mkdir_mode"; "/test"; "0o111"];
3768        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3769    "create a directory with a particular mode",
3770    "\
3771 This command creates a directory, setting the initial permissions
3772 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3773
3774   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3775    [], (* XXX *)
3776    "change file owner and group",
3777    "\
3778 Change the file owner to C<owner> and group to C<group>.
3779 This is like C<guestfs_chown> but if C<path> is a symlink then
3780 the link itself is changed, not the target.
3781
3782 Only numeric uid and gid are supported.  If you want to use
3783 names, you will need to locate and parse the password file
3784 yourself (Augeas support makes this relatively easy).");
3785
3786   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3787    [], (* XXX *)
3788    "lstat on multiple files",
3789    "\
3790 This call allows you to perform the C<guestfs_lstat> operation
3791 on multiple files, where all files are in the directory C<path>.
3792 C<names> is the list of files from this directory.
3793
3794 On return you get a list of stat structs, with a one-to-one
3795 correspondence to the C<names> list.  If any name did not exist
3796 or could not be lstat'd, then the C<ino> field of that structure
3797 is set to C<-1>.
3798
3799 This call is intended for programs that want to efficiently
3800 list a directory contents without making many round-trips.
3801 See also C<guestfs_lxattrlist> for a similarly efficient call
3802 for getting extended attributes.  Very long directory listings
3803 might cause the protocol message size to be exceeded, causing
3804 this call to fail.  The caller must split up such requests
3805 into smaller groups of names.");
3806
3807   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
3808    [], (* XXX *)
3809    "lgetxattr on multiple files",
3810    "\
3811 This call allows you to get the extended attributes
3812 of multiple files, where all files are in the directory C<path>.
3813 C<names> is the list of files from this directory.
3814
3815 On return you get a flat list of xattr structs which must be
3816 interpreted sequentially.  The first xattr struct always has a zero-length
3817 C<attrname>.  C<attrval> in this struct is zero-length
3818 to indicate there was an error doing C<lgetxattr> for this
3819 file, I<or> is a C string which is a decimal number
3820 (the number of following attributes for this file, which could
3821 be C<\"0\">).  Then after the first xattr struct are the
3822 zero or more attributes for the first named file.
3823 This repeats for the second and subsequent files.
3824
3825 This call is intended for programs that want to efficiently
3826 list a directory contents without making many round-trips.
3827 See also C<guestfs_lstatlist> for a similarly efficient call
3828 for getting standard stats.  Very long directory listings
3829 might cause the protocol message size to be exceeded, causing
3830 this call to fail.  The caller must split up such requests
3831 into smaller groups of names.");
3832
3833   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3834    [], (* XXX *)
3835    "readlink on multiple files",
3836    "\
3837 This call allows you to do a C<readlink> operation
3838 on multiple files, where all files are in the directory C<path>.
3839 C<names> is the list of files from this directory.
3840
3841 On return you get a list of strings, with a one-to-one
3842 correspondence to the C<names> list.  Each string is the
3843 value of the symbol link.
3844
3845 If the C<readlink(2)> operation fails on any name, then
3846 the corresponding result string is the empty string C<\"\">.
3847 However the whole operation is completed even if there
3848 were C<readlink(2)> errors, and so you can call this
3849 function with names where you don't know if they are
3850 symbolic links already (albeit slightly less efficient).
3851
3852 This call is intended for programs that want to efficiently
3853 list a directory contents without making many round-trips.
3854 Very long directory listings might cause the protocol
3855 message size to be exceeded, causing
3856 this call to fail.  The caller must split up such requests
3857 into smaller groups of names.");
3858
3859 ]
3860
3861 let all_functions = non_daemon_functions @ daemon_functions
3862
3863 (* In some places we want the functions to be displayed sorted
3864  * alphabetically, so this is useful:
3865  *)
3866 let all_functions_sorted =
3867   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3868                compare n1 n2) all_functions
3869
3870 (* Field types for structures. *)
3871 type field =
3872   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3873   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3874   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3875   | FUInt32
3876   | FInt32
3877   | FUInt64
3878   | FInt64
3879   | FBytes                      (* Any int measure that counts bytes. *)
3880   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3881   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3882
3883 (* Because we generate extra parsing code for LVM command line tools,
3884  * we have to pull out the LVM columns separately here.
3885  *)
3886 let lvm_pv_cols = [
3887   "pv_name", FString;
3888   "pv_uuid", FUUID;
3889   "pv_fmt", FString;
3890   "pv_size", FBytes;
3891   "dev_size", FBytes;
3892   "pv_free", FBytes;
3893   "pv_used", FBytes;
3894   "pv_attr", FString (* XXX *);
3895   "pv_pe_count", FInt64;
3896   "pv_pe_alloc_count", FInt64;
3897   "pv_tags", FString;
3898   "pe_start", FBytes;
3899   "pv_mda_count", FInt64;
3900   "pv_mda_free", FBytes;
3901   (* Not in Fedora 10:
3902      "pv_mda_size", FBytes;
3903   *)
3904 ]
3905 let lvm_vg_cols = [
3906   "vg_name", FString;
3907   "vg_uuid", FUUID;
3908   "vg_fmt", FString;
3909   "vg_attr", FString (* XXX *);
3910   "vg_size", FBytes;
3911   "vg_free", FBytes;
3912   "vg_sysid", FString;
3913   "vg_extent_size", FBytes;
3914   "vg_extent_count", FInt64;
3915   "vg_free_count", FInt64;
3916   "max_lv", FInt64;
3917   "max_pv", FInt64;
3918   "pv_count", FInt64;
3919   "lv_count", FInt64;
3920   "snap_count", FInt64;
3921   "vg_seqno", FInt64;
3922   "vg_tags", FString;
3923   "vg_mda_count", FInt64;
3924   "vg_mda_free", FBytes;
3925   (* Not in Fedora 10:
3926      "vg_mda_size", FBytes;
3927   *)
3928 ]
3929 let lvm_lv_cols = [
3930   "lv_name", FString;
3931   "lv_uuid", FUUID;
3932   "lv_attr", FString (* XXX *);
3933   "lv_major", FInt64;
3934   "lv_minor", FInt64;
3935   "lv_kernel_major", FInt64;
3936   "lv_kernel_minor", FInt64;
3937   "lv_size", FBytes;
3938   "seg_count", FInt64;
3939   "origin", FString;
3940   "snap_percent", FOptPercent;
3941   "copy_percent", FOptPercent;
3942   "move_pv", FString;
3943   "lv_tags", FString;
3944   "mirror_log", FString;
3945   "modules", FString;
3946 ]
3947
3948 (* Names and fields in all structures (in RStruct and RStructList)
3949  * that we support.
3950  *)
3951 let structs = [
3952   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3953    * not use this struct in any new code.
3954    *)
3955   "int_bool", [
3956     "i", FInt32;                (* for historical compatibility *)
3957     "b", FInt32;                (* for historical compatibility *)
3958   ];
3959
3960   (* LVM PVs, VGs, LVs. *)
3961   "lvm_pv", lvm_pv_cols;
3962   "lvm_vg", lvm_vg_cols;
3963   "lvm_lv", lvm_lv_cols;
3964
3965   (* Column names and types from stat structures.
3966    * NB. Can't use things like 'st_atime' because glibc header files
3967    * define some of these as macros.  Ugh.
3968    *)
3969   "stat", [
3970     "dev", FInt64;
3971     "ino", FInt64;
3972     "mode", FInt64;
3973     "nlink", FInt64;
3974     "uid", FInt64;
3975     "gid", FInt64;
3976     "rdev", FInt64;
3977     "size", FInt64;
3978     "blksize", FInt64;
3979     "blocks", FInt64;
3980     "atime", FInt64;
3981     "mtime", FInt64;
3982     "ctime", FInt64;
3983   ];
3984   "statvfs", [
3985     "bsize", FInt64;
3986     "frsize", FInt64;
3987     "blocks", FInt64;
3988     "bfree", FInt64;
3989     "bavail", FInt64;
3990     "files", FInt64;
3991     "ffree", FInt64;
3992     "favail", FInt64;
3993     "fsid", FInt64;
3994     "flag", FInt64;
3995     "namemax", FInt64;
3996   ];
3997
3998   (* Column names in dirent structure. *)
3999   "dirent", [
4000     "ino", FInt64;
4001     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4002     "ftyp", FChar;
4003     "name", FString;
4004   ];
4005
4006   (* Version numbers. *)
4007   "version", [
4008     "major", FInt64;
4009     "minor", FInt64;
4010     "release", FInt64;
4011     "extra", FString;
4012   ];
4013
4014   (* Extended attribute. *)
4015   "xattr", [
4016     "attrname", FString;
4017     "attrval", FBuffer;
4018   ];
4019
4020   (* Inotify events. *)
4021   "inotify_event", [
4022     "in_wd", FInt64;
4023     "in_mask", FUInt32;
4024     "in_cookie", FUInt32;
4025     "in_name", FString;
4026   ];
4027 ] (* end of structs *)
4028
4029 (* Ugh, Java has to be different ..
4030  * These names are also used by the Haskell bindings.
4031  *)
4032 let java_structs = [
4033   "int_bool", "IntBool";
4034   "lvm_pv", "PV";
4035   "lvm_vg", "VG";
4036   "lvm_lv", "LV";
4037   "stat", "Stat";
4038   "statvfs", "StatVFS";
4039   "dirent", "Dirent";
4040   "version", "Version";
4041   "xattr", "XAttr";
4042   "inotify_event", "INotifyEvent";
4043 ]
4044
4045 (* What structs are actually returned. *)
4046 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4047
4048 (* Returns a list of RStruct/RStructList structs that are returned
4049  * by any function.  Each element of returned list is a pair:
4050  *
4051  * (structname, RStructOnly)
4052  *    == there exists function which returns RStruct (_, structname)
4053  * (structname, RStructListOnly)
4054  *    == there exists function which returns RStructList (_, structname)
4055  * (structname, RStructAndList)
4056  *    == there are functions returning both RStruct (_, structname)
4057  *                                      and RStructList (_, structname)
4058  *)
4059 let rstructs_used_by functions =
4060   (* ||| is a "logical OR" for rstructs_used_t *)
4061   let (|||) a b =
4062     match a, b with
4063     | RStructAndList, _
4064     | _, RStructAndList -> RStructAndList
4065     | RStructOnly, RStructListOnly
4066     | RStructListOnly, RStructOnly -> RStructAndList
4067     | RStructOnly, RStructOnly -> RStructOnly
4068     | RStructListOnly, RStructListOnly -> RStructListOnly
4069   in
4070
4071   let h = Hashtbl.create 13 in
4072
4073   (* if elem->oldv exists, update entry using ||| operator,
4074    * else just add elem->newv to the hash
4075    *)
4076   let update elem newv =
4077     try  let oldv = Hashtbl.find h elem in
4078          Hashtbl.replace h elem (newv ||| oldv)
4079     with Not_found -> Hashtbl.add h elem newv
4080   in
4081
4082   List.iter (
4083     fun (_, style, _, _, _, _, _) ->
4084       match fst style with
4085       | RStruct (_, structname) -> update structname RStructOnly
4086       | RStructList (_, structname) -> update structname RStructListOnly
4087       | _ -> ()
4088   ) functions;
4089
4090   (* return key->values as a list of (key,value) *)
4091   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4092
4093 (* Used for testing language bindings. *)
4094 type callt =
4095   | CallString of string
4096   | CallOptString of string option
4097   | CallStringList of string list
4098   | CallInt of int
4099   | CallInt64 of int64
4100   | CallBool of bool
4101
4102 (* Used to memoize the result of pod2text. *)
4103 let pod2text_memo_filename = "src/.pod2text.data"
4104 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4105   try
4106     let chan = open_in pod2text_memo_filename in
4107     let v = input_value chan in
4108     close_in chan;
4109     v
4110   with
4111     _ -> Hashtbl.create 13
4112 let pod2text_memo_updated () =
4113   let chan = open_out pod2text_memo_filename in
4114   output_value chan pod2text_memo;
4115   close_out chan
4116
4117 (* Useful functions.
4118  * Note we don't want to use any external OCaml libraries which
4119  * makes this a bit harder than it should be.
4120  *)
4121 let failwithf fs = ksprintf failwith fs
4122
4123 let replace_char s c1 c2 =
4124   let s2 = String.copy s in
4125   let r = ref false in
4126   for i = 0 to String.length s2 - 1 do
4127     if String.unsafe_get s2 i = c1 then (
4128       String.unsafe_set s2 i c2;
4129       r := true
4130     )
4131   done;
4132   if not !r then s else s2
4133
4134 let isspace c =
4135   c = ' '
4136   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4137
4138 let triml ?(test = isspace) str =
4139   let i = ref 0 in
4140   let n = ref (String.length str) in
4141   while !n > 0 && test str.[!i]; do
4142     decr n;
4143     incr i
4144   done;
4145   if !i = 0 then str
4146   else String.sub str !i !n
4147
4148 let trimr ?(test = isspace) str =
4149   let n = ref (String.length str) in
4150   while !n > 0 && test str.[!n-1]; do
4151     decr n
4152   done;
4153   if !n = String.length str then str
4154   else String.sub str 0 !n
4155
4156 let trim ?(test = isspace) str =
4157   trimr ~test (triml ~test str)
4158
4159 let rec find s sub =
4160   let len = String.length s in
4161   let sublen = String.length sub in
4162   let rec loop i =
4163     if i <= len-sublen then (
4164       let rec loop2 j =
4165         if j < sublen then (
4166           if s.[i+j] = sub.[j] then loop2 (j+1)
4167           else -1
4168         ) else
4169           i (* found *)
4170       in
4171       let r = loop2 0 in
4172       if r = -1 then loop (i+1) else r
4173     ) else
4174       -1 (* not found *)
4175   in
4176   loop 0
4177
4178 let rec replace_str s s1 s2 =
4179   let len = String.length s in
4180   let sublen = String.length s1 in
4181   let i = find s s1 in
4182   if i = -1 then s
4183   else (
4184     let s' = String.sub s 0 i in
4185     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4186     s' ^ s2 ^ replace_str s'' s1 s2
4187   )
4188
4189 let rec string_split sep str =
4190   let len = String.length str in
4191   let seplen = String.length sep in
4192   let i = find str sep in
4193   if i = -1 then [str]
4194   else (
4195     let s' = String.sub str 0 i in
4196     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4197     s' :: string_split sep s''
4198   )
4199
4200 let files_equal n1 n2 =
4201   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4202   match Sys.command cmd with
4203   | 0 -> true
4204   | 1 -> false
4205   | i -> failwithf "%s: failed with error code %d" cmd i
4206
4207 let rec filter_map f = function
4208   | [] -> []
4209   | x :: xs ->
4210       match f x with
4211       | Some y -> y :: filter_map f xs
4212       | None -> filter_map f xs
4213
4214 let rec find_map f = function
4215   | [] -> raise Not_found
4216   | x :: xs ->
4217       match f x with
4218       | Some y -> y
4219       | None -> find_map f xs
4220
4221 let iteri f xs =
4222   let rec loop i = function
4223     | [] -> ()
4224     | x :: xs -> f i x; loop (i+1) xs
4225   in
4226   loop 0 xs
4227
4228 let mapi f xs =
4229   let rec loop i = function
4230     | [] -> []
4231     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4232   in
4233   loop 0 xs
4234
4235 let name_of_argt = function
4236   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4237   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4238   | FileIn n | FileOut n -> n
4239
4240 let java_name_of_struct typ =
4241   try List.assoc typ java_structs
4242   with Not_found ->
4243     failwithf
4244       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4245
4246 let cols_of_struct typ =
4247   try List.assoc typ structs
4248   with Not_found ->
4249     failwithf "cols_of_struct: unknown struct %s" typ
4250
4251 let seq_of_test = function
4252   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4253   | TestOutputListOfDevices (s, _)
4254   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4255   | TestOutputTrue s | TestOutputFalse s
4256   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4257   | TestOutputStruct (s, _)
4258   | TestLastFail s -> s
4259
4260 (* Handling for function flags. *)
4261 let protocol_limit_warning =
4262   "Because of the message protocol, there is a transfer limit
4263 of somewhere between 2MB and 4MB.  To transfer large files you should use
4264 FTP."
4265
4266 let danger_will_robinson =
4267   "B<This command is dangerous.  Without careful use you
4268 can easily destroy all your data>."
4269
4270 let deprecation_notice flags =
4271   try
4272     let alt =
4273       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4274     let txt =
4275       sprintf "This function is deprecated.
4276 In new code, use the C<%s> call instead.
4277
4278 Deprecated functions will not be removed from the API, but the
4279 fact that they are deprecated indicates that there are problems
4280 with correct use of these functions." alt in
4281     Some txt
4282   with
4283     Not_found -> None
4284
4285 (* Check function names etc. for consistency. *)
4286 let check_functions () =
4287   let contains_uppercase str =
4288     let len = String.length str in
4289     let rec loop i =
4290       if i >= len then false
4291       else (
4292         let c = str.[i] in
4293         if c >= 'A' && c <= 'Z' then true
4294         else loop (i+1)
4295       )
4296     in
4297     loop 0
4298   in
4299
4300   (* Check function names. *)
4301   List.iter (
4302     fun (name, _, _, _, _, _, _) ->
4303       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4304         failwithf "function name %s does not need 'guestfs' prefix" name;
4305       if name = "" then
4306         failwithf "function name is empty";
4307       if name.[0] < 'a' || name.[0] > 'z' then
4308         failwithf "function name %s must start with lowercase a-z" name;
4309       if String.contains name '-' then
4310         failwithf "function name %s should not contain '-', use '_' instead."
4311           name
4312   ) all_functions;
4313
4314   (* Check function parameter/return names. *)
4315   List.iter (
4316     fun (name, style, _, _, _, _, _) ->
4317       let check_arg_ret_name n =
4318         if contains_uppercase n then
4319           failwithf "%s param/ret %s should not contain uppercase chars"
4320             name n;
4321         if String.contains n '-' || String.contains n '_' then
4322           failwithf "%s param/ret %s should not contain '-' or '_'"
4323             name n;
4324         if n = "value" then
4325           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;
4326         if n = "int" || n = "char" || n = "short" || n = "long" then
4327           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4328         if n = "i" || n = "n" then
4329           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4330         if n = "argv" || n = "args" then
4331           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4332
4333         (* List Haskell, OCaml and C keywords here.
4334          * http://www.haskell.org/haskellwiki/Keywords
4335          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4336          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4337          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4338          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4339          * Omitting _-containing words, since they're handled above.
4340          * Omitting the OCaml reserved word, "val", is ok,
4341          * and saves us from renaming several parameters.
4342          *)
4343         let reserved = [
4344           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4345           "char"; "class"; "const"; "constraint"; "continue"; "data";
4346           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4347           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4348           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4349           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4350           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4351           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4352           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4353           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4354           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4355           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4356           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4357           "volatile"; "when"; "where"; "while";
4358           ] in
4359         if List.mem n reserved then
4360           failwithf "%s has param/ret using reserved word %s" name n;
4361       in
4362
4363       (match fst style with
4364        | RErr -> ()
4365        | RInt n | RInt64 n | RBool n
4366        | RConstString n | RConstOptString n | RString n
4367        | RStringList n | RStruct (n, _) | RStructList (n, _)
4368        | RHashtable n | RBufferOut n ->
4369            check_arg_ret_name n
4370       );
4371       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4372   ) all_functions;
4373
4374   (* Check short descriptions. *)
4375   List.iter (
4376     fun (name, _, _, _, _, shortdesc, _) ->
4377       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4378         failwithf "short description of %s should begin with lowercase." name;
4379       let c = shortdesc.[String.length shortdesc-1] in
4380       if c = '\n' || c = '.' then
4381         failwithf "short description of %s should not end with . or \\n." name
4382   ) all_functions;
4383
4384   (* Check long dscriptions. *)
4385   List.iter (
4386     fun (name, _, _, _, _, _, longdesc) ->
4387       if longdesc.[String.length longdesc-1] = '\n' then
4388         failwithf "long description of %s should not end with \\n." name
4389   ) all_functions;
4390
4391   (* Check proc_nrs. *)
4392   List.iter (
4393     fun (name, _, proc_nr, _, _, _, _) ->
4394       if proc_nr <= 0 then
4395         failwithf "daemon function %s should have proc_nr > 0" name
4396   ) daemon_functions;
4397
4398   List.iter (
4399     fun (name, _, proc_nr, _, _, _, _) ->
4400       if proc_nr <> -1 then
4401         failwithf "non-daemon function %s should have proc_nr -1" name
4402   ) non_daemon_functions;
4403
4404   let proc_nrs =
4405     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4406       daemon_functions in
4407   let proc_nrs =
4408     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4409   let rec loop = function
4410     | [] -> ()
4411     | [_] -> ()
4412     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4413         loop rest
4414     | (name1,nr1) :: (name2,nr2) :: _ ->
4415         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4416           name1 name2 nr1 nr2
4417   in
4418   loop proc_nrs;
4419
4420   (* Check tests. *)
4421   List.iter (
4422     function
4423       (* Ignore functions that have no tests.  We generate a
4424        * warning when the user does 'make check' instead.
4425        *)
4426     | name, _, _, _, [], _, _ -> ()
4427     | name, _, _, _, tests, _, _ ->
4428         let funcs =
4429           List.map (
4430             fun (_, _, test) ->
4431               match seq_of_test test with
4432               | [] ->
4433                   failwithf "%s has a test containing an empty sequence" name
4434               | cmds -> List.map List.hd cmds
4435           ) tests in
4436         let funcs = List.flatten funcs in
4437
4438         let tested = List.mem name funcs in
4439
4440         if not tested then
4441           failwithf "function %s has tests but does not test itself" name
4442   ) all_functions
4443
4444 (* 'pr' prints to the current output file. *)
4445 let chan = ref stdout
4446 let pr fs = ksprintf (output_string !chan) fs
4447
4448 (* Generate a header block in a number of standard styles. *)
4449 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4450 type license = GPLv2 | LGPLv2
4451
4452 let generate_header comment license =
4453   let c = match comment with
4454     | CStyle ->     pr "/* "; " *"
4455     | HashStyle ->  pr "# ";  "#"
4456     | OCamlStyle -> pr "(* "; " *"
4457     | HaskellStyle -> pr "{- "; "  " in
4458   pr "libguestfs generated file\n";
4459   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4460   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4461   pr "%s\n" c;
4462   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4463   pr "%s\n" c;
4464   (match license with
4465    | GPLv2 ->
4466        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4467        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4468        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4469        pr "%s (at your option) any later version.\n" c;
4470        pr "%s\n" c;
4471        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4472        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4473        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4474        pr "%s GNU General Public License for more details.\n" c;
4475        pr "%s\n" c;
4476        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4477        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4478        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4479
4480    | LGPLv2 ->
4481        pr "%s This library is free software; you can redistribute it and/or\n" c;
4482        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4483        pr "%s License as published by the Free Software Foundation; either\n" c;
4484        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4485        pr "%s\n" c;
4486        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4487        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4488        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4489        pr "%s Lesser General Public License for more details.\n" c;
4490        pr "%s\n" c;
4491        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4492        pr "%s License along with this library; if not, write to the Free Software\n" c;
4493        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4494   );
4495   (match comment with
4496    | CStyle -> pr " */\n"
4497    | HashStyle -> ()
4498    | OCamlStyle -> pr " *)\n"
4499    | HaskellStyle -> pr "-}\n"
4500   );
4501   pr "\n"
4502
4503 (* Start of main code generation functions below this line. *)
4504
4505 (* Generate the pod documentation for the C API. *)
4506 let rec generate_actions_pod () =
4507   List.iter (
4508     fun (shortname, style, _, flags, _, _, longdesc) ->
4509       if not (List.mem NotInDocs flags) then (
4510         let name = "guestfs_" ^ shortname in
4511         pr "=head2 %s\n\n" name;
4512         pr " ";
4513         generate_prototype ~extern:false ~handle:"handle" name style;
4514         pr "\n\n";
4515         pr "%s\n\n" longdesc;
4516         (match fst style with
4517          | RErr ->
4518              pr "This function returns 0 on success or -1 on error.\n\n"
4519          | RInt _ ->
4520              pr "On error this function returns -1.\n\n"
4521          | RInt64 _ ->
4522              pr "On error this function returns -1.\n\n"
4523          | RBool _ ->
4524              pr "This function returns a C truth value on success or -1 on error.\n\n"
4525          | RConstString _ ->
4526              pr "This function returns a string, or NULL on error.
4527 The string is owned by the guest handle and must I<not> be freed.\n\n"
4528          | RConstOptString _ ->
4529              pr "This function returns a string which may be NULL.
4530 There is way to return an error from this function.
4531 The string is owned by the guest handle and must I<not> be freed.\n\n"
4532          | RString _ ->
4533              pr "This function returns a string, or NULL on error.
4534 I<The caller must free the returned string after use>.\n\n"
4535          | RStringList _ ->
4536              pr "This function returns a NULL-terminated array of strings
4537 (like L<environ(3)>), or NULL if there was an error.
4538 I<The caller must free the strings and the array after use>.\n\n"
4539          | RStruct (_, typ) ->
4540              pr "This function returns a C<struct guestfs_%s *>,
4541 or NULL if there was an error.
4542 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4543          | RStructList (_, typ) ->
4544              pr "This function returns a C<struct guestfs_%s_list *>
4545 (see E<lt>guestfs-structs.hE<gt>),
4546 or NULL if there was an error.
4547 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4548          | RHashtable _ ->
4549              pr "This function returns a NULL-terminated array of
4550 strings, or NULL if there was an error.
4551 The array of strings will always have length C<2n+1>, where
4552 C<n> keys and values alternate, followed by the trailing NULL entry.
4553 I<The caller must free the strings and the array after use>.\n\n"
4554          | RBufferOut _ ->
4555              pr "This function returns a buffer, or NULL on error.
4556 The size of the returned buffer is written to C<*size_r>.
4557 I<The caller must free the returned buffer after use>.\n\n"
4558         );
4559         if List.mem ProtocolLimitWarning flags then
4560           pr "%s\n\n" protocol_limit_warning;
4561         if List.mem DangerWillRobinson flags then
4562           pr "%s\n\n" danger_will_robinson;
4563         match deprecation_notice flags with
4564         | None -> ()
4565         | Some txt -> pr "%s\n\n" txt
4566       )
4567   ) all_functions_sorted
4568
4569 and generate_structs_pod () =
4570   (* Structs documentation. *)
4571   List.iter (
4572     fun (typ, cols) ->
4573       pr "=head2 guestfs_%s\n" typ;
4574       pr "\n";
4575       pr " struct guestfs_%s {\n" typ;
4576       List.iter (
4577         function
4578         | name, FChar -> pr "   char %s;\n" name
4579         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4580         | name, FInt32 -> pr "   int32_t %s;\n" name
4581         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4582         | name, FInt64 -> pr "   int64_t %s;\n" name
4583         | name, FString -> pr "   char *%s;\n" name
4584         | name, FBuffer ->
4585             pr "   /* The next two fields describe a byte array. */\n";
4586             pr "   uint32_t %s_len;\n" name;
4587             pr "   char *%s;\n" name
4588         | name, FUUID ->
4589             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4590             pr "   char %s[32];\n" name
4591         | name, FOptPercent ->
4592             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4593             pr "   float %s;\n" name
4594       ) cols;
4595       pr " };\n";
4596       pr " \n";
4597       pr " struct guestfs_%s_list {\n" typ;
4598       pr "   uint32_t len; /* Number of elements in list. */\n";
4599       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4600       pr " };\n";
4601       pr " \n";
4602       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4603       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4604         typ typ;
4605       pr "\n"
4606   ) structs
4607
4608 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4609  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4610  *
4611  * We have to use an underscore instead of a dash because otherwise
4612  * rpcgen generates incorrect code.
4613  *
4614  * This header is NOT exported to clients, but see also generate_structs_h.
4615  *)
4616 and generate_xdr () =
4617   generate_header CStyle LGPLv2;
4618
4619   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4620   pr "typedef string str<>;\n";
4621   pr "\n";
4622
4623   (* Internal structures. *)
4624   List.iter (
4625     function
4626     | typ, cols ->
4627         pr "struct guestfs_int_%s {\n" typ;
4628         List.iter (function
4629                    | name, FChar -> pr "  char %s;\n" name
4630                    | name, FString -> pr "  string %s<>;\n" name
4631                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4632                    | name, FUUID -> pr "  opaque %s[32];\n" name
4633                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4634                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4635                    | name, FOptPercent -> pr "  float %s;\n" name
4636                   ) cols;
4637         pr "};\n";
4638         pr "\n";
4639         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4640         pr "\n";
4641   ) structs;
4642
4643   List.iter (
4644     fun (shortname, style, _, _, _, _, _) ->
4645       let name = "guestfs_" ^ shortname in
4646
4647       (match snd style with
4648        | [] -> ()
4649        | args ->
4650            pr "struct %s_args {\n" name;
4651            List.iter (
4652              function
4653              | Pathname n | Device n | Dev_or_Path n | String n ->
4654                  pr "  string %s<>;\n" n
4655              | OptString n -> pr "  str *%s;\n" n
4656              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4657              | Bool n -> pr "  bool %s;\n" n
4658              | Int n -> pr "  int %s;\n" n
4659              | Int64 n -> pr "  hyper %s;\n" n
4660              | FileIn _ | FileOut _ -> ()
4661            ) args;
4662            pr "};\n\n"
4663       );
4664       (match fst style with
4665        | RErr -> ()
4666        | RInt n ->
4667            pr "struct %s_ret {\n" name;
4668            pr "  int %s;\n" n;
4669            pr "};\n\n"
4670        | RInt64 n ->
4671            pr "struct %s_ret {\n" name;
4672            pr "  hyper %s;\n" n;
4673            pr "};\n\n"
4674        | RBool n ->
4675            pr "struct %s_ret {\n" name;
4676            pr "  bool %s;\n" n;
4677            pr "};\n\n"
4678        | RConstString _ | RConstOptString _ ->
4679            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4680        | RString n ->
4681            pr "struct %s_ret {\n" name;
4682            pr "  string %s<>;\n" n;
4683            pr "};\n\n"
4684        | RStringList n ->
4685            pr "struct %s_ret {\n" name;
4686            pr "  str %s<>;\n" n;
4687            pr "};\n\n"
4688        | RStruct (n, typ) ->
4689            pr "struct %s_ret {\n" name;
4690            pr "  guestfs_int_%s %s;\n" typ n;
4691            pr "};\n\n"
4692        | RStructList (n, typ) ->
4693            pr "struct %s_ret {\n" name;
4694            pr "  guestfs_int_%s_list %s;\n" typ n;
4695            pr "};\n\n"
4696        | RHashtable n ->
4697            pr "struct %s_ret {\n" name;
4698            pr "  str %s<>;\n" n;
4699            pr "};\n\n"
4700        | RBufferOut n ->
4701            pr "struct %s_ret {\n" name;
4702            pr "  opaque %s<>;\n" n;
4703            pr "};\n\n"
4704       );
4705   ) daemon_functions;
4706
4707   (* Table of procedure numbers. *)
4708   pr "enum guestfs_procedure {\n";
4709   List.iter (
4710     fun (shortname, _, proc_nr, _, _, _, _) ->
4711       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4712   ) daemon_functions;
4713   pr "  GUESTFS_PROC_NR_PROCS\n";
4714   pr "};\n";
4715   pr "\n";
4716
4717   (* Having to choose a maximum message size is annoying for several
4718    * reasons (it limits what we can do in the API), but it (a) makes
4719    * the protocol a lot simpler, and (b) provides a bound on the size
4720    * of the daemon which operates in limited memory space.  For large
4721    * file transfers you should use FTP.
4722    *)
4723   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4724   pr "\n";
4725
4726   (* Message header, etc. *)
4727   pr "\
4728 /* The communication protocol is now documented in the guestfs(3)
4729  * manpage.
4730  */
4731
4732 const GUESTFS_PROGRAM = 0x2000F5F5;
4733 const GUESTFS_PROTOCOL_VERSION = 1;
4734
4735 /* These constants must be larger than any possible message length. */
4736 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4737 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4738
4739 enum guestfs_message_direction {
4740   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4741   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4742 };
4743
4744 enum guestfs_message_status {
4745   GUESTFS_STATUS_OK = 0,
4746   GUESTFS_STATUS_ERROR = 1
4747 };
4748
4749 const GUESTFS_ERROR_LEN = 256;
4750
4751 struct guestfs_message_error {
4752   string error_message<GUESTFS_ERROR_LEN>;
4753 };
4754
4755 struct guestfs_message_header {
4756   unsigned prog;                     /* GUESTFS_PROGRAM */
4757   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4758   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4759   guestfs_message_direction direction;
4760   unsigned serial;                   /* message serial number */
4761   guestfs_message_status status;
4762 };
4763
4764 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4765
4766 struct guestfs_chunk {
4767   int cancel;                        /* if non-zero, transfer is cancelled */
4768   /* data size is 0 bytes if the transfer has finished successfully */
4769   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4770 };
4771 "
4772
4773 (* Generate the guestfs-structs.h file. *)
4774 and generate_structs_h () =
4775   generate_header CStyle LGPLv2;
4776
4777   (* This is a public exported header file containing various
4778    * structures.  The structures are carefully written to have
4779    * exactly the same in-memory format as the XDR structures that
4780    * we use on the wire to the daemon.  The reason for creating
4781    * copies of these structures here is just so we don't have to
4782    * export the whole of guestfs_protocol.h (which includes much
4783    * unrelated and XDR-dependent stuff that we don't want to be
4784    * public, or required by clients).
4785    *
4786    * To reiterate, we will pass these structures to and from the
4787    * client with a simple assignment or memcpy, so the format
4788    * must be identical to what rpcgen / the RFC defines.
4789    *)
4790
4791   (* Public structures. *)
4792   List.iter (
4793     fun (typ, cols) ->
4794       pr "struct guestfs_%s {\n" typ;
4795       List.iter (
4796         function
4797         | name, FChar -> pr "  char %s;\n" name
4798         | name, FString -> pr "  char *%s;\n" name
4799         | name, FBuffer ->
4800             pr "  uint32_t %s_len;\n" name;
4801             pr "  char *%s;\n" name
4802         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4803         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4804         | name, FInt32 -> pr "  int32_t %s;\n" name
4805         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4806         | name, FInt64 -> pr "  int64_t %s;\n" name
4807         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4808       ) cols;
4809       pr "};\n";
4810       pr "\n";
4811       pr "struct guestfs_%s_list {\n" typ;
4812       pr "  uint32_t len;\n";
4813       pr "  struct guestfs_%s *val;\n" typ;
4814       pr "};\n";
4815       pr "\n";
4816       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4817       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4818       pr "\n"
4819   ) structs
4820
4821 (* Generate the guestfs-actions.h file. *)
4822 and generate_actions_h () =
4823   generate_header CStyle LGPLv2;
4824   List.iter (
4825     fun (shortname, style, _, _, _, _, _) ->
4826       let name = "guestfs_" ^ shortname in
4827       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4828         name style
4829   ) all_functions
4830
4831 (* Generate the guestfs-internal-actions.h file. *)
4832 and generate_internal_actions_h () =
4833   generate_header CStyle LGPLv2;
4834   List.iter (
4835     fun (shortname, style, _, _, _, _, _) ->
4836       let name = "guestfs__" ^ shortname in
4837       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4838         name style
4839   ) non_daemon_functions
4840
4841 (* Generate the client-side dispatch stubs. *)
4842 and generate_client_actions () =
4843   generate_header CStyle LGPLv2;
4844
4845   pr "\
4846 #include <stdio.h>
4847 #include <stdlib.h>
4848 #include <stdint.h>
4849 #include <inttypes.h>
4850
4851 #include \"guestfs.h\"
4852 #include \"guestfs-internal-actions.h\"
4853 #include \"guestfs_protocol.h\"
4854
4855 #define error guestfs_error
4856 //#define perrorf guestfs_perrorf
4857 //#define safe_malloc guestfs_safe_malloc
4858 #define safe_realloc guestfs_safe_realloc
4859 //#define safe_strdup guestfs_safe_strdup
4860 #define safe_memdup guestfs_safe_memdup
4861
4862 /* Check the return message from a call for validity. */
4863 static int
4864 check_reply_header (guestfs_h *g,
4865                     const struct guestfs_message_header *hdr,
4866                     unsigned int proc_nr, unsigned int serial)
4867 {
4868   if (hdr->prog != GUESTFS_PROGRAM) {
4869     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4870     return -1;
4871   }
4872   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4873     error (g, \"wrong protocol version (%%d/%%d)\",
4874            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4875     return -1;
4876   }
4877   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4878     error (g, \"unexpected message direction (%%d/%%d)\",
4879            hdr->direction, GUESTFS_DIRECTION_REPLY);
4880     return -1;
4881   }
4882   if (hdr->proc != proc_nr) {
4883     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4884     return -1;
4885   }
4886   if (hdr->serial != serial) {
4887     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4888     return -1;
4889   }
4890
4891   return 0;
4892 }
4893
4894 /* Check we are in the right state to run a high-level action. */
4895 static int
4896 check_state (guestfs_h *g, const char *caller)
4897 {
4898   if (!guestfs__is_ready (g)) {
4899     if (guestfs__is_config (g) || guestfs__is_launching (g))
4900       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4901         caller);
4902     else
4903       error (g, \"%%s called from the wrong state, %%d != READY\",
4904         caller, guestfs__get_state (g));
4905     return -1;
4906   }
4907   return 0;
4908 }
4909
4910 ";
4911
4912   (* Generate code to generate guestfish call traces. *)
4913   let trace_call shortname style =
4914     pr "  if (guestfs__get_trace (g)) {\n";
4915
4916     let needs_i =
4917       List.exists (function
4918                    | StringList _ | DeviceList _ -> true
4919                    | _ -> false) (snd style) in
4920     if needs_i then (
4921       pr "    int i;\n";
4922       pr "\n"
4923     );
4924
4925     pr "    printf (\"%s\");\n" shortname;
4926     List.iter (
4927       function
4928       | String n                        (* strings *)
4929       | Device n
4930       | Pathname n
4931       | Dev_or_Path n
4932       | FileIn n
4933       | FileOut n ->
4934           (* guestfish doesn't support string escaping, so neither do we *)
4935           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4936       | OptString n ->                  (* string option *)
4937           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4938           pr "    else printf (\" null\");\n"
4939       | StringList n
4940       | DeviceList n ->                 (* string list *)
4941           pr "    putchar (' ');\n";
4942           pr "    putchar ('\"');\n";
4943           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4944           pr "      if (i > 0) putchar (' ');\n";
4945           pr "      fputs (%s[i], stdout);\n" n;
4946           pr "    }\n";
4947           pr "    putchar ('\"');\n";
4948       | Bool n ->                       (* boolean *)
4949           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4950       | Int n ->                        (* int *)
4951           pr "    printf (\" %%d\", %s);\n" n
4952       | Int64 n ->
4953           pr "    printf (\" %%\" PRIi64, %s);\n" n
4954     ) (snd style);
4955     pr "    putchar ('\\n');\n";
4956     pr "  }\n";
4957     pr "\n";
4958   in
4959
4960   (* For non-daemon functions, generate a wrapper around each function. *)
4961   List.iter (
4962     fun (shortname, style, _, _, _, _, _) ->
4963       let name = "guestfs_" ^ shortname in
4964
4965       generate_prototype ~extern:false ~semicolon:false ~newline:true
4966         ~handle:"g" name style;
4967       pr "{\n";
4968       trace_call shortname style;
4969       pr "  return guestfs__%s " shortname;
4970       generate_c_call_args ~handle:"g" style;
4971       pr ";\n";
4972       pr "}\n";
4973       pr "\n"
4974   ) non_daemon_functions;
4975
4976   (* Client-side stubs for each function. *)
4977   List.iter (
4978     fun (shortname, style, _, _, _, _, _) ->
4979       let name = "guestfs_" ^ shortname in
4980
4981       (* Generate the action stub. *)
4982       generate_prototype ~extern:false ~semicolon:false ~newline:true
4983         ~handle:"g" name style;
4984
4985       let error_code =
4986         match fst style with
4987         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4988         | RConstString _ | RConstOptString _ ->
4989             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4990         | RString _ | RStringList _
4991         | RStruct _ | RStructList _
4992         | RHashtable _ | RBufferOut _ ->
4993             "NULL" in
4994
4995       pr "{\n";
4996
4997       (match snd style with
4998        | [] -> ()
4999        | _ -> pr "  struct %s_args args;\n" name
5000       );
5001
5002       pr "  guestfs_message_header hdr;\n";
5003       pr "  guestfs_message_error err;\n";
5004       let has_ret =
5005         match fst style with
5006         | RErr -> false
5007         | RConstString _ | RConstOptString _ ->
5008             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5009         | RInt _ | RInt64 _
5010         | RBool _ | RString _ | RStringList _
5011         | RStruct _ | RStructList _
5012         | RHashtable _ | RBufferOut _ ->
5013             pr "  struct %s_ret ret;\n" name;
5014             true in
5015
5016       pr "  int serial;\n";
5017       pr "  int r;\n";
5018       pr "\n";
5019       trace_call shortname style;
5020       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5021       pr "  guestfs___set_busy (g);\n";
5022       pr "\n";
5023
5024       (* Send the main header and arguments. *)
5025       (match snd style with
5026        | [] ->
5027            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5028              (String.uppercase shortname)
5029        | args ->
5030            List.iter (
5031              function
5032              | Pathname n | Device n | Dev_or_Path n | String n ->
5033                  pr "  args.%s = (char *) %s;\n" n n
5034              | OptString n ->
5035                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5036              | StringList n | DeviceList n ->
5037                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5038                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5039              | Bool n ->
5040                  pr "  args.%s = %s;\n" n n
5041              | Int n ->
5042                  pr "  args.%s = %s;\n" n n
5043              | Int64 n ->
5044                  pr "  args.%s = %s;\n" n n
5045              | FileIn _ | FileOut _ -> ()
5046            ) args;
5047            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5048              (String.uppercase shortname);
5049            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5050              name;
5051       );
5052       pr "  if (serial == -1) {\n";
5053       pr "    guestfs___end_busy (g);\n";
5054       pr "    return %s;\n" error_code;
5055       pr "  }\n";
5056       pr "\n";
5057
5058       (* Send any additional files (FileIn) requested. *)
5059       let need_read_reply_label = ref false in
5060       List.iter (
5061         function
5062         | FileIn n ->
5063             pr "  r = guestfs___send_file (g, %s);\n" n;
5064             pr "  if (r == -1) {\n";
5065             pr "    guestfs___end_busy (g);\n";
5066             pr "    return %s;\n" error_code;
5067             pr "  }\n";
5068             pr "  if (r == -2) /* daemon cancelled */\n";
5069             pr "    goto read_reply;\n";
5070             need_read_reply_label := true;
5071             pr "\n";
5072         | _ -> ()
5073       ) (snd style);
5074
5075       (* Wait for the reply from the remote end. *)
5076       if !need_read_reply_label then pr " read_reply:\n";
5077       pr "  memset (&hdr, 0, sizeof hdr);\n";
5078       pr "  memset (&err, 0, sizeof err);\n";
5079       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5080       pr "\n";
5081       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5082       if not has_ret then
5083         pr "NULL, NULL"
5084       else
5085         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5086       pr ");\n";
5087
5088       pr "  if (r == -1) {\n";
5089       pr "    guestfs___end_busy (g);\n";
5090       pr "    return %s;\n" error_code;
5091       pr "  }\n";
5092       pr "\n";
5093
5094       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5095         (String.uppercase shortname);
5096       pr "    guestfs___end_busy (g);\n";
5097       pr "    return %s;\n" error_code;
5098       pr "  }\n";
5099       pr "\n";
5100
5101       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5102       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5103       pr "    free (err.error_message);\n";
5104       pr "    guestfs___end_busy (g);\n";
5105       pr "    return %s;\n" error_code;
5106       pr "  }\n";
5107       pr "\n";
5108
5109       (* Expecting to receive further files (FileOut)? *)
5110       List.iter (
5111         function
5112         | FileOut n ->
5113             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5114             pr "    guestfs___end_busy (g);\n";
5115             pr "    return %s;\n" error_code;
5116             pr "  }\n";
5117             pr "\n";
5118         | _ -> ()
5119       ) (snd style);
5120
5121       pr "  guestfs___end_busy (g);\n";
5122
5123       (match fst style with
5124        | RErr -> pr "  return 0;\n"
5125        | RInt n | RInt64 n | RBool n ->
5126            pr "  return ret.%s;\n" n
5127        | RConstString _ | RConstOptString _ ->
5128            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5129        | RString n ->
5130            pr "  return ret.%s; /* caller will free */\n" n
5131        | RStringList n | RHashtable n ->
5132            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5133            pr "  ret.%s.%s_val =\n" n n;
5134            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5135            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5136              n n;
5137            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5138            pr "  return ret.%s.%s_val;\n" n n
5139        | RStruct (n, _) ->
5140            pr "  /* caller will free this */\n";
5141            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5142        | RStructList (n, _) ->
5143            pr "  /* caller will free this */\n";
5144            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5145        | RBufferOut n ->
5146            pr "  *size_r = ret.%s.%s_len;\n" n n;
5147            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
5148       );
5149
5150       pr "}\n\n"
5151   ) daemon_functions;
5152
5153   (* Functions to free structures. *)
5154   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5155   pr " * structure format is identical to the XDR format.  See note in\n";
5156   pr " * generator.ml.\n";
5157   pr " */\n";
5158   pr "\n";
5159
5160   List.iter (
5161     fun (typ, _) ->
5162       pr "void\n";
5163       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5164       pr "{\n";
5165       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5166       pr "  free (x);\n";
5167       pr "}\n";
5168       pr "\n";
5169
5170       pr "void\n";
5171       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5172       pr "{\n";
5173       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5174       pr "  free (x);\n";
5175       pr "}\n";
5176       pr "\n";
5177
5178   ) structs;
5179
5180 (* Generate daemon/actions.h. *)
5181 and generate_daemon_actions_h () =
5182   generate_header CStyle GPLv2;
5183
5184   pr "#include \"../src/guestfs_protocol.h\"\n";
5185   pr "\n";
5186
5187   List.iter (
5188     fun (name, style, _, _, _, _, _) ->
5189       generate_prototype
5190         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5191         name style;
5192   ) daemon_functions
5193
5194 (* Generate the server-side stubs. *)
5195 and generate_daemon_actions () =
5196   generate_header CStyle GPLv2;
5197
5198   pr "#include <config.h>\n";
5199   pr "\n";
5200   pr "#include <stdio.h>\n";
5201   pr "#include <stdlib.h>\n";
5202   pr "#include <string.h>\n";
5203   pr "#include <inttypes.h>\n";
5204   pr "#include <rpc/types.h>\n";
5205   pr "#include <rpc/xdr.h>\n";
5206   pr "\n";
5207   pr "#include \"daemon.h\"\n";
5208   pr "#include \"c-ctype.h\"\n";
5209   pr "#include \"../src/guestfs_protocol.h\"\n";
5210   pr "#include \"actions.h\"\n";
5211   pr "\n";
5212
5213   List.iter (
5214     fun (name, style, _, _, _, _, _) ->
5215       (* Generate server-side stubs. *)
5216       pr "static void %s_stub (XDR *xdr_in)\n" name;
5217       pr "{\n";
5218       let error_code =
5219         match fst style with
5220         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5221         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5222         | RBool _ -> pr "  int r;\n"; "-1"
5223         | RConstString _ | RConstOptString _ ->
5224             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5225         | RString _ -> pr "  char *r;\n"; "NULL"
5226         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5227         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5228         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5229         | RBufferOut _ ->
5230             pr "  size_t size;\n";
5231             pr "  char *r;\n";
5232             "NULL" in
5233
5234       (match snd style with
5235        | [] -> ()
5236        | args ->
5237            pr "  struct guestfs_%s_args args;\n" name;
5238            List.iter (
5239              function
5240              | Device n | Dev_or_Path n
5241              | Pathname n
5242              | String n -> ()
5243              | OptString n -> pr "  char *%s;\n" n
5244              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5245              | Bool n -> pr "  int %s;\n" n
5246              | Int n -> pr "  int %s;\n" n
5247              | Int64 n -> pr "  int64_t %s;\n" n
5248              | FileIn _ | FileOut _ -> ()
5249            ) args
5250       );
5251       pr "\n";
5252
5253       (match snd style with
5254        | [] -> ()
5255        | args ->
5256            pr "  memset (&args, 0, sizeof args);\n";
5257            pr "\n";
5258            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5259            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5260            pr "    return;\n";
5261            pr "  }\n";
5262            let pr_args n =
5263              pr "  char *%s = args.%s;\n" n n
5264            in
5265            let pr_list_handling_code n =
5266              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5267              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5268              pr "  if (%s == NULL) {\n" n;
5269              pr "    reply_with_perror (\"realloc\");\n";
5270              pr "    goto done;\n";
5271              pr "  }\n";
5272              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5273              pr "  args.%s.%s_val = %s;\n" n n n;
5274            in
5275            List.iter (
5276              function
5277              | Pathname n ->
5278                  pr_args n;
5279                  pr "  ABS_PATH (%s, goto done);\n" n;
5280              | Device n ->
5281                  pr_args n;
5282                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5283              | Dev_or_Path n ->
5284                  pr_args n;
5285                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5286              | String n -> pr_args n
5287              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5288              | StringList n ->
5289                  pr_list_handling_code n;
5290              | DeviceList n ->
5291                  pr_list_handling_code n;
5292                  pr "  /* Ensure that each is a device,\n";
5293                  pr "   * and perform device name translation. */\n";
5294                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5295                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5296                  pr "  }\n";
5297              | Bool n -> pr "  %s = args.%s;\n" n n
5298              | Int n -> pr "  %s = args.%s;\n" n n
5299              | Int64 n -> pr "  %s = args.%s;\n" n n
5300              | FileIn _ | FileOut _ -> ()
5301            ) args;
5302            pr "\n"
5303       );
5304
5305
5306       (* this is used at least for do_equal *)
5307       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5308         (* Emit NEED_ROOT just once, even when there are two or
5309            more Pathname args *)
5310         pr "  NEED_ROOT (goto done);\n";
5311       );
5312
5313       (* Don't want to call the impl with any FileIn or FileOut
5314        * parameters, since these go "outside" the RPC protocol.
5315        *)
5316       let args' =
5317         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5318           (snd style) in
5319       pr "  r = do_%s " name;
5320       generate_c_call_args (fst style, args');
5321       pr ";\n";
5322
5323       pr "  if (r == %s)\n" error_code;
5324       pr "    /* do_%s has already called reply_with_error */\n" name;
5325       pr "    goto done;\n";
5326       pr "\n";
5327
5328       (* If there are any FileOut parameters, then the impl must
5329        * send its own reply.
5330        *)
5331       let no_reply =
5332         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5333       if no_reply then
5334         pr "  /* do_%s has already sent a reply */\n" name
5335       else (
5336         match fst style with
5337         | RErr -> pr "  reply (NULL, NULL);\n"
5338         | RInt n | RInt64 n | RBool n ->
5339             pr "  struct guestfs_%s_ret ret;\n" name;
5340             pr "  ret.%s = r;\n" n;
5341             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5342               name
5343         | RConstString _ | RConstOptString _ ->
5344             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5345         | RString n ->
5346             pr "  struct guestfs_%s_ret ret;\n" name;
5347             pr "  ret.%s = r;\n" n;
5348             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5349               name;
5350             pr "  free (r);\n"
5351         | RStringList n | RHashtable n ->
5352             pr "  struct guestfs_%s_ret ret;\n" name;
5353             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5354             pr "  ret.%s.%s_val = r;\n" n n;
5355             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5356               name;
5357             pr "  free_strings (r);\n"
5358         | RStruct (n, _) ->
5359             pr "  struct guestfs_%s_ret ret;\n" name;
5360             pr "  ret.%s = *r;\n" n;
5361             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5362               name;
5363             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5364               name
5365         | RStructList (n, _) ->
5366             pr "  struct guestfs_%s_ret ret;\n" name;
5367             pr "  ret.%s = *r;\n" n;
5368             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5369               name;
5370             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5371               name
5372         | RBufferOut n ->
5373             pr "  struct guestfs_%s_ret ret;\n" name;
5374             pr "  ret.%s.%s_val = r;\n" n n;
5375             pr "  ret.%s.%s_len = size;\n" n n;
5376             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5377               name;
5378             pr "  free (r);\n"
5379       );
5380
5381       (* Free the args. *)
5382       (match snd style with
5383        | [] ->
5384            pr "done: ;\n";
5385        | _ ->
5386            pr "done:\n";
5387            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5388              name
5389       );
5390
5391       pr "}\n\n";
5392   ) daemon_functions;
5393
5394   (* Dispatch function. *)
5395   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5396   pr "{\n";
5397   pr "  switch (proc_nr) {\n";
5398
5399   List.iter (
5400     fun (name, style, _, _, _, _, _) ->
5401       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5402       pr "      %s_stub (xdr_in);\n" name;
5403       pr "      break;\n"
5404   ) daemon_functions;
5405
5406   pr "    default:\n";
5407   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";
5408   pr "  }\n";
5409   pr "}\n";
5410   pr "\n";
5411
5412   (* LVM columns and tokenization functions. *)
5413   (* XXX This generates crap code.  We should rethink how we
5414    * do this parsing.
5415    *)
5416   List.iter (
5417     function
5418     | typ, cols ->
5419         pr "static const char *lvm_%s_cols = \"%s\";\n"
5420           typ (String.concat "," (List.map fst cols));
5421         pr "\n";
5422
5423         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5424         pr "{\n";
5425         pr "  char *tok, *p, *next;\n";
5426         pr "  int i, j;\n";
5427         pr "\n";
5428         (*
5429           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5430           pr "\n";
5431         *)
5432         pr "  if (!str) {\n";
5433         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5434         pr "    return -1;\n";
5435         pr "  }\n";
5436         pr "  if (!*str || c_isspace (*str)) {\n";
5437         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5438         pr "    return -1;\n";
5439         pr "  }\n";
5440         pr "  tok = str;\n";
5441         List.iter (
5442           fun (name, coltype) ->
5443             pr "  if (!tok) {\n";
5444             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5445             pr "    return -1;\n";
5446             pr "  }\n";
5447             pr "  p = strchrnul (tok, ',');\n";
5448             pr "  if (*p) next = p+1; else next = NULL;\n";
5449             pr "  *p = '\\0';\n";
5450             (match coltype with
5451              | FString ->
5452                  pr "  r->%s = strdup (tok);\n" name;
5453                  pr "  if (r->%s == NULL) {\n" name;
5454                  pr "    perror (\"strdup\");\n";
5455                  pr "    return -1;\n";
5456                  pr "  }\n"
5457              | FUUID ->
5458                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5459                  pr "    if (tok[j] == '\\0') {\n";
5460                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5461                  pr "      return -1;\n";
5462                  pr "    } else if (tok[j] != '-')\n";
5463                  pr "      r->%s[i++] = tok[j];\n" name;
5464                  pr "  }\n";
5465              | FBytes ->
5466                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5467                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5468                  pr "    return -1;\n";
5469                  pr "  }\n";
5470              | FInt64 ->
5471                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5472                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5473                  pr "    return -1;\n";
5474                  pr "  }\n";
5475              | FOptPercent ->
5476                  pr "  if (tok[0] == '\\0')\n";
5477                  pr "    r->%s = -1;\n" name;
5478                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5479                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5480                  pr "    return -1;\n";
5481                  pr "  }\n";
5482              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5483                  assert false (* can never be an LVM column *)
5484             );
5485             pr "  tok = next;\n";
5486         ) cols;
5487
5488         pr "  if (tok != NULL) {\n";
5489         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5490         pr "    return -1;\n";
5491         pr "  }\n";
5492         pr "  return 0;\n";
5493         pr "}\n";
5494         pr "\n";
5495
5496         pr "guestfs_int_lvm_%s_list *\n" typ;
5497         pr "parse_command_line_%ss (void)\n" typ;
5498         pr "{\n";
5499         pr "  char *out, *err;\n";
5500         pr "  char *p, *pend;\n";
5501         pr "  int r, i;\n";
5502         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5503         pr "  void *newp;\n";
5504         pr "\n";
5505         pr "  ret = malloc (sizeof *ret);\n";
5506         pr "  if (!ret) {\n";
5507         pr "    reply_with_perror (\"malloc\");\n";
5508         pr "    return NULL;\n";
5509         pr "  }\n";
5510         pr "\n";
5511         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5512         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5513         pr "\n";
5514         pr "  r = command (&out, &err,\n";
5515         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5516         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5517         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5518         pr "  if (r == -1) {\n";
5519         pr "    reply_with_error (\"%%s\", err);\n";
5520         pr "    free (out);\n";
5521         pr "    free (err);\n";
5522         pr "    free (ret);\n";
5523         pr "    return NULL;\n";
5524         pr "  }\n";
5525         pr "\n";
5526         pr "  free (err);\n";
5527         pr "\n";
5528         pr "  /* Tokenize each line of the output. */\n";
5529         pr "  p = out;\n";
5530         pr "  i = 0;\n";
5531         pr "  while (p) {\n";
5532         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5533         pr "    if (pend) {\n";
5534         pr "      *pend = '\\0';\n";
5535         pr "      pend++;\n";
5536         pr "    }\n";
5537         pr "\n";
5538         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5539         pr "      p++;\n";
5540         pr "\n";
5541         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5542         pr "      p = pend;\n";
5543         pr "      continue;\n";
5544         pr "    }\n";
5545         pr "\n";
5546         pr "    /* Allocate some space to store this next entry. */\n";
5547         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5548         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5549         pr "    if (newp == NULL) {\n";
5550         pr "      reply_with_perror (\"realloc\");\n";
5551         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5552         pr "      free (ret);\n";
5553         pr "      free (out);\n";
5554         pr "      return NULL;\n";
5555         pr "    }\n";
5556         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5557         pr "\n";
5558         pr "    /* Tokenize the next entry. */\n";
5559         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5560         pr "    if (r == -1) {\n";
5561         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5562         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5563         pr "      free (ret);\n";
5564         pr "      free (out);\n";
5565         pr "      return NULL;\n";
5566         pr "    }\n";
5567         pr "\n";
5568         pr "    ++i;\n";
5569         pr "    p = pend;\n";
5570         pr "  }\n";
5571         pr "\n";
5572         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5573         pr "\n";
5574         pr "  free (out);\n";
5575         pr "  return ret;\n";
5576         pr "}\n"
5577
5578   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5579
5580 (* Generate a list of function names, for debugging in the daemon.. *)
5581 and generate_daemon_names () =
5582   generate_header CStyle GPLv2;
5583
5584   pr "#include <config.h>\n";
5585   pr "\n";
5586   pr "#include \"daemon.h\"\n";
5587   pr "\n";
5588
5589   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5590   pr "const char *function_names[] = {\n";
5591   List.iter (
5592     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5593   ) daemon_functions;
5594   pr "};\n";
5595
5596 (* Generate the tests. *)
5597 and generate_tests () =
5598   generate_header CStyle GPLv2;
5599
5600   pr "\
5601 #include <stdio.h>
5602 #include <stdlib.h>
5603 #include <string.h>
5604 #include <unistd.h>
5605 #include <sys/types.h>
5606 #include <fcntl.h>
5607
5608 #include \"guestfs.h\"
5609
5610 static guestfs_h *g;
5611 static int suppress_error = 0;
5612
5613 static void print_error (guestfs_h *g, void *data, const char *msg)
5614 {
5615   if (!suppress_error)
5616     fprintf (stderr, \"%%s\\n\", msg);
5617 }
5618
5619 /* FIXME: nearly identical code appears in fish.c */
5620 static void print_strings (char *const *argv)
5621 {
5622   int argc;
5623
5624   for (argc = 0; argv[argc] != NULL; ++argc)
5625     printf (\"\\t%%s\\n\", argv[argc]);
5626 }
5627
5628 /*
5629 static void print_table (char const *const *argv)
5630 {
5631   int i;
5632
5633   for (i = 0; argv[i] != NULL; i += 2)
5634     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5635 }
5636 */
5637
5638 ";
5639
5640   (* Generate a list of commands which are not tested anywhere. *)
5641   pr "static void no_test_warnings (void)\n";
5642   pr "{\n";
5643
5644   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5645   List.iter (
5646     fun (_, _, _, _, tests, _, _) ->
5647       let tests = filter_map (
5648         function
5649         | (_, (Always|If _|Unless _), test) -> Some test
5650         | (_, Disabled, _) -> None
5651       ) tests in
5652       let seq = List.concat (List.map seq_of_test tests) in
5653       let cmds_tested = List.map List.hd seq in
5654       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5655   ) all_functions;
5656
5657   List.iter (
5658     fun (name, _, _, _, _, _, _) ->
5659       if not (Hashtbl.mem hash name) then
5660         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5661   ) all_functions;
5662
5663   pr "}\n";
5664   pr "\n";
5665
5666   (* Generate the actual tests.  Note that we generate the tests
5667    * in reverse order, deliberately, so that (in general) the
5668    * newest tests run first.  This makes it quicker and easier to
5669    * debug them.
5670    *)
5671   let test_names =
5672     List.map (
5673       fun (name, _, _, _, tests, _, _) ->
5674         mapi (generate_one_test name) tests
5675     ) (List.rev all_functions) in
5676   let test_names = List.concat test_names in
5677   let nr_tests = List.length test_names in
5678
5679   pr "\
5680 int main (int argc, char *argv[])
5681 {
5682   char c = 0;
5683   unsigned long int n_failed = 0;
5684   const char *filename;
5685   int fd;
5686   int nr_tests, test_num = 0;
5687
5688   setbuf (stdout, NULL);
5689
5690   no_test_warnings ();
5691
5692   g = guestfs_create ();
5693   if (g == NULL) {
5694     printf (\"guestfs_create FAILED\\n\");
5695     exit (1);
5696   }
5697
5698   guestfs_set_error_handler (g, print_error, NULL);
5699
5700   guestfs_set_path (g, \"../appliance\");
5701
5702   filename = \"test1.img\";
5703   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5704   if (fd == -1) {
5705     perror (filename);
5706     exit (1);
5707   }
5708   if (lseek (fd, %d, SEEK_SET) == -1) {
5709     perror (\"lseek\");
5710     close (fd);
5711     unlink (filename);
5712     exit (1);
5713   }
5714   if (write (fd, &c, 1) == -1) {
5715     perror (\"write\");
5716     close (fd);
5717     unlink (filename);
5718     exit (1);
5719   }
5720   if (close (fd) == -1) {
5721     perror (filename);
5722     unlink (filename);
5723     exit (1);
5724   }
5725   if (guestfs_add_drive (g, filename) == -1) {
5726     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5727     exit (1);
5728   }
5729
5730   filename = \"test2.img\";
5731   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5732   if (fd == -1) {
5733     perror (filename);
5734     exit (1);
5735   }
5736   if (lseek (fd, %d, SEEK_SET) == -1) {
5737     perror (\"lseek\");
5738     close (fd);
5739     unlink (filename);
5740     exit (1);
5741   }
5742   if (write (fd, &c, 1) == -1) {
5743     perror (\"write\");
5744     close (fd);
5745     unlink (filename);
5746     exit (1);
5747   }
5748   if (close (fd) == -1) {
5749     perror (filename);
5750     unlink (filename);
5751     exit (1);
5752   }
5753   if (guestfs_add_drive (g, filename) == -1) {
5754     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5755     exit (1);
5756   }
5757
5758   filename = \"test3.img\";
5759   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5760   if (fd == -1) {
5761     perror (filename);
5762     exit (1);
5763   }
5764   if (lseek (fd, %d, SEEK_SET) == -1) {
5765     perror (\"lseek\");
5766     close (fd);
5767     unlink (filename);
5768     exit (1);
5769   }
5770   if (write (fd, &c, 1) == -1) {
5771     perror (\"write\");
5772     close (fd);
5773     unlink (filename);
5774     exit (1);
5775   }
5776   if (close (fd) == -1) {
5777     perror (filename);
5778     unlink (filename);
5779     exit (1);
5780   }
5781   if (guestfs_add_drive (g, filename) == -1) {
5782     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5783     exit (1);
5784   }
5785
5786   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5787     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5788     exit (1);
5789   }
5790
5791   if (guestfs_launch (g) == -1) {
5792     printf (\"guestfs_launch FAILED\\n\");
5793     exit (1);
5794   }
5795
5796   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5797   alarm (600);
5798
5799   /* Cancel previous alarm. */
5800   alarm (0);
5801
5802   nr_tests = %d;
5803
5804 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5805
5806   iteri (
5807     fun i test_name ->
5808       pr "  test_num++;\n";
5809       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5810       pr "  if (%s () == -1) {\n" test_name;
5811       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5812       pr "    n_failed++;\n";
5813       pr "  }\n";
5814   ) test_names;
5815   pr "\n";
5816
5817   pr "  guestfs_close (g);\n";
5818   pr "  unlink (\"test1.img\");\n";
5819   pr "  unlink (\"test2.img\");\n";
5820   pr "  unlink (\"test3.img\");\n";
5821   pr "\n";
5822
5823   pr "  if (n_failed > 0) {\n";
5824   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5825   pr "    exit (1);\n";
5826   pr "  }\n";
5827   pr "\n";
5828
5829   pr "  exit (0);\n";
5830   pr "}\n"
5831
5832 and generate_one_test name i (init, prereq, test) =
5833   let test_name = sprintf "test_%s_%d" name i in
5834
5835   pr "\
5836 static int %s_skip (void)
5837 {
5838   const char *str;
5839
5840   str = getenv (\"TEST_ONLY\");
5841   if (str)
5842     return strstr (str, \"%s\") == NULL;
5843   str = getenv (\"SKIP_%s\");
5844   if (str && strcmp (str, \"1\") == 0) return 1;
5845   str = getenv (\"SKIP_TEST_%s\");
5846   if (str && strcmp (str, \"1\") == 0) return 1;
5847   return 0;
5848 }
5849
5850 " test_name name (String.uppercase test_name) (String.uppercase name);
5851
5852   (match prereq with
5853    | Disabled | Always -> ()
5854    | If code | Unless code ->
5855        pr "static int %s_prereq (void)\n" test_name;
5856        pr "{\n";
5857        pr "  %s\n" code;
5858        pr "}\n";
5859        pr "\n";
5860   );
5861
5862   pr "\
5863 static int %s (void)
5864 {
5865   if (%s_skip ()) {
5866     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5867     return 0;
5868   }
5869
5870 " test_name test_name test_name;
5871
5872   (match prereq with
5873    | Disabled ->
5874        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5875    | If _ ->
5876        pr "  if (! %s_prereq ()) {\n" test_name;
5877        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5878        pr "    return 0;\n";
5879        pr "  }\n";
5880        pr "\n";
5881        generate_one_test_body name i test_name init test;
5882    | Unless _ ->
5883        pr "  if (%s_prereq ()) {\n" test_name;
5884        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5885        pr "    return 0;\n";
5886        pr "  }\n";
5887        pr "\n";
5888        generate_one_test_body name i test_name init test;
5889    | Always ->
5890        generate_one_test_body name i test_name init test
5891   );
5892
5893   pr "  return 0;\n";
5894   pr "}\n";
5895   pr "\n";
5896   test_name
5897
5898 and generate_one_test_body name i test_name init test =
5899   (match init with
5900    | InitNone (* XXX at some point, InitNone and InitEmpty became
5901                * folded together as the same thing.  Really we should
5902                * make InitNone do nothing at all, but the tests may
5903                * need to be checked to make sure this is OK.
5904                *)
5905    | InitEmpty ->
5906        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5907        List.iter (generate_test_command_call test_name)
5908          [["blockdev_setrw"; "/dev/sda"];
5909           ["umount_all"];
5910           ["lvm_remove_all"]]
5911    | InitPartition ->
5912        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5913        List.iter (generate_test_command_call test_name)
5914          [["blockdev_setrw"; "/dev/sda"];
5915           ["umount_all"];
5916           ["lvm_remove_all"];
5917           ["sfdiskM"; "/dev/sda"; ","]]
5918    | InitBasicFS ->
5919        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5920        List.iter (generate_test_command_call test_name)
5921          [["blockdev_setrw"; "/dev/sda"];
5922           ["umount_all"];
5923           ["lvm_remove_all"];
5924           ["sfdiskM"; "/dev/sda"; ","];
5925           ["mkfs"; "ext2"; "/dev/sda1"];
5926           ["mount"; "/dev/sda1"; "/"]]
5927    | InitBasicFSonLVM ->
5928        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5929          test_name;
5930        List.iter (generate_test_command_call test_name)
5931          [["blockdev_setrw"; "/dev/sda"];
5932           ["umount_all"];
5933           ["lvm_remove_all"];
5934           ["sfdiskM"; "/dev/sda"; ","];
5935           ["pvcreate"; "/dev/sda1"];
5936           ["vgcreate"; "VG"; "/dev/sda1"];
5937           ["lvcreate"; "LV"; "VG"; "8"];
5938           ["mkfs"; "ext2"; "/dev/VG/LV"];
5939           ["mount"; "/dev/VG/LV"; "/"]]
5940    | InitISOFS ->
5941        pr "  /* InitISOFS for %s */\n" test_name;
5942        List.iter (generate_test_command_call test_name)
5943          [["blockdev_setrw"; "/dev/sda"];
5944           ["umount_all"];
5945           ["lvm_remove_all"];
5946           ["mount_ro"; "/dev/sdd"; "/"]]
5947   );
5948
5949   let get_seq_last = function
5950     | [] ->
5951         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5952           test_name
5953     | seq ->
5954         let seq = List.rev seq in
5955         List.rev (List.tl seq), List.hd seq
5956   in
5957
5958   match test with
5959   | TestRun seq ->
5960       pr "  /* TestRun for %s (%d) */\n" name i;
5961       List.iter (generate_test_command_call test_name) seq
5962   | TestOutput (seq, expected) ->
5963       pr "  /* TestOutput for %s (%d) */\n" name i;
5964       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5965       let seq, last = get_seq_last seq in
5966       let test () =
5967         pr "    if (strcmp (r, expected) != 0) {\n";
5968         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5969         pr "      return -1;\n";
5970         pr "    }\n"
5971       in
5972       List.iter (generate_test_command_call test_name) seq;
5973       generate_test_command_call ~test test_name last
5974   | TestOutputList (seq, expected) ->
5975       pr "  /* TestOutputList for %s (%d) */\n" name i;
5976       let seq, last = get_seq_last seq in
5977       let test () =
5978         iteri (
5979           fun i str ->
5980             pr "    if (!r[%d]) {\n" i;
5981             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5982             pr "      print_strings (r);\n";
5983             pr "      return -1;\n";
5984             pr "    }\n";
5985             pr "    {\n";
5986             pr "      const char *expected = \"%s\";\n" (c_quote str);
5987             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5988             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5989             pr "        return -1;\n";
5990             pr "      }\n";
5991             pr "    }\n"
5992         ) expected;
5993         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5994         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5995           test_name;
5996         pr "      print_strings (r);\n";
5997         pr "      return -1;\n";
5998         pr "    }\n"
5999       in
6000       List.iter (generate_test_command_call test_name) seq;
6001       generate_test_command_call ~test test_name last
6002   | TestOutputListOfDevices (seq, expected) ->
6003       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6004       let seq, last = get_seq_last seq in
6005       let test () =
6006         iteri (
6007           fun i str ->
6008             pr "    if (!r[%d]) {\n" i;
6009             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6010             pr "      print_strings (r);\n";
6011             pr "      return -1;\n";
6012             pr "    }\n";
6013             pr "    {\n";
6014             pr "      const char *expected = \"%s\";\n" (c_quote str);
6015             pr "      r[%d][5] = 's';\n" i;
6016             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
6017             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6018             pr "        return -1;\n";
6019             pr "      }\n";
6020             pr "    }\n"
6021         ) expected;
6022         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6023         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6024           test_name;
6025         pr "      print_strings (r);\n";
6026         pr "      return -1;\n";
6027         pr "    }\n"
6028       in
6029       List.iter (generate_test_command_call test_name) seq;
6030       generate_test_command_call ~test test_name last
6031   | TestOutputInt (seq, expected) ->
6032       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6033       let seq, last = get_seq_last seq in
6034       let test () =
6035         pr "    if (r != %d) {\n" expected;
6036         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6037           test_name expected;
6038         pr "               (int) r);\n";
6039         pr "      return -1;\n";
6040         pr "    }\n"
6041       in
6042       List.iter (generate_test_command_call test_name) seq;
6043       generate_test_command_call ~test test_name last
6044   | TestOutputIntOp (seq, op, expected) ->
6045       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6046       let seq, last = get_seq_last seq in
6047       let test () =
6048         pr "    if (! (r %s %d)) {\n" op expected;
6049         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6050           test_name op expected;
6051         pr "               (int) r);\n";
6052         pr "      return -1;\n";
6053         pr "    }\n"
6054       in
6055       List.iter (generate_test_command_call test_name) seq;
6056       generate_test_command_call ~test test_name last
6057   | TestOutputTrue seq ->
6058       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6059       let seq, last = get_seq_last seq in
6060       let test () =
6061         pr "    if (!r) {\n";
6062         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6063           test_name;
6064         pr "      return -1;\n";
6065         pr "    }\n"
6066       in
6067       List.iter (generate_test_command_call test_name) seq;
6068       generate_test_command_call ~test test_name last
6069   | TestOutputFalse seq ->
6070       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6071       let seq, last = get_seq_last seq in
6072       let test () =
6073         pr "    if (r) {\n";
6074         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6075           test_name;
6076         pr "      return -1;\n";
6077         pr "    }\n"
6078       in
6079       List.iter (generate_test_command_call test_name) seq;
6080       generate_test_command_call ~test test_name last
6081   | TestOutputLength (seq, expected) ->
6082       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6083       let seq, last = get_seq_last seq in
6084       let test () =
6085         pr "    int j;\n";
6086         pr "    for (j = 0; j < %d; ++j)\n" expected;
6087         pr "      if (r[j] == NULL) {\n";
6088         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6089           test_name;
6090         pr "        print_strings (r);\n";
6091         pr "        return -1;\n";
6092         pr "      }\n";
6093         pr "    if (r[j] != NULL) {\n";
6094         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6095           test_name;
6096         pr "      print_strings (r);\n";
6097         pr "      return -1;\n";
6098         pr "    }\n"
6099       in
6100       List.iter (generate_test_command_call test_name) seq;
6101       generate_test_command_call ~test test_name last
6102   | TestOutputBuffer (seq, expected) ->
6103       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6104       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6105       let seq, last = get_seq_last seq in
6106       let len = String.length expected in
6107       let test () =
6108         pr "    if (size != %d) {\n" len;
6109         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6110         pr "      return -1;\n";
6111         pr "    }\n";
6112         pr "    if (strncmp (r, expected, size) != 0) {\n";
6113         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6114         pr "      return -1;\n";
6115         pr "    }\n"
6116       in
6117       List.iter (generate_test_command_call test_name) seq;
6118       generate_test_command_call ~test test_name last
6119   | TestOutputStruct (seq, checks) ->
6120       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6121       let seq, last = get_seq_last seq in
6122       let test () =
6123         List.iter (
6124           function
6125           | CompareWithInt (field, expected) ->
6126               pr "    if (r->%s != %d) {\n" field expected;
6127               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6128                 test_name field expected;
6129               pr "               (int) r->%s);\n" field;
6130               pr "      return -1;\n";
6131               pr "    }\n"
6132           | CompareWithIntOp (field, op, expected) ->
6133               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6134               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6135                 test_name field op expected;
6136               pr "               (int) r->%s);\n" field;
6137               pr "      return -1;\n";
6138               pr "    }\n"
6139           | CompareWithString (field, expected) ->
6140               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
6141               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6142                 test_name field expected;
6143               pr "               r->%s);\n" field;
6144               pr "      return -1;\n";
6145               pr "    }\n"
6146           | CompareFieldsIntEq (field1, field2) ->
6147               pr "    if (r->%s != r->%s) {\n" field1 field2;
6148               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6149                 test_name field1 field2;
6150               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6151               pr "      return -1;\n";
6152               pr "    }\n"
6153           | CompareFieldsStrEq (field1, field2) ->
6154               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
6155               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6156                 test_name field1 field2;
6157               pr "               r->%s, r->%s);\n" field1 field2;
6158               pr "      return -1;\n";
6159               pr "    }\n"
6160         ) checks
6161       in
6162       List.iter (generate_test_command_call test_name) seq;
6163       generate_test_command_call ~test test_name last
6164   | TestLastFail seq ->
6165       pr "  /* TestLastFail for %s (%d) */\n" name i;
6166       let seq, last = get_seq_last seq in
6167       List.iter (generate_test_command_call test_name) seq;
6168       generate_test_command_call test_name ~expect_error:true last
6169
6170 (* Generate the code to run a command, leaving the result in 'r'.
6171  * If you expect to get an error then you should set expect_error:true.
6172  *)
6173 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6174   match cmd with
6175   | [] -> assert false
6176   | name :: args ->
6177       (* Look up the command to find out what args/ret it has. *)
6178       let style =
6179         try
6180           let _, style, _, _, _, _, _ =
6181             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6182           style
6183         with Not_found ->
6184           failwithf "%s: in test, command %s was not found" test_name name in
6185
6186       if List.length (snd style) <> List.length args then
6187         failwithf "%s: in test, wrong number of args given to %s"
6188           test_name name;
6189
6190       pr "  {\n";
6191
6192       List.iter (
6193         function
6194         | OptString n, "NULL" -> ()
6195         | Pathname n, arg
6196         | Device n, arg
6197         | Dev_or_Path n, arg
6198         | String n, arg
6199         | OptString n, arg ->
6200             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6201         | Int _, _
6202         | Int64 _, _
6203         | Bool _, _
6204         | FileIn _, _ | FileOut _, _ -> ()
6205         | StringList n, arg | DeviceList n, arg ->
6206             let strs = string_split " " arg in
6207             iteri (
6208               fun i str ->
6209                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6210             ) strs;
6211             pr "    const char *const %s[] = {\n" n;
6212             iteri (
6213               fun i _ -> pr "      %s_%d,\n" n i
6214             ) strs;
6215             pr "      NULL\n";
6216             pr "    };\n";
6217       ) (List.combine (snd style) args);
6218
6219       let error_code =
6220         match fst style with
6221         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6222         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6223         | RConstString _ | RConstOptString _ ->
6224             pr "    const char *r;\n"; "NULL"
6225         | RString _ -> pr "    char *r;\n"; "NULL"
6226         | RStringList _ | RHashtable _ ->
6227             pr "    char **r;\n";
6228             pr "    int i;\n";
6229             "NULL"
6230         | RStruct (_, typ) ->
6231             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6232         | RStructList (_, typ) ->
6233             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6234         | RBufferOut _ ->
6235             pr "    char *r;\n";
6236             pr "    size_t size;\n";
6237             "NULL" in
6238
6239       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6240       pr "    r = guestfs_%s (g" name;
6241
6242       (* Generate the parameters. *)
6243       List.iter (
6244         function
6245         | OptString _, "NULL" -> pr ", NULL"
6246         | Pathname n, _
6247         | Device n, _ | Dev_or_Path n, _
6248         | String n, _
6249         | OptString n, _ ->
6250             pr ", %s" n
6251         | FileIn _, arg | FileOut _, arg ->
6252             pr ", \"%s\"" (c_quote arg)
6253         | StringList n, _ | DeviceList n, _ ->
6254             pr ", (char **) %s" n
6255         | Int _, arg ->
6256             let i =
6257               try int_of_string arg
6258               with Failure "int_of_string" ->
6259                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6260             pr ", %d" i
6261         | Int64 _, arg ->
6262             let i =
6263               try Int64.of_string arg
6264               with Failure "int_of_string" ->
6265                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6266             pr ", %Ld" i
6267         | Bool _, arg ->
6268             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6269       ) (List.combine (snd style) args);
6270
6271       (match fst style with
6272        | RBufferOut _ -> pr ", &size"
6273        | _ -> ()
6274       );
6275
6276       pr ");\n";
6277
6278       if not expect_error then
6279         pr "    if (r == %s)\n" error_code
6280       else
6281         pr "    if (r != %s)\n" error_code;
6282       pr "      return -1;\n";
6283
6284       (* Insert the test code. *)
6285       (match test with
6286        | None -> ()
6287        | Some f -> f ()
6288       );
6289
6290       (match fst style with
6291        | RErr | RInt _ | RInt64 _ | RBool _
6292        | RConstString _ | RConstOptString _ -> ()
6293        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6294        | RStringList _ | RHashtable _ ->
6295            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6296            pr "      free (r[i]);\n";
6297            pr "    free (r);\n"
6298        | RStruct (_, typ) ->
6299            pr "    guestfs_free_%s (r);\n" typ
6300        | RStructList (_, typ) ->
6301            pr "    guestfs_free_%s_list (r);\n" typ
6302       );
6303
6304       pr "  }\n"
6305
6306 and c_quote str =
6307   let str = replace_str str "\r" "\\r" in
6308   let str = replace_str str "\n" "\\n" in
6309   let str = replace_str str "\t" "\\t" in
6310   let str = replace_str str "\000" "\\0" in
6311   str
6312
6313 (* Generate a lot of different functions for guestfish. *)
6314 and generate_fish_cmds () =
6315   generate_header CStyle GPLv2;
6316
6317   let all_functions =
6318     List.filter (
6319       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6320     ) all_functions in
6321   let all_functions_sorted =
6322     List.filter (
6323       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6324     ) all_functions_sorted in
6325
6326   pr "#include <stdio.h>\n";
6327   pr "#include <stdlib.h>\n";
6328   pr "#include <string.h>\n";
6329   pr "#include <inttypes.h>\n";
6330   pr "\n";
6331   pr "#include <guestfs.h>\n";
6332   pr "#include \"c-ctype.h\"\n";
6333   pr "#include \"fish.h\"\n";
6334   pr "\n";
6335
6336   (* list_commands function, which implements guestfish -h *)
6337   pr "void list_commands (void)\n";
6338   pr "{\n";
6339   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6340   pr "  list_builtin_commands ();\n";
6341   List.iter (
6342     fun (name, _, _, flags, _, shortdesc, _) ->
6343       let name = replace_char name '_' '-' in
6344       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6345         name shortdesc
6346   ) all_functions_sorted;
6347   pr "  printf (\"    %%s\\n\",";
6348   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6349   pr "}\n";
6350   pr "\n";
6351
6352   (* display_command function, which implements guestfish -h cmd *)
6353   pr "void display_command (const char *cmd)\n";
6354   pr "{\n";
6355   List.iter (
6356     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6357       let name2 = replace_char name '_' '-' in
6358       let alias =
6359         try find_map (function FishAlias n -> Some n | _ -> None) flags
6360         with Not_found -> name in
6361       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6362       let synopsis =
6363         match snd style with
6364         | [] -> name2
6365         | args ->
6366             sprintf "%s <%s>"
6367               name2 (String.concat "> <" (List.map name_of_argt args)) in
6368
6369       let warnings =
6370         if List.mem ProtocolLimitWarning flags then
6371           ("\n\n" ^ protocol_limit_warning)
6372         else "" in
6373
6374       (* For DangerWillRobinson commands, we should probably have
6375        * guestfish prompt before allowing you to use them (especially
6376        * in interactive mode). XXX
6377        *)
6378       let warnings =
6379         warnings ^
6380           if List.mem DangerWillRobinson flags then
6381             ("\n\n" ^ danger_will_robinson)
6382           else "" in
6383
6384       let warnings =
6385         warnings ^
6386           match deprecation_notice flags with
6387           | None -> ""
6388           | Some txt -> "\n\n" ^ txt in
6389
6390       let describe_alias =
6391         if name <> alias then
6392           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6393         else "" in
6394
6395       pr "  if (";
6396       pr "strcasecmp (cmd, \"%s\") == 0" name;
6397       if name <> name2 then
6398         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6399       if name <> alias then
6400         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6401       pr ")\n";
6402       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6403         name2 shortdesc
6404         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6405       pr "  else\n"
6406   ) all_functions;
6407   pr "    display_builtin_command (cmd);\n";
6408   pr "}\n";
6409   pr "\n";
6410
6411   let emit_print_list_function typ =
6412     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6413       typ typ typ;
6414     pr "{\n";
6415     pr "  unsigned int i;\n";
6416     pr "\n";
6417     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6418     pr "    printf (\"[%%d] = {\\n\", i);\n";
6419     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6420     pr "    printf (\"}\\n\");\n";
6421     pr "  }\n";
6422     pr "}\n";
6423     pr "\n";
6424   in
6425
6426   (* print_* functions *)
6427   List.iter (
6428     fun (typ, cols) ->
6429       let needs_i =
6430         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6431
6432       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6433       pr "{\n";
6434       if needs_i then (
6435         pr "  unsigned int i;\n";
6436         pr "\n"
6437       );
6438       List.iter (
6439         function
6440         | name, FString ->
6441             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6442         | name, FUUID ->
6443             pr "  printf (\"%%s%s: \", indent);\n" name;
6444             pr "  for (i = 0; i < 32; ++i)\n";
6445             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6446             pr "  printf (\"\\n\");\n"
6447         | name, FBuffer ->
6448             pr "  printf (\"%%s%s: \", indent);\n" name;
6449             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6450             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6451             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6452             pr "    else\n";
6453             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6454             pr "  printf (\"\\n\");\n"
6455         | name, (FUInt64|FBytes) ->
6456             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6457               name typ name
6458         | name, FInt64 ->
6459             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6460               name typ name
6461         | name, FUInt32 ->
6462             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6463               name typ name
6464         | name, FInt32 ->
6465             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6466               name typ name
6467         | name, FChar ->
6468             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6469               name typ name
6470         | name, FOptPercent ->
6471             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6472               typ name name typ name;
6473             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6474       ) cols;
6475       pr "}\n";
6476       pr "\n";
6477   ) structs;
6478
6479   (* Emit a print_TYPE_list function definition only if that function is used. *)
6480   List.iter (
6481     function
6482     | typ, (RStructListOnly | RStructAndList) ->
6483         (* generate the function for typ *)
6484         emit_print_list_function typ
6485     | typ, _ -> () (* empty *)
6486   ) (rstructs_used_by all_functions);
6487
6488   (* Emit a print_TYPE function definition only if that function is used. *)
6489   List.iter (
6490     function
6491     | typ, (RStructOnly | RStructAndList) ->
6492         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6493         pr "{\n";
6494         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6495         pr "}\n";
6496         pr "\n";
6497     | typ, _ -> () (* empty *)
6498   ) (rstructs_used_by all_functions);
6499
6500   (* run_<action> actions *)
6501   List.iter (
6502     fun (name, style, _, flags, _, _, _) ->
6503       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6504       pr "{\n";
6505       (match fst style with
6506        | RErr
6507        | RInt _
6508        | RBool _ -> pr "  int r;\n"
6509        | RInt64 _ -> pr "  int64_t r;\n"
6510        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6511        | RString _ -> pr "  char *r;\n"
6512        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6513        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6514        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6515        | RBufferOut _ ->
6516            pr "  char *r;\n";
6517            pr "  size_t size;\n";
6518       );
6519       List.iter (
6520         function
6521         | Device n
6522         | String n
6523         | OptString n
6524         | FileIn n
6525         | FileOut n -> pr "  const char *%s;\n" n
6526         | Pathname n
6527         | Dev_or_Path n -> pr "  char *%s;\n" n
6528         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6529         | Bool n -> pr "  int %s;\n" n
6530         | Int n -> pr "  int %s;\n" n
6531         | Int64 n -> pr "  int64_t %s;\n" n
6532       ) (snd style);
6533
6534       (* Check and convert parameters. *)
6535       let argc_expected = List.length (snd style) in
6536       pr "  if (argc != %d) {\n" argc_expected;
6537       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6538         argc_expected;
6539       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6540       pr "    return -1;\n";
6541       pr "  }\n";
6542       iteri (
6543         fun i ->
6544           function
6545           | Device name
6546           | String name ->
6547               pr "  %s = argv[%d];\n" name i
6548           | Pathname name
6549           | Dev_or_Path name ->
6550               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6551               pr "  if (%s == NULL) return -1;\n" name
6552           | OptString name ->
6553               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6554                 name i i
6555           | FileIn name ->
6556               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6557                 name i i
6558           | FileOut name ->
6559               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6560                 name i i
6561           | StringList name | DeviceList name ->
6562               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6563               pr "  if (%s == NULL) return -1;\n" name;
6564           | Bool name ->
6565               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6566           | Int name ->
6567               pr "  %s = atoi (argv[%d]);\n" name i
6568           | Int64 name ->
6569               pr "  %s = atoll (argv[%d]);\n" name i
6570       ) (snd style);
6571
6572       (* Call C API function. *)
6573       let fn =
6574         try find_map (function FishAction n -> Some n | _ -> None) flags
6575         with Not_found -> sprintf "guestfs_%s" name in
6576       pr "  r = %s " fn;
6577       generate_c_call_args ~handle:"g" style;
6578       pr ";\n";
6579
6580       List.iter (
6581         function
6582         | Device name | String name
6583         | OptString name | FileIn name | FileOut name | Bool name
6584         | Int name | Int64 name -> ()
6585         | Pathname name | Dev_or_Path name ->
6586             pr "  free (%s);\n" name
6587         | StringList name | DeviceList name ->
6588             pr "  free_strings (%s);\n" name
6589       ) (snd style);
6590
6591       (* Check return value for errors and display command results. *)
6592       (match fst style with
6593        | RErr -> pr "  return r;\n"
6594        | RInt _ ->
6595            pr "  if (r == -1) return -1;\n";
6596            pr "  printf (\"%%d\\n\", r);\n";
6597            pr "  return 0;\n"
6598        | RInt64 _ ->
6599            pr "  if (r == -1) return -1;\n";
6600            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6601            pr "  return 0;\n"
6602        | RBool _ ->
6603            pr "  if (r == -1) return -1;\n";
6604            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6605            pr "  return 0;\n"
6606        | RConstString _ ->
6607            pr "  if (r == NULL) return -1;\n";
6608            pr "  printf (\"%%s\\n\", r);\n";
6609            pr "  return 0;\n"
6610        | RConstOptString _ ->
6611            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6612            pr "  return 0;\n"
6613        | RString _ ->
6614            pr "  if (r == NULL) return -1;\n";
6615            pr "  printf (\"%%s\\n\", r);\n";
6616            pr "  free (r);\n";
6617            pr "  return 0;\n"
6618        | RStringList _ ->
6619            pr "  if (r == NULL) return -1;\n";
6620            pr "  print_strings (r);\n";
6621            pr "  free_strings (r);\n";
6622            pr "  return 0;\n"
6623        | RStruct (_, typ) ->
6624            pr "  if (r == NULL) return -1;\n";
6625            pr "  print_%s (r);\n" typ;
6626            pr "  guestfs_free_%s (r);\n" typ;
6627            pr "  return 0;\n"
6628        | RStructList (_, typ) ->
6629            pr "  if (r == NULL) return -1;\n";
6630            pr "  print_%s_list (r);\n" typ;
6631            pr "  guestfs_free_%s_list (r);\n" typ;
6632            pr "  return 0;\n"
6633        | RHashtable _ ->
6634            pr "  if (r == NULL) return -1;\n";
6635            pr "  print_table (r);\n";
6636            pr "  free_strings (r);\n";
6637            pr "  return 0;\n"
6638        | RBufferOut _ ->
6639            pr "  if (r == NULL) return -1;\n";
6640            pr "  fwrite (r, size, 1, stdout);\n";
6641            pr "  free (r);\n";
6642            pr "  return 0;\n"
6643       );
6644       pr "}\n";
6645       pr "\n"
6646   ) all_functions;
6647
6648   (* run_action function *)
6649   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6650   pr "{\n";
6651   List.iter (
6652     fun (name, _, _, flags, _, _, _) ->
6653       let name2 = replace_char name '_' '-' in
6654       let alias =
6655         try find_map (function FishAlias n -> Some n | _ -> None) flags
6656         with Not_found -> name in
6657       pr "  if (";
6658       pr "strcasecmp (cmd, \"%s\") == 0" name;
6659       if name <> name2 then
6660         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6661       if name <> alias then
6662         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6663       pr ")\n";
6664       pr "    return run_%s (cmd, argc, argv);\n" name;
6665       pr "  else\n";
6666   ) all_functions;
6667   pr "    {\n";
6668   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6669   pr "      return -1;\n";
6670   pr "    }\n";
6671   pr "  return 0;\n";
6672   pr "}\n";
6673   pr "\n"
6674
6675 (* Readline completion for guestfish. *)
6676 and generate_fish_completion () =
6677   generate_header CStyle GPLv2;
6678
6679   let all_functions =
6680     List.filter (
6681       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6682     ) all_functions in
6683
6684   pr "\
6685 #include <config.h>
6686
6687 #include <stdio.h>
6688 #include <stdlib.h>
6689 #include <string.h>
6690
6691 #ifdef HAVE_LIBREADLINE
6692 #include <readline/readline.h>
6693 #endif
6694
6695 #include \"fish.h\"
6696
6697 #ifdef HAVE_LIBREADLINE
6698
6699 static const char *const commands[] = {
6700   BUILTIN_COMMANDS_FOR_COMPLETION,
6701 ";
6702
6703   (* Get the commands, including the aliases.  They don't need to be
6704    * sorted - the generator() function just does a dumb linear search.
6705    *)
6706   let commands =
6707     List.map (
6708       fun (name, _, _, flags, _, _, _) ->
6709         let name2 = replace_char name '_' '-' in
6710         let alias =
6711           try find_map (function FishAlias n -> Some n | _ -> None) flags
6712           with Not_found -> name in
6713
6714         if name <> alias then [name2; alias] else [name2]
6715     ) all_functions in
6716   let commands = List.flatten commands in
6717
6718   List.iter (pr "  \"%s\",\n") commands;
6719
6720   pr "  NULL
6721 };
6722
6723 static char *
6724 generator (const char *text, int state)
6725 {
6726   static int index, len;
6727   const char *name;
6728
6729   if (!state) {
6730     index = 0;
6731     len = strlen (text);
6732   }
6733
6734   rl_attempted_completion_over = 1;
6735
6736   while ((name = commands[index]) != NULL) {
6737     index++;
6738     if (strncasecmp (name, text, len) == 0)
6739       return strdup (name);
6740   }
6741
6742   return NULL;
6743 }
6744
6745 #endif /* HAVE_LIBREADLINE */
6746
6747 char **do_completion (const char *text, int start, int end)
6748 {
6749   char **matches = NULL;
6750
6751 #ifdef HAVE_LIBREADLINE
6752   rl_completion_append_character = ' ';
6753
6754   if (start == 0)
6755     matches = rl_completion_matches (text, generator);
6756   else if (complete_dest_paths)
6757     matches = rl_completion_matches (text, complete_dest_paths_generator);
6758 #endif
6759
6760   return matches;
6761 }
6762 ";
6763
6764 (* Generate the POD documentation for guestfish. *)
6765 and generate_fish_actions_pod () =
6766   let all_functions_sorted =
6767     List.filter (
6768       fun (_, _, _, flags, _, _, _) ->
6769         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6770     ) all_functions_sorted in
6771
6772   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6773
6774   List.iter (
6775     fun (name, style, _, flags, _, _, longdesc) ->
6776       let longdesc =
6777         Str.global_substitute rex (
6778           fun s ->
6779             let sub =
6780               try Str.matched_group 1 s
6781               with Not_found ->
6782                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6783             "C<" ^ replace_char sub '_' '-' ^ ">"
6784         ) longdesc in
6785       let name = replace_char name '_' '-' in
6786       let alias =
6787         try find_map (function FishAlias n -> Some n | _ -> None) flags
6788         with Not_found -> name in
6789
6790       pr "=head2 %s" name;
6791       if name <> alias then
6792         pr " | %s" alias;
6793       pr "\n";
6794       pr "\n";
6795       pr " %s" name;
6796       List.iter (
6797         function
6798         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6799         | OptString n -> pr " %s" n
6800         | StringList n | DeviceList n -> pr " '%s ...'" n
6801         | Bool _ -> pr " true|false"
6802         | Int n -> pr " %s" n
6803         | Int64 n -> pr " %s" n
6804         | FileIn n | FileOut n -> pr " (%s|-)" n
6805       ) (snd style);
6806       pr "\n";
6807       pr "\n";
6808       pr "%s\n\n" longdesc;
6809
6810       if List.exists (function FileIn _ | FileOut _ -> true
6811                       | _ -> false) (snd style) then
6812         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6813
6814       if List.mem ProtocolLimitWarning flags then
6815         pr "%s\n\n" protocol_limit_warning;
6816
6817       if List.mem DangerWillRobinson flags then
6818         pr "%s\n\n" danger_will_robinson;
6819
6820       match deprecation_notice flags with
6821       | None -> ()
6822       | Some txt -> pr "%s\n\n" txt
6823   ) all_functions_sorted
6824
6825 (* Generate a C function prototype. *)
6826 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6827     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6828     ?(prefix = "")
6829     ?handle name style =
6830   if extern then pr "extern ";
6831   if static then pr "static ";
6832   (match fst style with
6833    | RErr -> pr "int "
6834    | RInt _ -> pr "int "
6835    | RInt64 _ -> pr "int64_t "
6836    | RBool _ -> pr "int "
6837    | RConstString _ | RConstOptString _ -> pr "const char *"
6838    | RString _ | RBufferOut _ -> pr "char *"
6839    | RStringList _ | RHashtable _ -> pr "char **"
6840    | RStruct (_, typ) ->
6841        if not in_daemon then pr "struct guestfs_%s *" typ
6842        else pr "guestfs_int_%s *" typ
6843    | RStructList (_, typ) ->
6844        if not in_daemon then pr "struct guestfs_%s_list *" typ
6845        else pr "guestfs_int_%s_list *" typ
6846   );
6847   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6848   pr "%s%s (" prefix name;
6849   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6850     pr "void"
6851   else (
6852     let comma = ref false in
6853     (match handle with
6854      | None -> ()
6855      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6856     );
6857     let next () =
6858       if !comma then (
6859         if single_line then pr ", " else pr ",\n\t\t"
6860       );
6861       comma := true
6862     in
6863     List.iter (
6864       function
6865       | Pathname n
6866       | Device n | Dev_or_Path n
6867       | String n
6868       | OptString n ->
6869           next ();
6870           pr "const char *%s" n
6871       | StringList n | DeviceList n ->
6872           next ();
6873           pr "char *const *%s" n
6874       | Bool n -> next (); pr "int %s" n
6875       | Int n -> next (); pr "int %s" n
6876       | Int64 n -> next (); pr "int64_t %s" n
6877       | FileIn n
6878       | FileOut n ->
6879           if not in_daemon then (next (); pr "const char *%s" n)
6880     ) (snd style);
6881     if is_RBufferOut then (next (); pr "size_t *size_r");
6882   );
6883   pr ")";
6884   if semicolon then pr ";";
6885   if newline then pr "\n"
6886
6887 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6888 and generate_c_call_args ?handle ?(decl = false) style =
6889   pr "(";
6890   let comma = ref false in
6891   let next () =
6892     if !comma then pr ", ";
6893     comma := true
6894   in
6895   (match handle with
6896    | None -> ()
6897    | Some handle -> pr "%s" handle; comma := true
6898   );
6899   List.iter (
6900     fun arg ->
6901       next ();
6902       pr "%s" (name_of_argt arg)
6903   ) (snd style);
6904   (* For RBufferOut calls, add implicit &size parameter. *)
6905   if not decl then (
6906     match fst style with
6907     | RBufferOut _ ->
6908         next ();
6909         pr "&size"
6910     | _ -> ()
6911   );
6912   pr ")"
6913
6914 (* Generate the OCaml bindings interface. *)
6915 and generate_ocaml_mli () =
6916   generate_header OCamlStyle LGPLv2;
6917
6918   pr "\
6919 (** For API documentation you should refer to the C API
6920     in the guestfs(3) manual page.  The OCaml API uses almost
6921     exactly the same calls. *)
6922
6923 type t
6924 (** A [guestfs_h] handle. *)
6925
6926 exception Error of string
6927 (** This exception is raised when there is an error. *)
6928
6929 val create : unit -> t
6930
6931 val close : t -> unit
6932 (** Handles are closed by the garbage collector when they become
6933     unreferenced, but callers can also call this in order to
6934     provide predictable cleanup. *)
6935
6936 ";
6937   generate_ocaml_structure_decls ();
6938
6939   (* The actions. *)
6940   List.iter (
6941     fun (name, style, _, _, _, shortdesc, _) ->
6942       generate_ocaml_prototype name style;
6943       pr "(** %s *)\n" shortdesc;
6944       pr "\n"
6945   ) all_functions
6946
6947 (* Generate the OCaml bindings implementation. *)
6948 and generate_ocaml_ml () =
6949   generate_header OCamlStyle LGPLv2;
6950
6951   pr "\
6952 type t
6953 exception Error of string
6954 external create : unit -> t = \"ocaml_guestfs_create\"
6955 external close : t -> unit = \"ocaml_guestfs_close\"
6956
6957 let () =
6958   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6959
6960 ";
6961
6962   generate_ocaml_structure_decls ();
6963
6964   (* The actions. *)
6965   List.iter (
6966     fun (name, style, _, _, _, shortdesc, _) ->
6967       generate_ocaml_prototype ~is_external:true name style;
6968   ) all_functions
6969
6970 (* Generate the OCaml bindings C implementation. *)
6971 and generate_ocaml_c () =
6972   generate_header CStyle LGPLv2;
6973
6974   pr "\
6975 #include <stdio.h>
6976 #include <stdlib.h>
6977 #include <string.h>
6978
6979 #include <caml/config.h>
6980 #include <caml/alloc.h>
6981 #include <caml/callback.h>
6982 #include <caml/fail.h>
6983 #include <caml/memory.h>
6984 #include <caml/mlvalues.h>
6985 #include <caml/signals.h>
6986
6987 #include <guestfs.h>
6988
6989 #include \"guestfs_c.h\"
6990
6991 /* Copy a hashtable of string pairs into an assoc-list.  We return
6992  * the list in reverse order, but hashtables aren't supposed to be
6993  * ordered anyway.
6994  */
6995 static CAMLprim value
6996 copy_table (char * const * argv)
6997 {
6998   CAMLparam0 ();
6999   CAMLlocal5 (rv, pairv, kv, vv, cons);
7000   int i;
7001
7002   rv = Val_int (0);
7003   for (i = 0; argv[i] != NULL; i += 2) {
7004     kv = caml_copy_string (argv[i]);
7005     vv = caml_copy_string (argv[i+1]);
7006     pairv = caml_alloc (2, 0);
7007     Store_field (pairv, 0, kv);
7008     Store_field (pairv, 1, vv);
7009     cons = caml_alloc (2, 0);
7010     Store_field (cons, 1, rv);
7011     rv = cons;
7012     Store_field (cons, 0, pairv);
7013   }
7014
7015   CAMLreturn (rv);
7016 }
7017
7018 ";
7019
7020   (* Struct copy functions. *)
7021
7022   let emit_ocaml_copy_list_function typ =
7023     pr "static CAMLprim value\n";
7024     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7025     pr "{\n";
7026     pr "  CAMLparam0 ();\n";
7027     pr "  CAMLlocal2 (rv, v);\n";
7028     pr "  unsigned int i;\n";
7029     pr "\n";
7030     pr "  if (%ss->len == 0)\n" typ;
7031     pr "    CAMLreturn (Atom (0));\n";
7032     pr "  else {\n";
7033     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7034     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7035     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7036     pr "      caml_modify (&Field (rv, i), v);\n";
7037     pr "    }\n";
7038     pr "    CAMLreturn (rv);\n";
7039     pr "  }\n";
7040     pr "}\n";
7041     pr "\n";
7042   in
7043
7044   List.iter (
7045     fun (typ, cols) ->
7046       let has_optpercent_col =
7047         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7048
7049       pr "static CAMLprim value\n";
7050       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7051       pr "{\n";
7052       pr "  CAMLparam0 ();\n";
7053       if has_optpercent_col then
7054         pr "  CAMLlocal3 (rv, v, v2);\n"
7055       else
7056         pr "  CAMLlocal2 (rv, v);\n";
7057       pr "\n";
7058       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7059       iteri (
7060         fun i col ->
7061           (match col with
7062            | name, FString ->
7063                pr "  v = caml_copy_string (%s->%s);\n" typ name
7064            | name, FBuffer ->
7065                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7066                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7067                  typ name typ name
7068            | name, FUUID ->
7069                pr "  v = caml_alloc_string (32);\n";
7070                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7071            | name, (FBytes|FInt64|FUInt64) ->
7072                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7073            | name, (FInt32|FUInt32) ->
7074                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7075            | name, FOptPercent ->
7076                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7077                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7078                pr "    v = caml_alloc (1, 0);\n";
7079                pr "    Store_field (v, 0, v2);\n";
7080                pr "  } else /* None */\n";
7081                pr "    v = Val_int (0);\n";
7082            | name, FChar ->
7083                pr "  v = Val_int (%s->%s);\n" typ name
7084           );
7085           pr "  Store_field (rv, %d, v);\n" i
7086       ) cols;
7087       pr "  CAMLreturn (rv);\n";
7088       pr "}\n";
7089       pr "\n";
7090   ) structs;
7091
7092   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7093   List.iter (
7094     function
7095     | typ, (RStructListOnly | RStructAndList) ->
7096         (* generate the function for typ *)
7097         emit_ocaml_copy_list_function typ
7098     | typ, _ -> () (* empty *)
7099   ) (rstructs_used_by all_functions);
7100
7101   (* The wrappers. *)
7102   List.iter (
7103     fun (name, style, _, _, _, _, _) ->
7104       let params =
7105         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7106
7107       let needs_extra_vs =
7108         match fst style with RConstOptString _ -> true | _ -> false in
7109
7110       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7111       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7112       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7113
7114       pr "CAMLprim value\n";
7115       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7116       List.iter (pr ", value %s") (List.tl params);
7117       pr ")\n";
7118       pr "{\n";
7119
7120       (match params with
7121        | [p1; p2; p3; p4; p5] ->
7122            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7123        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7124            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7125            pr "  CAMLxparam%d (%s);\n"
7126              (List.length rest) (String.concat ", " rest)
7127        | ps ->
7128            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7129       );
7130       if not needs_extra_vs then
7131         pr "  CAMLlocal1 (rv);\n"
7132       else
7133         pr "  CAMLlocal3 (rv, v, v2);\n";
7134       pr "\n";
7135
7136       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7137       pr "  if (g == NULL)\n";
7138       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
7139       pr "\n";
7140
7141       List.iter (
7142         function
7143         | Pathname n
7144         | Device n | Dev_or_Path n
7145         | String n
7146         | FileIn n
7147         | FileOut n ->
7148             pr "  const char *%s = String_val (%sv);\n" n n
7149         | OptString n ->
7150             pr "  const char *%s =\n" n;
7151             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7152               n n
7153         | StringList n | DeviceList n ->
7154             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7155         | Bool n ->
7156             pr "  int %s = Bool_val (%sv);\n" n n
7157         | Int n ->
7158             pr "  int %s = Int_val (%sv);\n" n n
7159         | Int64 n ->
7160             pr "  int64_t %s = Int64_val (%sv);\n" n n
7161       ) (snd style);
7162       let error_code =
7163         match fst style with
7164         | RErr -> pr "  int r;\n"; "-1"
7165         | RInt _ -> pr "  int r;\n"; "-1"
7166         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7167         | RBool _ -> pr "  int r;\n"; "-1"
7168         | RConstString _ | RConstOptString _ ->
7169             pr "  const char *r;\n"; "NULL"
7170         | RString _ -> pr "  char *r;\n"; "NULL"
7171         | RStringList _ ->
7172             pr "  int i;\n";
7173             pr "  char **r;\n";
7174             "NULL"
7175         | RStruct (_, typ) ->
7176             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7177         | RStructList (_, typ) ->
7178             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7179         | RHashtable _ ->
7180             pr "  int i;\n";
7181             pr "  char **r;\n";
7182             "NULL"
7183         | RBufferOut _ ->
7184             pr "  char *r;\n";
7185             pr "  size_t size;\n";
7186             "NULL" in
7187       pr "\n";
7188
7189       pr "  caml_enter_blocking_section ();\n";
7190       pr "  r = guestfs_%s " name;
7191       generate_c_call_args ~handle:"g" style;
7192       pr ";\n";
7193       pr "  caml_leave_blocking_section ();\n";
7194
7195       List.iter (
7196         function
7197         | StringList n | DeviceList n ->
7198             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7199         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7200         | Bool _ | Int _ | Int64 _
7201         | FileIn _ | FileOut _ -> ()
7202       ) (snd style);
7203
7204       pr "  if (r == %s)\n" error_code;
7205       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7206       pr "\n";
7207
7208       (match fst style with
7209        | RErr -> pr "  rv = Val_unit;\n"
7210        | RInt _ -> pr "  rv = Val_int (r);\n"
7211        | RInt64 _ ->
7212            pr "  rv = caml_copy_int64 (r);\n"
7213        | RBool _ -> pr "  rv = Val_bool (r);\n"
7214        | RConstString _ ->
7215            pr "  rv = caml_copy_string (r);\n"
7216        | RConstOptString _ ->
7217            pr "  if (r) { /* Some string */\n";
7218            pr "    v = caml_alloc (1, 0);\n";
7219            pr "    v2 = caml_copy_string (r);\n";
7220            pr "    Store_field (v, 0, v2);\n";
7221            pr "  } else /* None */\n";
7222            pr "    v = Val_int (0);\n";
7223        | RString _ ->
7224            pr "  rv = caml_copy_string (r);\n";
7225            pr "  free (r);\n"
7226        | RStringList _ ->
7227            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7228            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7229            pr "  free (r);\n"
7230        | RStruct (_, typ) ->
7231            pr "  rv = copy_%s (r);\n" typ;
7232            pr "  guestfs_free_%s (r);\n" typ;
7233        | RStructList (_, typ) ->
7234            pr "  rv = copy_%s_list (r);\n" typ;
7235            pr "  guestfs_free_%s_list (r);\n" typ;
7236        | RHashtable _ ->
7237            pr "  rv = copy_table (r);\n";
7238            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7239            pr "  free (r);\n";
7240        | RBufferOut _ ->
7241            pr "  rv = caml_alloc_string (size);\n";
7242            pr "  memcpy (String_val (rv), r, size);\n";
7243       );
7244
7245       pr "  CAMLreturn (rv);\n";
7246       pr "}\n";
7247       pr "\n";
7248
7249       if List.length params > 5 then (
7250         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7251         pr "CAMLprim value ";
7252         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7253         pr "CAMLprim value\n";
7254         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7255         pr "{\n";
7256         pr "  return ocaml_guestfs_%s (argv[0]" name;
7257         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7258         pr ");\n";
7259         pr "}\n";
7260         pr "\n"
7261       )
7262   ) all_functions
7263
7264 and generate_ocaml_structure_decls () =
7265   List.iter (
7266     fun (typ, cols) ->
7267       pr "type %s = {\n" typ;
7268       List.iter (
7269         function
7270         | name, FString -> pr "  %s : string;\n" name
7271         | name, FBuffer -> pr "  %s : string;\n" name
7272         | name, FUUID -> pr "  %s : string;\n" name
7273         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7274         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7275         | name, FChar -> pr "  %s : char;\n" name
7276         | name, FOptPercent -> pr "  %s : float option;\n" name
7277       ) cols;
7278       pr "}\n";
7279       pr "\n"
7280   ) structs
7281
7282 and generate_ocaml_prototype ?(is_external = false) name style =
7283   if is_external then pr "external " else pr "val ";
7284   pr "%s : t -> " name;
7285   List.iter (
7286     function
7287     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7288     | OptString _ -> pr "string option -> "
7289     | StringList _ | DeviceList _ -> pr "string array -> "
7290     | Bool _ -> pr "bool -> "
7291     | Int _ -> pr "int -> "
7292     | Int64 _ -> pr "int64 -> "
7293   ) (snd style);
7294   (match fst style with
7295    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7296    | RInt _ -> pr "int"
7297    | RInt64 _ -> pr "int64"
7298    | RBool _ -> pr "bool"
7299    | RConstString _ -> pr "string"
7300    | RConstOptString _ -> pr "string option"
7301    | RString _ | RBufferOut _ -> pr "string"
7302    | RStringList _ -> pr "string array"
7303    | RStruct (_, typ) -> pr "%s" typ
7304    | RStructList (_, typ) -> pr "%s array" typ
7305    | RHashtable _ -> pr "(string * string) list"
7306   );
7307   if is_external then (
7308     pr " = ";
7309     if List.length (snd style) + 1 > 5 then
7310       pr "\"ocaml_guestfs_%s_byte\" " name;
7311     pr "\"ocaml_guestfs_%s\"" name
7312   );
7313   pr "\n"
7314
7315 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7316 and generate_perl_xs () =
7317   generate_header CStyle LGPLv2;
7318
7319   pr "\
7320 #include \"EXTERN.h\"
7321 #include \"perl.h\"
7322 #include \"XSUB.h\"
7323
7324 #include <guestfs.h>
7325
7326 #ifndef PRId64
7327 #define PRId64 \"lld\"
7328 #endif
7329
7330 static SV *
7331 my_newSVll(long long val) {
7332 #ifdef USE_64_BIT_ALL
7333   return newSViv(val);
7334 #else
7335   char buf[100];
7336   int len;
7337   len = snprintf(buf, 100, \"%%\" PRId64, val);
7338   return newSVpv(buf, len);
7339 #endif
7340 }
7341
7342 #ifndef PRIu64
7343 #define PRIu64 \"llu\"
7344 #endif
7345
7346 static SV *
7347 my_newSVull(unsigned long long val) {
7348 #ifdef USE_64_BIT_ALL
7349   return newSVuv(val);
7350 #else
7351   char buf[100];
7352   int len;
7353   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7354   return newSVpv(buf, len);
7355 #endif
7356 }
7357
7358 /* http://www.perlmonks.org/?node_id=680842 */
7359 static char **
7360 XS_unpack_charPtrPtr (SV *arg) {
7361   char **ret;
7362   AV *av;
7363   I32 i;
7364
7365   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7366     croak (\"array reference expected\");
7367
7368   av = (AV *)SvRV (arg);
7369   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7370   if (!ret)
7371     croak (\"malloc failed\");
7372
7373   for (i = 0; i <= av_len (av); i++) {
7374     SV **elem = av_fetch (av, i, 0);
7375
7376     if (!elem || !*elem)
7377       croak (\"missing element in list\");
7378
7379     ret[i] = SvPV_nolen (*elem);
7380   }
7381
7382   ret[i] = NULL;
7383
7384   return ret;
7385 }
7386
7387 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7388
7389 PROTOTYPES: ENABLE
7390
7391 guestfs_h *
7392 _create ()
7393    CODE:
7394       RETVAL = guestfs_create ();
7395       if (!RETVAL)
7396         croak (\"could not create guestfs handle\");
7397       guestfs_set_error_handler (RETVAL, NULL, NULL);
7398  OUTPUT:
7399       RETVAL
7400
7401 void
7402 DESTROY (g)
7403       guestfs_h *g;
7404  PPCODE:
7405       guestfs_close (g);
7406
7407 ";
7408
7409   List.iter (
7410     fun (name, style, _, _, _, _, _) ->
7411       (match fst style with
7412        | RErr -> pr "void\n"
7413        | RInt _ -> pr "SV *\n"
7414        | RInt64 _ -> pr "SV *\n"
7415        | RBool _ -> pr "SV *\n"
7416        | RConstString _ -> pr "SV *\n"
7417        | RConstOptString _ -> pr "SV *\n"
7418        | RString _ -> pr "SV *\n"
7419        | RBufferOut _ -> pr "SV *\n"
7420        | RStringList _
7421        | RStruct _ | RStructList _
7422        | RHashtable _ ->
7423            pr "void\n" (* all lists returned implictly on the stack *)
7424       );
7425       (* Call and arguments. *)
7426       pr "%s " name;
7427       generate_c_call_args ~handle:"g" ~decl:true style;
7428       pr "\n";
7429       pr "      guestfs_h *g;\n";
7430       iteri (
7431         fun i ->
7432           function
7433           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7434               pr "      char *%s;\n" n
7435           | OptString n ->
7436               (* http://www.perlmonks.org/?node_id=554277
7437                * Note that the implicit handle argument means we have
7438                * to add 1 to the ST(x) operator.
7439                *)
7440               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7441           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7442           | Bool n -> pr "      int %s;\n" n
7443           | Int n -> pr "      int %s;\n" n
7444           | Int64 n -> pr "      int64_t %s;\n" n
7445       ) (snd style);
7446
7447       let do_cleanups () =
7448         List.iter (
7449           function
7450           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7451           | Bool _ | Int _ | Int64 _
7452           | FileIn _ | FileOut _ -> ()
7453           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7454         ) (snd style)
7455       in
7456
7457       (* Code. *)
7458       (match fst style with
7459        | RErr ->
7460            pr "PREINIT:\n";
7461            pr "      int r;\n";
7462            pr " PPCODE:\n";
7463            pr "      r = guestfs_%s " name;
7464            generate_c_call_args ~handle:"g" style;
7465            pr ";\n";
7466            do_cleanups ();
7467            pr "      if (r == -1)\n";
7468            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7469        | RInt n
7470        | RBool n ->
7471            pr "PREINIT:\n";
7472            pr "      int %s;\n" n;
7473            pr "   CODE:\n";
7474            pr "      %s = guestfs_%s " n name;
7475            generate_c_call_args ~handle:"g" style;
7476            pr ";\n";
7477            do_cleanups ();
7478            pr "      if (%s == -1)\n" n;
7479            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7480            pr "      RETVAL = newSViv (%s);\n" n;
7481            pr " OUTPUT:\n";
7482            pr "      RETVAL\n"
7483        | RInt64 n ->
7484            pr "PREINIT:\n";
7485            pr "      int64_t %s;\n" n;
7486            pr "   CODE:\n";
7487            pr "      %s = guestfs_%s " n name;
7488            generate_c_call_args ~handle:"g" style;
7489            pr ";\n";
7490            do_cleanups ();
7491            pr "      if (%s == -1)\n" n;
7492            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7493            pr "      RETVAL = my_newSVll (%s);\n" n;
7494            pr " OUTPUT:\n";
7495            pr "      RETVAL\n"
7496        | RConstString n ->
7497            pr "PREINIT:\n";
7498            pr "      const char *%s;\n" n;
7499            pr "   CODE:\n";
7500            pr "      %s = guestfs_%s " n name;
7501            generate_c_call_args ~handle:"g" style;
7502            pr ";\n";
7503            do_cleanups ();
7504            pr "      if (%s == NULL)\n" n;
7505            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7506            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7507            pr " OUTPUT:\n";
7508            pr "      RETVAL\n"
7509        | RConstOptString n ->
7510            pr "PREINIT:\n";
7511            pr "      const char *%s;\n" n;
7512            pr "   CODE:\n";
7513            pr "      %s = guestfs_%s " n name;
7514            generate_c_call_args ~handle:"g" style;
7515            pr ";\n";
7516            do_cleanups ();
7517            pr "      if (%s == NULL)\n" n;
7518            pr "        RETVAL = &PL_sv_undef;\n";
7519            pr "      else\n";
7520            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7521            pr " OUTPUT:\n";
7522            pr "      RETVAL\n"
7523        | RString n ->
7524            pr "PREINIT:\n";
7525            pr "      char *%s;\n" n;
7526            pr "   CODE:\n";
7527            pr "      %s = guestfs_%s " n name;
7528            generate_c_call_args ~handle:"g" style;
7529            pr ";\n";
7530            do_cleanups ();
7531            pr "      if (%s == NULL)\n" n;
7532            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7533            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7534            pr "      free (%s);\n" n;
7535            pr " OUTPUT:\n";
7536            pr "      RETVAL\n"
7537        | RStringList n | RHashtable n ->
7538            pr "PREINIT:\n";
7539            pr "      char **%s;\n" n;
7540            pr "      int i, n;\n";
7541            pr " PPCODE:\n";
7542            pr "      %s = guestfs_%s " n name;
7543            generate_c_call_args ~handle:"g" style;
7544            pr ";\n";
7545            do_cleanups ();
7546            pr "      if (%s == NULL)\n" n;
7547            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7548            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7549            pr "      EXTEND (SP, n);\n";
7550            pr "      for (i = 0; i < n; ++i) {\n";
7551            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7552            pr "        free (%s[i]);\n" n;
7553            pr "      }\n";
7554            pr "      free (%s);\n" n;
7555        | RStruct (n, typ) ->
7556            let cols = cols_of_struct typ in
7557            generate_perl_struct_code typ cols name style n do_cleanups
7558        | RStructList (n, typ) ->
7559            let cols = cols_of_struct typ in
7560            generate_perl_struct_list_code typ cols name style n do_cleanups
7561        | RBufferOut n ->
7562            pr "PREINIT:\n";
7563            pr "      char *%s;\n" n;
7564            pr "      size_t size;\n";
7565            pr "   CODE:\n";
7566            pr "      %s = guestfs_%s " n name;
7567            generate_c_call_args ~handle:"g" style;
7568            pr ";\n";
7569            do_cleanups ();
7570            pr "      if (%s == NULL)\n" n;
7571            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7572            pr "      RETVAL = newSVpv (%s, size);\n" n;
7573            pr "      free (%s);\n" n;
7574            pr " OUTPUT:\n";
7575            pr "      RETVAL\n"
7576       );
7577
7578       pr "\n"
7579   ) all_functions
7580
7581 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7582   pr "PREINIT:\n";
7583   pr "      struct guestfs_%s_list *%s;\n" typ n;
7584   pr "      int i;\n";
7585   pr "      HV *hv;\n";
7586   pr " PPCODE:\n";
7587   pr "      %s = guestfs_%s " n name;
7588   generate_c_call_args ~handle:"g" style;
7589   pr ";\n";
7590   do_cleanups ();
7591   pr "      if (%s == NULL)\n" n;
7592   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7593   pr "      EXTEND (SP, %s->len);\n" n;
7594   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7595   pr "        hv = newHV ();\n";
7596   List.iter (
7597     function
7598     | name, FString ->
7599         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7600           name (String.length name) n name
7601     | name, FUUID ->
7602         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7603           name (String.length name) n name
7604     | name, FBuffer ->
7605         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7606           name (String.length name) n name n name
7607     | name, (FBytes|FUInt64) ->
7608         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7609           name (String.length name) n name
7610     | name, FInt64 ->
7611         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7612           name (String.length name) n name
7613     | name, (FInt32|FUInt32) ->
7614         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7615           name (String.length name) n name
7616     | name, FChar ->
7617         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7618           name (String.length name) n name
7619     | name, FOptPercent ->
7620         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7621           name (String.length name) n name
7622   ) cols;
7623   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7624   pr "      }\n";
7625   pr "      guestfs_free_%s_list (%s);\n" typ n
7626
7627 and generate_perl_struct_code typ cols name style n do_cleanups =
7628   pr "PREINIT:\n";
7629   pr "      struct guestfs_%s *%s;\n" typ n;
7630   pr " PPCODE:\n";
7631   pr "      %s = guestfs_%s " n name;
7632   generate_c_call_args ~handle:"g" style;
7633   pr ";\n";
7634   do_cleanups ();
7635   pr "      if (%s == NULL)\n" n;
7636   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7637   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7638   List.iter (
7639     fun ((name, _) as col) ->
7640       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7641
7642       match col with
7643       | name, FString ->
7644           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7645             n name
7646       | name, FBuffer ->
7647           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7648             n name n name
7649       | name, FUUID ->
7650           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7651             n name
7652       | name, (FBytes|FUInt64) ->
7653           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7654             n name
7655       | name, FInt64 ->
7656           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7657             n name
7658       | name, (FInt32|FUInt32) ->
7659           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7660             n name
7661       | name, FChar ->
7662           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7663             n name
7664       | name, FOptPercent ->
7665           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7666             n name
7667   ) cols;
7668   pr "      free (%s);\n" n
7669
7670 (* Generate Sys/Guestfs.pm. *)
7671 and generate_perl_pm () =
7672   generate_header HashStyle LGPLv2;
7673
7674   pr "\
7675 =pod
7676
7677 =head1 NAME
7678
7679 Sys::Guestfs - Perl bindings for libguestfs
7680
7681 =head1 SYNOPSIS
7682
7683  use Sys::Guestfs;
7684
7685  my $h = Sys::Guestfs->new ();
7686  $h->add_drive ('guest.img');
7687  $h->launch ();
7688  $h->mount ('/dev/sda1', '/');
7689  $h->touch ('/hello');
7690  $h->sync ();
7691
7692 =head1 DESCRIPTION
7693
7694 The C<Sys::Guestfs> module provides a Perl XS binding to the
7695 libguestfs API for examining and modifying virtual machine
7696 disk images.
7697
7698 Amongst the things this is good for: making batch configuration
7699 changes to guests, getting disk used/free statistics (see also:
7700 virt-df), migrating between virtualization systems (see also:
7701 virt-p2v), performing partial backups, performing partial guest
7702 clones, cloning guests and changing registry/UUID/hostname info, and
7703 much else besides.
7704
7705 Libguestfs uses Linux kernel and qemu code, and can access any type of
7706 guest filesystem that Linux and qemu can, including but not limited
7707 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7708 schemes, qcow, qcow2, vmdk.
7709
7710 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7711 LVs, what filesystem is in each LV, etc.).  It can also run commands
7712 in the context of the guest.  Also you can access filesystems over FTP.
7713
7714 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7715 functions for using libguestfs from Perl, including integration
7716 with libvirt.
7717
7718 =head1 ERRORS
7719
7720 All errors turn into calls to C<croak> (see L<Carp(3)>).
7721
7722 =head1 METHODS
7723
7724 =over 4
7725
7726 =cut
7727
7728 package Sys::Guestfs;
7729
7730 use strict;
7731 use warnings;
7732
7733 require XSLoader;
7734 XSLoader::load ('Sys::Guestfs');
7735
7736 =item $h = Sys::Guestfs->new ();
7737
7738 Create a new guestfs handle.
7739
7740 =cut
7741
7742 sub new {
7743   my $proto = shift;
7744   my $class = ref ($proto) || $proto;
7745
7746   my $self = Sys::Guestfs::_create ();
7747   bless $self, $class;
7748   return $self;
7749 }
7750
7751 ";
7752
7753   (* Actions.  We only need to print documentation for these as
7754    * they are pulled in from the XS code automatically.
7755    *)
7756   List.iter (
7757     fun (name, style, _, flags, _, _, longdesc) ->
7758       if not (List.mem NotInDocs flags) then (
7759         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7760         pr "=item ";
7761         generate_perl_prototype name style;
7762         pr "\n\n";
7763         pr "%s\n\n" longdesc;
7764         if List.mem ProtocolLimitWarning flags then
7765           pr "%s\n\n" protocol_limit_warning;
7766         if List.mem DangerWillRobinson flags then
7767           pr "%s\n\n" danger_will_robinson;
7768         match deprecation_notice flags with
7769         | None -> ()
7770         | Some txt -> pr "%s\n\n" txt
7771       )
7772   ) all_functions_sorted;
7773
7774   (* End of file. *)
7775   pr "\
7776 =cut
7777
7778 1;
7779
7780 =back
7781
7782 =head1 COPYRIGHT
7783
7784 Copyright (C) 2009 Red Hat Inc.
7785
7786 =head1 LICENSE
7787
7788 Please see the file COPYING.LIB for the full license.
7789
7790 =head1 SEE ALSO
7791
7792 L<guestfs(3)>,
7793 L<guestfish(1)>,
7794 L<http://libguestfs.org>,
7795 L<Sys::Guestfs::Lib(3)>.
7796
7797 =cut
7798 "
7799
7800 and generate_perl_prototype name style =
7801   (match fst style with
7802    | RErr -> ()
7803    | RBool n
7804    | RInt n
7805    | RInt64 n
7806    | RConstString n
7807    | RConstOptString n
7808    | RString n
7809    | RBufferOut n -> pr "$%s = " n
7810    | RStruct (n,_)
7811    | RHashtable n -> pr "%%%s = " n
7812    | RStringList n
7813    | RStructList (n,_) -> pr "@%s = " n
7814   );
7815   pr "$h->%s (" name;
7816   let comma = ref false in
7817   List.iter (
7818     fun arg ->
7819       if !comma then pr ", ";
7820       comma := true;
7821       match arg with
7822       | Pathname n | Device n | Dev_or_Path n | String n
7823       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
7824           pr "$%s" n
7825       | StringList n | DeviceList n ->
7826           pr "\\@%s" n
7827   ) (snd style);
7828   pr ");"
7829
7830 (* Generate Python C module. *)
7831 and generate_python_c () =
7832   generate_header CStyle LGPLv2;
7833
7834   pr "\
7835 #include <Python.h>
7836
7837 #include <stdio.h>
7838 #include <stdlib.h>
7839 #include <assert.h>
7840
7841 #include \"guestfs.h\"
7842
7843 typedef struct {
7844   PyObject_HEAD
7845   guestfs_h *g;
7846 } Pyguestfs_Object;
7847
7848 static guestfs_h *
7849 get_handle (PyObject *obj)
7850 {
7851   assert (obj);
7852   assert (obj != Py_None);
7853   return ((Pyguestfs_Object *) obj)->g;
7854 }
7855
7856 static PyObject *
7857 put_handle (guestfs_h *g)
7858 {
7859   assert (g);
7860   return
7861     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7862 }
7863
7864 /* This list should be freed (but not the strings) after use. */
7865 static char **
7866 get_string_list (PyObject *obj)
7867 {
7868   int i, len;
7869   char **r;
7870
7871   assert (obj);
7872
7873   if (!PyList_Check (obj)) {
7874     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7875     return NULL;
7876   }
7877
7878   len = PyList_Size (obj);
7879   r = malloc (sizeof (char *) * (len+1));
7880   if (r == NULL) {
7881     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7882     return NULL;
7883   }
7884
7885   for (i = 0; i < len; ++i)
7886     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7887   r[len] = NULL;
7888
7889   return r;
7890 }
7891
7892 static PyObject *
7893 put_string_list (char * const * const argv)
7894 {
7895   PyObject *list;
7896   int argc, i;
7897
7898   for (argc = 0; argv[argc] != NULL; ++argc)
7899     ;
7900
7901   list = PyList_New (argc);
7902   for (i = 0; i < argc; ++i)
7903     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7904
7905   return list;
7906 }
7907
7908 static PyObject *
7909 put_table (char * const * const argv)
7910 {
7911   PyObject *list, *item;
7912   int argc, i;
7913
7914   for (argc = 0; argv[argc] != NULL; ++argc)
7915     ;
7916
7917   list = PyList_New (argc >> 1);
7918   for (i = 0; i < argc; i += 2) {
7919     item = PyTuple_New (2);
7920     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7921     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7922     PyList_SetItem (list, i >> 1, item);
7923   }
7924
7925   return list;
7926 }
7927
7928 static void
7929 free_strings (char **argv)
7930 {
7931   int argc;
7932
7933   for (argc = 0; argv[argc] != NULL; ++argc)
7934     free (argv[argc]);
7935   free (argv);
7936 }
7937
7938 static PyObject *
7939 py_guestfs_create (PyObject *self, PyObject *args)
7940 {
7941   guestfs_h *g;
7942
7943   g = guestfs_create ();
7944   if (g == NULL) {
7945     PyErr_SetString (PyExc_RuntimeError,
7946                      \"guestfs.create: failed to allocate handle\");
7947     return NULL;
7948   }
7949   guestfs_set_error_handler (g, NULL, NULL);
7950   return put_handle (g);
7951 }
7952
7953 static PyObject *
7954 py_guestfs_close (PyObject *self, PyObject *args)
7955 {
7956   PyObject *py_g;
7957   guestfs_h *g;
7958
7959   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7960     return NULL;
7961   g = get_handle (py_g);
7962
7963   guestfs_close (g);
7964
7965   Py_INCREF (Py_None);
7966   return Py_None;
7967 }
7968
7969 ";
7970
7971   let emit_put_list_function typ =
7972     pr "static PyObject *\n";
7973     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7974     pr "{\n";
7975     pr "  PyObject *list;\n";
7976     pr "  int i;\n";
7977     pr "\n";
7978     pr "  list = PyList_New (%ss->len);\n" typ;
7979     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7980     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7981     pr "  return list;\n";
7982     pr "};\n";
7983     pr "\n"
7984   in
7985
7986   (* Structures, turned into Python dictionaries. *)
7987   List.iter (
7988     fun (typ, cols) ->
7989       pr "static PyObject *\n";
7990       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7991       pr "{\n";
7992       pr "  PyObject *dict;\n";
7993       pr "\n";
7994       pr "  dict = PyDict_New ();\n";
7995       List.iter (
7996         function
7997         | name, FString ->
7998             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7999             pr "                        PyString_FromString (%s->%s));\n"
8000               typ name
8001         | name, FBuffer ->
8002             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8003             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8004               typ name typ name
8005         | name, FUUID ->
8006             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8007             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8008               typ name
8009         | name, (FBytes|FUInt64) ->
8010             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8011             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8012               typ name
8013         | name, FInt64 ->
8014             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8015             pr "                        PyLong_FromLongLong (%s->%s));\n"
8016               typ name
8017         | name, FUInt32 ->
8018             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8019             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8020               typ name
8021         | name, FInt32 ->
8022             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8023             pr "                        PyLong_FromLong (%s->%s));\n"
8024               typ name
8025         | name, FOptPercent ->
8026             pr "  if (%s->%s >= 0)\n" typ name;
8027             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8028             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8029               typ name;
8030             pr "  else {\n";
8031             pr "    Py_INCREF (Py_None);\n";
8032             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8033             pr "  }\n"
8034         | name, FChar ->
8035             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8036             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8037       ) cols;
8038       pr "  return dict;\n";
8039       pr "};\n";
8040       pr "\n";
8041
8042   ) structs;
8043
8044   (* Emit a put_TYPE_list function definition only if that function is used. *)
8045   List.iter (
8046     function
8047     | typ, (RStructListOnly | RStructAndList) ->
8048         (* generate the function for typ *)
8049         emit_put_list_function typ
8050     | typ, _ -> () (* empty *)
8051   ) (rstructs_used_by all_functions);
8052
8053   (* Python wrapper functions. *)
8054   List.iter (
8055     fun (name, style, _, _, _, _, _) ->
8056       pr "static PyObject *\n";
8057       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8058       pr "{\n";
8059
8060       pr "  PyObject *py_g;\n";
8061       pr "  guestfs_h *g;\n";
8062       pr "  PyObject *py_r;\n";
8063
8064       let error_code =
8065         match fst style with
8066         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8067         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8068         | RConstString _ | RConstOptString _ ->
8069             pr "  const char *r;\n"; "NULL"
8070         | RString _ -> pr "  char *r;\n"; "NULL"
8071         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8072         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8073         | RStructList (_, typ) ->
8074             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8075         | RBufferOut _ ->
8076             pr "  char *r;\n";
8077             pr "  size_t size;\n";
8078             "NULL" in
8079
8080       List.iter (
8081         function
8082         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8083             pr "  const char *%s;\n" n
8084         | OptString n -> pr "  const char *%s;\n" n
8085         | StringList n | DeviceList n ->
8086             pr "  PyObject *py_%s;\n" n;
8087             pr "  char **%s;\n" n
8088         | Bool n -> pr "  int %s;\n" n
8089         | Int n -> pr "  int %s;\n" n
8090         | Int64 n -> pr "  long long %s;\n" n
8091       ) (snd style);
8092
8093       pr "\n";
8094
8095       (* Convert the parameters. *)
8096       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8097       List.iter (
8098         function
8099         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8100         | OptString _ -> pr "z"
8101         | StringList _ | DeviceList _ -> pr "O"
8102         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8103         | Int _ -> pr "i"
8104         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8105                              * emulate C's int/long/long long in Python?
8106                              *)
8107       ) (snd style);
8108       pr ":guestfs_%s\",\n" name;
8109       pr "                         &py_g";
8110       List.iter (
8111         function
8112         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8113         | OptString n -> pr ", &%s" n
8114         | StringList n | DeviceList n -> pr ", &py_%s" n
8115         | Bool n -> pr ", &%s" n
8116         | Int n -> pr ", &%s" n
8117         | Int64 n -> pr ", &%s" n
8118       ) (snd style);
8119
8120       pr "))\n";
8121       pr "    return NULL;\n";
8122
8123       pr "  g = get_handle (py_g);\n";
8124       List.iter (
8125         function
8126         | Pathname _ | Device _ | Dev_or_Path _ | String _
8127         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8128         | StringList n | DeviceList n ->
8129             pr "  %s = get_string_list (py_%s);\n" n n;
8130             pr "  if (!%s) return NULL;\n" n
8131       ) (snd style);
8132
8133       pr "\n";
8134
8135       pr "  r = guestfs_%s " name;
8136       generate_c_call_args ~handle:"g" style;
8137       pr ";\n";
8138
8139       List.iter (
8140         function
8141         | Pathname _ | Device _ | Dev_or_Path _ | String _
8142         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8143         | StringList n | DeviceList n ->
8144             pr "  free (%s);\n" n
8145       ) (snd style);
8146
8147       pr "  if (r == %s) {\n" error_code;
8148       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8149       pr "    return NULL;\n";
8150       pr "  }\n";
8151       pr "\n";
8152
8153       (match fst style with
8154        | RErr ->
8155            pr "  Py_INCREF (Py_None);\n";
8156            pr "  py_r = Py_None;\n"
8157        | RInt _
8158        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8159        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8160        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8161        | RConstOptString _ ->
8162            pr "  if (r)\n";
8163            pr "    py_r = PyString_FromString (r);\n";
8164            pr "  else {\n";
8165            pr "    Py_INCREF (Py_None);\n";
8166            pr "    py_r = Py_None;\n";
8167            pr "  }\n"
8168        | RString _ ->
8169            pr "  py_r = PyString_FromString (r);\n";
8170            pr "  free (r);\n"
8171        | RStringList _ ->
8172            pr "  py_r = put_string_list (r);\n";
8173            pr "  free_strings (r);\n"
8174        | RStruct (_, typ) ->
8175            pr "  py_r = put_%s (r);\n" typ;
8176            pr "  guestfs_free_%s (r);\n" typ
8177        | RStructList (_, typ) ->
8178            pr "  py_r = put_%s_list (r);\n" typ;
8179            pr "  guestfs_free_%s_list (r);\n" typ
8180        | RHashtable n ->
8181            pr "  py_r = put_table (r);\n";
8182            pr "  free_strings (r);\n"
8183        | RBufferOut _ ->
8184            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8185            pr "  free (r);\n"
8186       );
8187
8188       pr "  return py_r;\n";
8189       pr "}\n";
8190       pr "\n"
8191   ) all_functions;
8192
8193   (* Table of functions. *)
8194   pr "static PyMethodDef methods[] = {\n";
8195   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8196   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8197   List.iter (
8198     fun (name, _, _, _, _, _, _) ->
8199       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8200         name name
8201   ) all_functions;
8202   pr "  { NULL, NULL, 0, NULL }\n";
8203   pr "};\n";
8204   pr "\n";
8205
8206   (* Init function. *)
8207   pr "\
8208 void
8209 initlibguestfsmod (void)
8210 {
8211   static int initialized = 0;
8212
8213   if (initialized) return;
8214   Py_InitModule ((char *) \"libguestfsmod\", methods);
8215   initialized = 1;
8216 }
8217 "
8218
8219 (* Generate Python module. *)
8220 and generate_python_py () =
8221   generate_header HashStyle LGPLv2;
8222
8223   pr "\
8224 u\"\"\"Python bindings for libguestfs
8225
8226 import guestfs
8227 g = guestfs.GuestFS ()
8228 g.add_drive (\"guest.img\")
8229 g.launch ()
8230 parts = g.list_partitions ()
8231
8232 The guestfs module provides a Python binding to the libguestfs API
8233 for examining and modifying virtual machine disk images.
8234
8235 Amongst the things this is good for: making batch configuration
8236 changes to guests, getting disk used/free statistics (see also:
8237 virt-df), migrating between virtualization systems (see also:
8238 virt-p2v), performing partial backups, performing partial guest
8239 clones, cloning guests and changing registry/UUID/hostname info, and
8240 much else besides.
8241
8242 Libguestfs uses Linux kernel and qemu code, and can access any type of
8243 guest filesystem that Linux and qemu can, including but not limited
8244 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8245 schemes, qcow, qcow2, vmdk.
8246
8247 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8248 LVs, what filesystem is in each LV, etc.).  It can also run commands
8249 in the context of the guest.  Also you can access filesystems over FTP.
8250
8251 Errors which happen while using the API are turned into Python
8252 RuntimeError exceptions.
8253
8254 To create a guestfs handle you usually have to perform the following
8255 sequence of calls:
8256
8257 # Create the handle, call add_drive at least once, and possibly
8258 # several times if the guest has multiple block devices:
8259 g = guestfs.GuestFS ()
8260 g.add_drive (\"guest.img\")
8261
8262 # Launch the qemu subprocess and wait for it to become ready:
8263 g.launch ()
8264
8265 # Now you can issue commands, for example:
8266 logvols = g.lvs ()
8267
8268 \"\"\"
8269
8270 import libguestfsmod
8271
8272 class GuestFS:
8273     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8274
8275     def __init__ (self):
8276         \"\"\"Create a new libguestfs handle.\"\"\"
8277         self._o = libguestfsmod.create ()
8278
8279     def __del__ (self):
8280         libguestfsmod.close (self._o)
8281
8282 ";
8283
8284   List.iter (
8285     fun (name, style, _, flags, _, _, longdesc) ->
8286       pr "    def %s " name;
8287       generate_py_call_args ~handle:"self" (snd style);
8288       pr ":\n";
8289
8290       if not (List.mem NotInDocs flags) then (
8291         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8292         let doc =
8293           match fst style with
8294           | RErr | RInt _ | RInt64 _ | RBool _
8295           | RConstOptString _ | RConstString _
8296           | RString _ | RBufferOut _ -> doc
8297           | RStringList _ ->
8298               doc ^ "\n\nThis function returns a list of strings."
8299           | RStruct (_, typ) ->
8300               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8301           | RStructList (_, typ) ->
8302               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8303           | RHashtable _ ->
8304               doc ^ "\n\nThis function returns a dictionary." in
8305         let doc =
8306           if List.mem ProtocolLimitWarning flags then
8307             doc ^ "\n\n" ^ protocol_limit_warning
8308           else doc in
8309         let doc =
8310           if List.mem DangerWillRobinson flags then
8311             doc ^ "\n\n" ^ danger_will_robinson
8312           else doc in
8313         let doc =
8314           match deprecation_notice flags with
8315           | None -> doc
8316           | Some txt -> doc ^ "\n\n" ^ txt in
8317         let doc = pod2text ~width:60 name doc in
8318         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8319         let doc = String.concat "\n        " doc in
8320         pr "        u\"\"\"%s\"\"\"\n" doc;
8321       );
8322       pr "        return libguestfsmod.%s " name;
8323       generate_py_call_args ~handle:"self._o" (snd style);
8324       pr "\n";
8325       pr "\n";
8326   ) all_functions
8327
8328 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8329 and generate_py_call_args ~handle args =
8330   pr "(%s" handle;
8331   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8332   pr ")"
8333
8334 (* Useful if you need the longdesc POD text as plain text.  Returns a
8335  * list of lines.
8336  *
8337  * Because this is very slow (the slowest part of autogeneration),
8338  * we memoize the results.
8339  *)
8340 and pod2text ~width name longdesc =
8341   let key = width, name, longdesc in
8342   try Hashtbl.find pod2text_memo key
8343   with Not_found ->
8344     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8345     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8346     close_out chan;
8347     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8348     let chan = Unix.open_process_in cmd in
8349     let lines = ref [] in
8350     let rec loop i =
8351       let line = input_line chan in
8352       if i = 1 then             (* discard the first line of output *)
8353         loop (i+1)
8354       else (
8355         let line = triml line in
8356         lines := line :: !lines;
8357         loop (i+1)
8358       ) in
8359     let lines = try loop 1 with End_of_file -> List.rev !lines in
8360     Unix.unlink filename;
8361     (match Unix.close_process_in chan with
8362      | Unix.WEXITED 0 -> ()
8363      | Unix.WEXITED i ->
8364          failwithf "pod2text: process exited with non-zero status (%d)" i
8365      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8366          failwithf "pod2text: process signalled or stopped by signal %d" i
8367     );
8368     Hashtbl.add pod2text_memo key lines;
8369     pod2text_memo_updated ();
8370     lines
8371
8372 (* Generate ruby bindings. *)
8373 and generate_ruby_c () =
8374   generate_header CStyle LGPLv2;
8375
8376   pr "\
8377 #include <stdio.h>
8378 #include <stdlib.h>
8379
8380 #include <ruby.h>
8381
8382 #include \"guestfs.h\"
8383
8384 #include \"extconf.h\"
8385
8386 /* For Ruby < 1.9 */
8387 #ifndef RARRAY_LEN
8388 #define RARRAY_LEN(r) (RARRAY((r))->len)
8389 #endif
8390
8391 static VALUE m_guestfs;                 /* guestfs module */
8392 static VALUE c_guestfs;                 /* guestfs_h handle */
8393 static VALUE e_Error;                   /* used for all errors */
8394
8395 static void ruby_guestfs_free (void *p)
8396 {
8397   if (!p) return;
8398   guestfs_close ((guestfs_h *) p);
8399 }
8400
8401 static VALUE ruby_guestfs_create (VALUE m)
8402 {
8403   guestfs_h *g;
8404
8405   g = guestfs_create ();
8406   if (!g)
8407     rb_raise (e_Error, \"failed to create guestfs handle\");
8408
8409   /* Don't print error messages to stderr by default. */
8410   guestfs_set_error_handler (g, NULL, NULL);
8411
8412   /* Wrap it, and make sure the close function is called when the
8413    * handle goes away.
8414    */
8415   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8416 }
8417
8418 static VALUE ruby_guestfs_close (VALUE gv)
8419 {
8420   guestfs_h *g;
8421   Data_Get_Struct (gv, guestfs_h, g);
8422
8423   ruby_guestfs_free (g);
8424   DATA_PTR (gv) = NULL;
8425
8426   return Qnil;
8427 }
8428
8429 ";
8430
8431   List.iter (
8432     fun (name, style, _, _, _, _, _) ->
8433       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8434       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8435       pr ")\n";
8436       pr "{\n";
8437       pr "  guestfs_h *g;\n";
8438       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8439       pr "  if (!g)\n";
8440       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8441         name;
8442       pr "\n";
8443
8444       List.iter (
8445         function
8446         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8447             pr "  Check_Type (%sv, T_STRING);\n" n;
8448             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8449             pr "  if (!%s)\n" n;
8450             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8451             pr "              \"%s\", \"%s\");\n" n name
8452         | OptString n ->
8453             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8454         | StringList n | DeviceList n ->
8455             pr "  char **%s;\n" n;
8456             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8457             pr "  {\n";
8458             pr "    int i, len;\n";
8459             pr "    len = RARRAY_LEN (%sv);\n" n;
8460             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8461               n;
8462             pr "    for (i = 0; i < len; ++i) {\n";
8463             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8464             pr "      %s[i] = StringValueCStr (v);\n" n;
8465             pr "    }\n";
8466             pr "    %s[len] = NULL;\n" n;
8467             pr "  }\n";
8468         | Bool n ->
8469             pr "  int %s = RTEST (%sv);\n" n n
8470         | Int n ->
8471             pr "  int %s = NUM2INT (%sv);\n" n n
8472         | Int64 n ->
8473             pr "  long long %s = NUM2LL (%sv);\n" n n
8474       ) (snd style);
8475       pr "\n";
8476
8477       let error_code =
8478         match fst style with
8479         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8480         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8481         | RConstString _ | RConstOptString _ ->
8482             pr "  const char *r;\n"; "NULL"
8483         | RString _ -> pr "  char *r;\n"; "NULL"
8484         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8485         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8486         | RStructList (_, typ) ->
8487             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8488         | RBufferOut _ ->
8489             pr "  char *r;\n";
8490             pr "  size_t size;\n";
8491             "NULL" in
8492       pr "\n";
8493
8494       pr "  r = guestfs_%s " name;
8495       generate_c_call_args ~handle:"g" style;
8496       pr ";\n";
8497
8498       List.iter (
8499         function
8500         | Pathname _ | Device _ | Dev_or_Path _ | String _
8501         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8502         | StringList n | DeviceList n ->
8503             pr "  free (%s);\n" n
8504       ) (snd style);
8505
8506       pr "  if (r == %s)\n" error_code;
8507       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8508       pr "\n";
8509
8510       (match fst style with
8511        | RErr ->
8512            pr "  return Qnil;\n"
8513        | RInt _ | RBool _ ->
8514            pr "  return INT2NUM (r);\n"
8515        | RInt64 _ ->
8516            pr "  return ULL2NUM (r);\n"
8517        | RConstString _ ->
8518            pr "  return rb_str_new2 (r);\n";
8519        | RConstOptString _ ->
8520            pr "  if (r)\n";
8521            pr "    return rb_str_new2 (r);\n";
8522            pr "  else\n";
8523            pr "    return Qnil;\n";
8524        | RString _ ->
8525            pr "  VALUE rv = rb_str_new2 (r);\n";
8526            pr "  free (r);\n";
8527            pr "  return rv;\n";
8528        | RStringList _ ->
8529            pr "  int i, len = 0;\n";
8530            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8531            pr "  VALUE rv = rb_ary_new2 (len);\n";
8532            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8533            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8534            pr "    free (r[i]);\n";
8535            pr "  }\n";
8536            pr "  free (r);\n";
8537            pr "  return rv;\n"
8538        | RStruct (_, typ) ->
8539            let cols = cols_of_struct typ in
8540            generate_ruby_struct_code typ cols
8541        | RStructList (_, typ) ->
8542            let cols = cols_of_struct typ in
8543            generate_ruby_struct_list_code typ cols
8544        | RHashtable _ ->
8545            pr "  VALUE rv = rb_hash_new ();\n";
8546            pr "  int i;\n";
8547            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8548            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8549            pr "    free (r[i]);\n";
8550            pr "    free (r[i+1]);\n";
8551            pr "  }\n";
8552            pr "  free (r);\n";
8553            pr "  return rv;\n"
8554        | RBufferOut _ ->
8555            pr "  VALUE rv = rb_str_new (r, size);\n";
8556            pr "  free (r);\n";
8557            pr "  return rv;\n";
8558       );
8559
8560       pr "}\n";
8561       pr "\n"
8562   ) all_functions;
8563
8564   pr "\
8565 /* Initialize the module. */
8566 void Init__guestfs ()
8567 {
8568   m_guestfs = rb_define_module (\"Guestfs\");
8569   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8570   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8571
8572   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8573   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8574
8575 ";
8576   (* Define the rest of the methods. *)
8577   List.iter (
8578     fun (name, style, _, _, _, _, _) ->
8579       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8580       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8581   ) all_functions;
8582
8583   pr "}\n"
8584
8585 (* Ruby code to return a struct. *)
8586 and generate_ruby_struct_code typ cols =
8587   pr "  VALUE rv = rb_hash_new ();\n";
8588   List.iter (
8589     function
8590     | name, FString ->
8591         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8592     | name, FBuffer ->
8593         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8594     | name, FUUID ->
8595         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8596     | name, (FBytes|FUInt64) ->
8597         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8598     | name, FInt64 ->
8599         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8600     | name, FUInt32 ->
8601         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8602     | name, FInt32 ->
8603         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8604     | name, FOptPercent ->
8605         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8606     | name, FChar -> (* XXX wrong? *)
8607         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8608   ) cols;
8609   pr "  guestfs_free_%s (r);\n" typ;
8610   pr "  return rv;\n"
8611
8612 (* Ruby code to return a struct list. *)
8613 and generate_ruby_struct_list_code typ cols =
8614   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8615   pr "  int i;\n";
8616   pr "  for (i = 0; i < r->len; ++i) {\n";
8617   pr "    VALUE hv = rb_hash_new ();\n";
8618   List.iter (
8619     function
8620     | name, FString ->
8621         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8622     | name, FBuffer ->
8623         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
8624     | name, FUUID ->
8625         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8626     | name, (FBytes|FUInt64) ->
8627         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8628     | name, FInt64 ->
8629         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8630     | name, FUInt32 ->
8631         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8632     | name, FInt32 ->
8633         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8634     | name, FOptPercent ->
8635         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8636     | name, FChar -> (* XXX wrong? *)
8637         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8638   ) cols;
8639   pr "    rb_ary_push (rv, hv);\n";
8640   pr "  }\n";
8641   pr "  guestfs_free_%s_list (r);\n" typ;
8642   pr "  return rv;\n"
8643
8644 (* Generate Java bindings GuestFS.java file. *)
8645 and generate_java_java () =
8646   generate_header CStyle LGPLv2;
8647
8648   pr "\
8649 package com.redhat.et.libguestfs;
8650
8651 import java.util.HashMap;
8652 import com.redhat.et.libguestfs.LibGuestFSException;
8653 import com.redhat.et.libguestfs.PV;
8654 import com.redhat.et.libguestfs.VG;
8655 import com.redhat.et.libguestfs.LV;
8656 import com.redhat.et.libguestfs.Stat;
8657 import com.redhat.et.libguestfs.StatVFS;
8658 import com.redhat.et.libguestfs.IntBool;
8659 import com.redhat.et.libguestfs.Dirent;
8660
8661 /**
8662  * The GuestFS object is a libguestfs handle.
8663  *
8664  * @author rjones
8665  */
8666 public class GuestFS {
8667   // Load the native code.
8668   static {
8669     System.loadLibrary (\"guestfs_jni\");
8670   }
8671
8672   /**
8673    * The native guestfs_h pointer.
8674    */
8675   long g;
8676
8677   /**
8678    * Create a libguestfs handle.
8679    *
8680    * @throws LibGuestFSException
8681    */
8682   public GuestFS () throws LibGuestFSException
8683   {
8684     g = _create ();
8685   }
8686   private native long _create () throws LibGuestFSException;
8687
8688   /**
8689    * Close a libguestfs handle.
8690    *
8691    * You can also leave handles to be collected by the garbage
8692    * collector, but this method ensures that the resources used
8693    * by the handle are freed up immediately.  If you call any
8694    * other methods after closing the handle, you will get an
8695    * exception.
8696    *
8697    * @throws LibGuestFSException
8698    */
8699   public void close () throws LibGuestFSException
8700   {
8701     if (g != 0)
8702       _close (g);
8703     g = 0;
8704   }
8705   private native void _close (long g) throws LibGuestFSException;
8706
8707   public void finalize () throws LibGuestFSException
8708   {
8709     close ();
8710   }
8711
8712 ";
8713
8714   List.iter (
8715     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8716       if not (List.mem NotInDocs flags); then (
8717         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8718         let doc =
8719           if List.mem ProtocolLimitWarning flags then
8720             doc ^ "\n\n" ^ protocol_limit_warning
8721           else doc in
8722         let doc =
8723           if List.mem DangerWillRobinson flags then
8724             doc ^ "\n\n" ^ danger_will_robinson
8725           else doc in
8726         let doc =
8727           match deprecation_notice flags with
8728           | None -> doc
8729           | Some txt -> doc ^ "\n\n" ^ txt in
8730         let doc = pod2text ~width:60 name doc in
8731         let doc = List.map (            (* RHBZ#501883 *)
8732           function
8733           | "" -> "<p>"
8734           | nonempty -> nonempty
8735         ) doc in
8736         let doc = String.concat "\n   * " doc in
8737
8738         pr "  /**\n";
8739         pr "   * %s\n" shortdesc;
8740         pr "   * <p>\n";
8741         pr "   * %s\n" doc;
8742         pr "   * @throws LibGuestFSException\n";
8743         pr "   */\n";
8744         pr "  ";
8745       );
8746       generate_java_prototype ~public:true ~semicolon:false name style;
8747       pr "\n";
8748       pr "  {\n";
8749       pr "    if (g == 0)\n";
8750       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8751         name;
8752       pr "    ";
8753       if fst style <> RErr then pr "return ";
8754       pr "_%s " name;
8755       generate_java_call_args ~handle:"g" (snd style);
8756       pr ";\n";
8757       pr "  }\n";
8758       pr "  ";
8759       generate_java_prototype ~privat:true ~native:true name style;
8760       pr "\n";
8761       pr "\n";
8762   ) all_functions;
8763
8764   pr "}\n"
8765
8766 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8767 and generate_java_call_args ~handle args =
8768   pr "(%s" handle;
8769   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8770   pr ")"
8771
8772 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8773     ?(semicolon=true) name style =
8774   if privat then pr "private ";
8775   if public then pr "public ";
8776   if native then pr "native ";
8777
8778   (* return type *)
8779   (match fst style with
8780    | RErr -> pr "void ";
8781    | RInt _ -> pr "int ";
8782    | RInt64 _ -> pr "long ";
8783    | RBool _ -> pr "boolean ";
8784    | RConstString _ | RConstOptString _ | RString _
8785    | RBufferOut _ -> pr "String ";
8786    | RStringList _ -> pr "String[] ";
8787    | RStruct (_, typ) ->
8788        let name = java_name_of_struct typ in
8789        pr "%s " name;
8790    | RStructList (_, typ) ->
8791        let name = java_name_of_struct typ in
8792        pr "%s[] " name;
8793    | RHashtable _ -> pr "HashMap<String,String> ";
8794   );
8795
8796   if native then pr "_%s " name else pr "%s " name;
8797   pr "(";
8798   let needs_comma = ref false in
8799   if native then (
8800     pr "long g";
8801     needs_comma := true
8802   );
8803
8804   (* args *)
8805   List.iter (
8806     fun arg ->
8807       if !needs_comma then pr ", ";
8808       needs_comma := true;
8809
8810       match arg with
8811       | Pathname n
8812       | Device n | Dev_or_Path n
8813       | String n
8814       | OptString n
8815       | FileIn n
8816       | FileOut n ->
8817           pr "String %s" n
8818       | StringList n | DeviceList n ->
8819           pr "String[] %s" n
8820       | Bool n ->
8821           pr "boolean %s" n
8822       | Int n ->
8823           pr "int %s" n
8824       | Int64 n ->
8825           pr "long %s" n
8826   ) (snd style);
8827
8828   pr ")\n";
8829   pr "    throws LibGuestFSException";
8830   if semicolon then pr ";"
8831
8832 and generate_java_struct jtyp cols =
8833   generate_header CStyle LGPLv2;
8834
8835   pr "\
8836 package com.redhat.et.libguestfs;
8837
8838 /**
8839  * Libguestfs %s structure.
8840  *
8841  * @author rjones
8842  * @see GuestFS
8843  */
8844 public class %s {
8845 " jtyp jtyp;
8846
8847   List.iter (
8848     function
8849     | name, FString
8850     | name, FUUID
8851     | name, FBuffer -> pr "  public String %s;\n" name
8852     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8853     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8854     | name, FChar -> pr "  public char %s;\n" name
8855     | name, FOptPercent ->
8856         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8857         pr "  public float %s;\n" name
8858   ) cols;
8859
8860   pr "}\n"
8861
8862 and generate_java_c () =
8863   generate_header CStyle LGPLv2;
8864
8865   pr "\
8866 #include <stdio.h>
8867 #include <stdlib.h>
8868 #include <string.h>
8869
8870 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8871 #include \"guestfs.h\"
8872
8873 /* Note that this function returns.  The exception is not thrown
8874  * until after the wrapper function returns.
8875  */
8876 static void
8877 throw_exception (JNIEnv *env, const char *msg)
8878 {
8879   jclass cl;
8880   cl = (*env)->FindClass (env,
8881                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8882   (*env)->ThrowNew (env, cl, msg);
8883 }
8884
8885 JNIEXPORT jlong JNICALL
8886 Java_com_redhat_et_libguestfs_GuestFS__1create
8887   (JNIEnv *env, jobject obj)
8888 {
8889   guestfs_h *g;
8890
8891   g = guestfs_create ();
8892   if (g == NULL) {
8893     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8894     return 0;
8895   }
8896   guestfs_set_error_handler (g, NULL, NULL);
8897   return (jlong) (long) g;
8898 }
8899
8900 JNIEXPORT void JNICALL
8901 Java_com_redhat_et_libguestfs_GuestFS__1close
8902   (JNIEnv *env, jobject obj, jlong jg)
8903 {
8904   guestfs_h *g = (guestfs_h *) (long) jg;
8905   guestfs_close (g);
8906 }
8907
8908 ";
8909
8910   List.iter (
8911     fun (name, style, _, _, _, _, _) ->
8912       pr "JNIEXPORT ";
8913       (match fst style with
8914        | RErr -> pr "void ";
8915        | RInt _ -> pr "jint ";
8916        | RInt64 _ -> pr "jlong ";
8917        | RBool _ -> pr "jboolean ";
8918        | RConstString _ | RConstOptString _ | RString _
8919        | RBufferOut _ -> pr "jstring ";
8920        | RStruct _ | RHashtable _ ->
8921            pr "jobject ";
8922        | RStringList _ | RStructList _ ->
8923            pr "jobjectArray ";
8924       );
8925       pr "JNICALL\n";
8926       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8927       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8928       pr "\n";
8929       pr "  (JNIEnv *env, jobject obj, jlong jg";
8930       List.iter (
8931         function
8932         | Pathname n
8933         | Device n | Dev_or_Path n
8934         | String n
8935         | OptString n
8936         | FileIn n
8937         | FileOut n ->
8938             pr ", jstring j%s" n
8939         | StringList n | DeviceList n ->
8940             pr ", jobjectArray j%s" n
8941         | Bool n ->
8942             pr ", jboolean j%s" n
8943         | Int n ->
8944             pr ", jint j%s" n
8945         | Int64 n ->
8946             pr ", jlong j%s" n
8947       ) (snd style);
8948       pr ")\n";
8949       pr "{\n";
8950       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8951       let error_code, no_ret =
8952         match fst style with
8953         | RErr -> pr "  int r;\n"; "-1", ""
8954         | RBool _
8955         | RInt _ -> pr "  int r;\n"; "-1", "0"
8956         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8957         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8958         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8959         | RString _ ->
8960             pr "  jstring jr;\n";
8961             pr "  char *r;\n"; "NULL", "NULL"
8962         | RStringList _ ->
8963             pr "  jobjectArray jr;\n";
8964             pr "  int r_len;\n";
8965             pr "  jclass cl;\n";
8966             pr "  jstring jstr;\n";
8967             pr "  char **r;\n"; "NULL", "NULL"
8968         | RStruct (_, typ) ->
8969             pr "  jobject jr;\n";
8970             pr "  jclass cl;\n";
8971             pr "  jfieldID fl;\n";
8972             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8973         | RStructList (_, typ) ->
8974             pr "  jobjectArray jr;\n";
8975             pr "  jclass cl;\n";
8976             pr "  jfieldID fl;\n";
8977             pr "  jobject jfl;\n";
8978             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8979         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8980         | RBufferOut _ ->
8981             pr "  jstring jr;\n";
8982             pr "  char *r;\n";
8983             pr "  size_t size;\n";
8984             "NULL", "NULL" in
8985       List.iter (
8986         function
8987         | Pathname n
8988         | Device n | Dev_or_Path n
8989         | String n
8990         | OptString n
8991         | FileIn n
8992         | FileOut n ->
8993             pr "  const char *%s;\n" n
8994         | StringList n | DeviceList n ->
8995             pr "  int %s_len;\n" n;
8996             pr "  const char **%s;\n" n
8997         | Bool n
8998         | Int n ->
8999             pr "  int %s;\n" n
9000         | Int64 n ->
9001             pr "  int64_t %s;\n" n
9002       ) (snd style);
9003
9004       let needs_i =
9005         (match fst style with
9006          | RStringList _ | RStructList _ -> true
9007          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9008          | RConstOptString _
9009          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9010           List.exists (function
9011                        | StringList _ -> true
9012                        | DeviceList _ -> true
9013                        | _ -> false) (snd style) in
9014       if needs_i then
9015         pr "  int i;\n";
9016
9017       pr "\n";
9018
9019       (* Get the parameters. *)
9020       List.iter (
9021         function
9022         | Pathname n
9023         | Device n | Dev_or_Path n
9024         | String n
9025         | FileIn n
9026         | FileOut n ->
9027             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9028         | OptString n ->
9029             (* This is completely undocumented, but Java null becomes
9030              * a NULL parameter.
9031              *)
9032             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9033         | StringList n | DeviceList n ->
9034             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9035             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9036             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9037             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9038               n;
9039             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9040             pr "  }\n";
9041             pr "  %s[%s_len] = NULL;\n" n n;
9042         | Bool n
9043         | Int n
9044         | Int64 n ->
9045             pr "  %s = j%s;\n" n n
9046       ) (snd style);
9047
9048       (* Make the call. *)
9049       pr "  r = guestfs_%s " name;
9050       generate_c_call_args ~handle:"g" style;
9051       pr ";\n";
9052
9053       (* Release the parameters. *)
9054       List.iter (
9055         function
9056         | Pathname n
9057         | Device n | Dev_or_Path n
9058         | String n
9059         | FileIn n
9060         | FileOut n ->
9061             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9062         | OptString n ->
9063             pr "  if (j%s)\n" n;
9064             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9065         | StringList n | DeviceList n ->
9066             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9067             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9068               n;
9069             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9070             pr "  }\n";
9071             pr "  free (%s);\n" n
9072         | Bool n
9073         | Int n
9074         | Int64 n -> ()
9075       ) (snd style);
9076
9077       (* Check for errors. *)
9078       pr "  if (r == %s) {\n" error_code;
9079       pr "    throw_exception (env, guestfs_last_error (g));\n";
9080       pr "    return %s;\n" no_ret;
9081       pr "  }\n";
9082
9083       (* Return value. *)
9084       (match fst style with
9085        | RErr -> ()
9086        | RInt _ -> pr "  return (jint) r;\n"
9087        | RBool _ -> pr "  return (jboolean) r;\n"
9088        | RInt64 _ -> pr "  return (jlong) r;\n"
9089        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9090        | RConstOptString _ ->
9091            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9092        | RString _ ->
9093            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9094            pr "  free (r);\n";
9095            pr "  return jr;\n"
9096        | RStringList _ ->
9097            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9098            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9099            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9100            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9101            pr "  for (i = 0; i < r_len; ++i) {\n";
9102            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9103            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9104            pr "    free (r[i]);\n";
9105            pr "  }\n";
9106            pr "  free (r);\n";
9107            pr "  return jr;\n"
9108        | RStruct (_, typ) ->
9109            let jtyp = java_name_of_struct typ in
9110            let cols = cols_of_struct typ in
9111            generate_java_struct_return typ jtyp cols
9112        | RStructList (_, typ) ->
9113            let jtyp = java_name_of_struct typ in
9114            let cols = cols_of_struct typ in
9115            generate_java_struct_list_return typ jtyp cols
9116        | RHashtable _ ->
9117            (* XXX *)
9118            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9119            pr "  return NULL;\n"
9120        | RBufferOut _ ->
9121            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9122            pr "  free (r);\n";
9123            pr "  return jr;\n"
9124       );
9125
9126       pr "}\n";
9127       pr "\n"
9128   ) all_functions
9129
9130 and generate_java_struct_return typ jtyp cols =
9131   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9132   pr "  jr = (*env)->AllocObject (env, cl);\n";
9133   List.iter (
9134     function
9135     | name, FString ->
9136         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9137         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9138     | name, FUUID ->
9139         pr "  {\n";
9140         pr "    char s[33];\n";
9141         pr "    memcpy (s, r->%s, 32);\n" name;
9142         pr "    s[32] = 0;\n";
9143         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9144         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9145         pr "  }\n";
9146     | name, FBuffer ->
9147         pr "  {\n";
9148         pr "    int len = r->%s_len;\n" name;
9149         pr "    char s[len+1];\n";
9150         pr "    memcpy (s, r->%s, len);\n" name;
9151         pr "    s[len] = 0;\n";
9152         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9153         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9154         pr "  }\n";
9155     | name, (FBytes|FUInt64|FInt64) ->
9156         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9157         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9158     | name, (FUInt32|FInt32) ->
9159         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9160         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9161     | name, FOptPercent ->
9162         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9163         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9164     | name, FChar ->
9165         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9166         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9167   ) cols;
9168   pr "  free (r);\n";
9169   pr "  return jr;\n"
9170
9171 and generate_java_struct_list_return typ jtyp cols =
9172   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9173   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9174   pr "  for (i = 0; i < r->len; ++i) {\n";
9175   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9176   List.iter (
9177     function
9178     | name, FString ->
9179         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9180         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9181     | name, FUUID ->
9182         pr "    {\n";
9183         pr "      char s[33];\n";
9184         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9185         pr "      s[32] = 0;\n";
9186         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9187         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9188         pr "    }\n";
9189     | name, FBuffer ->
9190         pr "    {\n";
9191         pr "      int len = r->val[i].%s_len;\n" name;
9192         pr "      char s[len+1];\n";
9193         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9194         pr "      s[len] = 0;\n";
9195         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9196         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9197         pr "    }\n";
9198     | name, (FBytes|FUInt64|FInt64) ->
9199         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9200         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9201     | name, (FUInt32|FInt32) ->
9202         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9203         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9204     | name, FOptPercent ->
9205         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9206         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9207     | name, FChar ->
9208         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9209         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9210   ) cols;
9211   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9212   pr "  }\n";
9213   pr "  guestfs_free_%s_list (r);\n" typ;
9214   pr "  return jr;\n"
9215
9216 and generate_java_makefile_inc () =
9217   generate_header HashStyle GPLv2;
9218
9219   pr "java_built_sources = \\\n";
9220   List.iter (
9221     fun (typ, jtyp) ->
9222         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9223   ) java_structs;
9224   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9225
9226 and generate_haskell_hs () =
9227   generate_header HaskellStyle LGPLv2;
9228
9229   (* XXX We only know how to generate partial FFI for Haskell
9230    * at the moment.  Please help out!
9231    *)
9232   let can_generate style =
9233     match style with
9234     | RErr, _
9235     | RInt _, _
9236     | RInt64 _, _ -> true
9237     | RBool _, _
9238     | RConstString _, _
9239     | RConstOptString _, _
9240     | RString _, _
9241     | RStringList _, _
9242     | RStruct _, _
9243     | RStructList _, _
9244     | RHashtable _, _
9245     | RBufferOut _, _ -> false in
9246
9247   pr "\
9248 {-# INCLUDE <guestfs.h> #-}
9249 {-# LANGUAGE ForeignFunctionInterface #-}
9250
9251 module Guestfs (
9252   create";
9253
9254   (* List out the names of the actions we want to export. *)
9255   List.iter (
9256     fun (name, style, _, _, _, _, _) ->
9257       if can_generate style then pr ",\n  %s" name
9258   ) all_functions;
9259
9260   pr "
9261   ) where
9262 import Foreign
9263 import Foreign.C
9264 import Foreign.C.Types
9265 import IO
9266 import Control.Exception
9267 import Data.Typeable
9268
9269 data GuestfsS = GuestfsS            -- represents the opaque C struct
9270 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9271 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9272
9273 -- XXX define properly later XXX
9274 data PV = PV
9275 data VG = VG
9276 data LV = LV
9277 data IntBool = IntBool
9278 data Stat = Stat
9279 data StatVFS = StatVFS
9280 data Hashtable = Hashtable
9281
9282 foreign import ccall unsafe \"guestfs_create\" c_create
9283   :: IO GuestfsP
9284 foreign import ccall unsafe \"&guestfs_close\" c_close
9285   :: FunPtr (GuestfsP -> IO ())
9286 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9287   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9288
9289 create :: IO GuestfsH
9290 create = do
9291   p <- c_create
9292   c_set_error_handler p nullPtr nullPtr
9293   h <- newForeignPtr c_close p
9294   return h
9295
9296 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9297   :: GuestfsP -> IO CString
9298
9299 -- last_error :: GuestfsH -> IO (Maybe String)
9300 -- last_error h = do
9301 --   str <- withForeignPtr h (\\p -> c_last_error p)
9302 --   maybePeek peekCString str
9303
9304 last_error :: GuestfsH -> IO (String)
9305 last_error h = do
9306   str <- withForeignPtr h (\\p -> c_last_error p)
9307   if (str == nullPtr)
9308     then return \"no error\"
9309     else peekCString str
9310
9311 ";
9312
9313   (* Generate wrappers for each foreign function. *)
9314   List.iter (
9315     fun (name, style, _, _, _, _, _) ->
9316       if can_generate style then (
9317         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9318         pr "  :: ";
9319         generate_haskell_prototype ~handle:"GuestfsP" style;
9320         pr "\n";
9321         pr "\n";
9322         pr "%s :: " name;
9323         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9324         pr "\n";
9325         pr "%s %s = do\n" name
9326           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9327         pr "  r <- ";
9328         (* Convert pointer arguments using with* functions. *)
9329         List.iter (
9330           function
9331           | FileIn n
9332           | FileOut n
9333           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9334           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9335           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9336           | Bool _ | Int _ | Int64 _ -> ()
9337         ) (snd style);
9338         (* Convert integer arguments. *)
9339         let args =
9340           List.map (
9341             function
9342             | Bool n -> sprintf "(fromBool %s)" n
9343             | Int n -> sprintf "(fromIntegral %s)" n
9344             | Int64 n -> sprintf "(fromIntegral %s)" n
9345             | FileIn n | FileOut n
9346             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9347           ) (snd style) in
9348         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9349           (String.concat " " ("p" :: args));
9350         (match fst style with
9351          | RErr | RInt _ | RInt64 _ | RBool _ ->
9352              pr "  if (r == -1)\n";
9353              pr "    then do\n";
9354              pr "      err <- last_error h\n";
9355              pr "      fail err\n";
9356          | RConstString _ | RConstOptString _ | RString _
9357          | RStringList _ | RStruct _
9358          | RStructList _ | RHashtable _ | RBufferOut _ ->
9359              pr "  if (r == nullPtr)\n";
9360              pr "    then do\n";
9361              pr "      err <- last_error h\n";
9362              pr "      fail err\n";
9363         );
9364         (match fst style with
9365          | RErr ->
9366              pr "    else return ()\n"
9367          | RInt _ ->
9368              pr "    else return (fromIntegral r)\n"
9369          | RInt64 _ ->
9370              pr "    else return (fromIntegral r)\n"
9371          | RBool _ ->
9372              pr "    else return (toBool r)\n"
9373          | RConstString _
9374          | RConstOptString _
9375          | RString _
9376          | RStringList _
9377          | RStruct _
9378          | RStructList _
9379          | RHashtable _
9380          | RBufferOut _ ->
9381              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9382         );
9383         pr "\n";
9384       )
9385   ) all_functions
9386
9387 and generate_haskell_prototype ~handle ?(hs = false) style =
9388   pr "%s -> " handle;
9389   let string = if hs then "String" else "CString" in
9390   let int = if hs then "Int" else "CInt" in
9391   let bool = if hs then "Bool" else "CInt" in
9392   let int64 = if hs then "Integer" else "Int64" in
9393   List.iter (
9394     fun arg ->
9395       (match arg with
9396        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9397        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9398        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9399        | Bool _ -> pr "%s" bool
9400        | Int _ -> pr "%s" int
9401        | Int64 _ -> pr "%s" int
9402        | FileIn _ -> pr "%s" string
9403        | FileOut _ -> pr "%s" string
9404       );
9405       pr " -> ";
9406   ) (snd style);
9407   pr "IO (";
9408   (match fst style with
9409    | RErr -> if not hs then pr "CInt"
9410    | RInt _ -> pr "%s" int
9411    | RInt64 _ -> pr "%s" int64
9412    | RBool _ -> pr "%s" bool
9413    | RConstString _ -> pr "%s" string
9414    | RConstOptString _ -> pr "Maybe %s" string
9415    | RString _ -> pr "%s" string
9416    | RStringList _ -> pr "[%s]" string
9417    | RStruct (_, typ) ->
9418        let name = java_name_of_struct typ in
9419        pr "%s" name
9420    | RStructList (_, typ) ->
9421        let name = java_name_of_struct typ in
9422        pr "[%s]" name
9423    | RHashtable _ -> pr "Hashtable"
9424    | RBufferOut _ -> pr "%s" string
9425   );
9426   pr ")"
9427
9428 and generate_bindtests () =
9429   generate_header CStyle LGPLv2;
9430
9431   pr "\
9432 #include <stdio.h>
9433 #include <stdlib.h>
9434 #include <inttypes.h>
9435 #include <string.h>
9436
9437 #include \"guestfs.h\"
9438 #include \"guestfs-internal-actions.h\"
9439 #include \"guestfs_protocol.h\"
9440
9441 #define error guestfs_error
9442 #define safe_calloc guestfs_safe_calloc
9443 #define safe_malloc guestfs_safe_malloc
9444
9445 static void
9446 print_strings (char *const *argv)
9447 {
9448   int argc;
9449
9450   printf (\"[\");
9451   for (argc = 0; argv[argc] != NULL; ++argc) {
9452     if (argc > 0) printf (\", \");
9453     printf (\"\\\"%%s\\\"\", argv[argc]);
9454   }
9455   printf (\"]\\n\");
9456 }
9457
9458 /* The test0 function prints its parameters to stdout. */
9459 ";
9460
9461   let test0, tests =
9462     match test_functions with
9463     | [] -> assert false
9464     | test0 :: tests -> test0, tests in
9465
9466   let () =
9467     let (name, style, _, _, _, _, _) = test0 in
9468     generate_prototype ~extern:false ~semicolon:false ~newline:true
9469       ~handle:"g" ~prefix:"guestfs__" name style;
9470     pr "{\n";
9471     List.iter (
9472       function
9473       | Pathname n
9474       | Device n | Dev_or_Path n
9475       | String n
9476       | FileIn n
9477       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9478       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9479       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9480       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9481       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9482       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9483     ) (snd style);
9484     pr "  /* Java changes stdout line buffering so we need this: */\n";
9485     pr "  fflush (stdout);\n";
9486     pr "  return 0;\n";
9487     pr "}\n";
9488     pr "\n" in
9489
9490   List.iter (
9491     fun (name, style, _, _, _, _, _) ->
9492       if String.sub name (String.length name - 3) 3 <> "err" then (
9493         pr "/* Test normal return. */\n";
9494         generate_prototype ~extern:false ~semicolon:false ~newline:true
9495           ~handle:"g" ~prefix:"guestfs__" name style;
9496         pr "{\n";
9497         (match fst style with
9498          | RErr ->
9499              pr "  return 0;\n"
9500          | RInt _ ->
9501              pr "  int r;\n";
9502              pr "  sscanf (val, \"%%d\", &r);\n";
9503              pr "  return r;\n"
9504          | RInt64 _ ->
9505              pr "  int64_t r;\n";
9506              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9507              pr "  return r;\n"
9508          | RBool _ ->
9509              pr "  return strcmp (val, \"true\") == 0;\n"
9510          | RConstString _
9511          | RConstOptString _ ->
9512              (* Can't return the input string here.  Return a static
9513               * string so we ensure we get a segfault if the caller
9514               * tries to free it.
9515               *)
9516              pr "  return \"static string\";\n"
9517          | RString _ ->
9518              pr "  return strdup (val);\n"
9519          | RStringList _ ->
9520              pr "  char **strs;\n";
9521              pr "  int n, i;\n";
9522              pr "  sscanf (val, \"%%d\", &n);\n";
9523              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9524              pr "  for (i = 0; i < n; ++i) {\n";
9525              pr "    strs[i] = safe_malloc (g, 16);\n";
9526              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9527              pr "  }\n";
9528              pr "  strs[n] = NULL;\n";
9529              pr "  return strs;\n"
9530          | RStruct (_, typ) ->
9531              pr "  struct guestfs_%s *r;\n" typ;
9532              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9533              pr "  return r;\n"
9534          | RStructList (_, typ) ->
9535              pr "  struct guestfs_%s_list *r;\n" typ;
9536              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9537              pr "  sscanf (val, \"%%d\", &r->len);\n";
9538              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9539              pr "  return r;\n"
9540          | RHashtable _ ->
9541              pr "  char **strs;\n";
9542              pr "  int n, i;\n";
9543              pr "  sscanf (val, \"%%d\", &n);\n";
9544              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9545              pr "  for (i = 0; i < n; ++i) {\n";
9546              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9547              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9548              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9549              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9550              pr "  }\n";
9551              pr "  strs[n*2] = NULL;\n";
9552              pr "  return strs;\n"
9553          | RBufferOut _ ->
9554              pr "  return strdup (val);\n"
9555         );
9556         pr "}\n";
9557         pr "\n"
9558       ) else (
9559         pr "/* Test error return. */\n";
9560         generate_prototype ~extern:false ~semicolon:false ~newline:true
9561           ~handle:"g" ~prefix:"guestfs__" name style;
9562         pr "{\n";
9563         pr "  error (g, \"error\");\n";
9564         (match fst style with
9565          | RErr | RInt _ | RInt64 _ | RBool _ ->
9566              pr "  return -1;\n"
9567          | RConstString _ | RConstOptString _
9568          | RString _ | RStringList _ | RStruct _
9569          | RStructList _
9570          | RHashtable _
9571          | RBufferOut _ ->
9572              pr "  return NULL;\n"
9573         );
9574         pr "}\n";
9575         pr "\n"
9576       )
9577   ) tests
9578
9579 and generate_ocaml_bindtests () =
9580   generate_header OCamlStyle GPLv2;
9581
9582   pr "\
9583 let () =
9584   let g = Guestfs.create () in
9585 ";
9586
9587   let mkargs args =
9588     String.concat " " (
9589       List.map (
9590         function
9591         | CallString s -> "\"" ^ s ^ "\""
9592         | CallOptString None -> "None"
9593         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9594         | CallStringList xs ->
9595             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9596         | CallInt i when i >= 0 -> string_of_int i
9597         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9598         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9599         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9600         | CallBool b -> string_of_bool b
9601       ) args
9602     )
9603   in
9604
9605   generate_lang_bindtests (
9606     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9607   );
9608
9609   pr "print_endline \"EOF\"\n"
9610
9611 and generate_perl_bindtests () =
9612   pr "#!/usr/bin/perl -w\n";
9613   generate_header HashStyle GPLv2;
9614
9615   pr "\
9616 use strict;
9617
9618 use Sys::Guestfs;
9619
9620 my $g = Sys::Guestfs->new ();
9621 ";
9622
9623   let mkargs args =
9624     String.concat ", " (
9625       List.map (
9626         function
9627         | CallString s -> "\"" ^ s ^ "\""
9628         | CallOptString None -> "undef"
9629         | CallOptString (Some s) -> sprintf "\"%s\"" s
9630         | CallStringList xs ->
9631             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9632         | CallInt i -> string_of_int i
9633         | CallInt64 i -> Int64.to_string i
9634         | CallBool b -> if b then "1" else "0"
9635       ) args
9636     )
9637   in
9638
9639   generate_lang_bindtests (
9640     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9641   );
9642
9643   pr "print \"EOF\\n\"\n"
9644
9645 and generate_python_bindtests () =
9646   generate_header HashStyle GPLv2;
9647
9648   pr "\
9649 import guestfs
9650
9651 g = guestfs.GuestFS ()
9652 ";
9653
9654   let mkargs args =
9655     String.concat ", " (
9656       List.map (
9657         function
9658         | CallString s -> "\"" ^ s ^ "\""
9659         | CallOptString None -> "None"
9660         | CallOptString (Some s) -> sprintf "\"%s\"" s
9661         | CallStringList xs ->
9662             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9663         | CallInt i -> string_of_int i
9664         | CallInt64 i -> Int64.to_string i
9665         | CallBool b -> if b then "1" else "0"
9666       ) args
9667     )
9668   in
9669
9670   generate_lang_bindtests (
9671     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9672   );
9673
9674   pr "print \"EOF\"\n"
9675
9676 and generate_ruby_bindtests () =
9677   generate_header HashStyle GPLv2;
9678
9679   pr "\
9680 require 'guestfs'
9681
9682 g = Guestfs::create()
9683 ";
9684
9685   let mkargs args =
9686     String.concat ", " (
9687       List.map (
9688         function
9689         | CallString s -> "\"" ^ s ^ "\""
9690         | CallOptString None -> "nil"
9691         | CallOptString (Some s) -> sprintf "\"%s\"" s
9692         | CallStringList xs ->
9693             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9694         | CallInt i -> string_of_int i
9695         | CallInt64 i -> Int64.to_string i
9696         | CallBool b -> string_of_bool b
9697       ) args
9698     )
9699   in
9700
9701   generate_lang_bindtests (
9702     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9703   );
9704
9705   pr "print \"EOF\\n\"\n"
9706
9707 and generate_java_bindtests () =
9708   generate_header CStyle GPLv2;
9709
9710   pr "\
9711 import com.redhat.et.libguestfs.*;
9712
9713 public class Bindtests {
9714     public static void main (String[] argv)
9715     {
9716         try {
9717             GuestFS g = new GuestFS ();
9718 ";
9719
9720   let mkargs args =
9721     String.concat ", " (
9722       List.map (
9723         function
9724         | CallString s -> "\"" ^ s ^ "\""
9725         | CallOptString None -> "null"
9726         | CallOptString (Some s) -> sprintf "\"%s\"" s
9727         | CallStringList xs ->
9728             "new String[]{" ^
9729               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9730         | CallInt i -> string_of_int i
9731         | CallInt64 i -> Int64.to_string i
9732         | CallBool b -> string_of_bool b
9733       ) args
9734     )
9735   in
9736
9737   generate_lang_bindtests (
9738     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9739   );
9740
9741   pr "
9742             System.out.println (\"EOF\");
9743         }
9744         catch (Exception exn) {
9745             System.err.println (exn);
9746             System.exit (1);
9747         }
9748     }
9749 }
9750 "
9751
9752 and generate_haskell_bindtests () =
9753   generate_header HaskellStyle GPLv2;
9754
9755   pr "\
9756 module Bindtests where
9757 import qualified Guestfs
9758
9759 main = do
9760   g <- Guestfs.create
9761 ";
9762
9763   let mkargs args =
9764     String.concat " " (
9765       List.map (
9766         function
9767         | CallString s -> "\"" ^ s ^ "\""
9768         | CallOptString None -> "Nothing"
9769         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9770         | CallStringList xs ->
9771             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9772         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9773         | CallInt i -> string_of_int i
9774         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
9775         | CallInt64 i -> Int64.to_string i
9776         | CallBool true -> "True"
9777         | CallBool false -> "False"
9778       ) args
9779     )
9780   in
9781
9782   generate_lang_bindtests (
9783     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9784   );
9785
9786   pr "  putStrLn \"EOF\"\n"
9787
9788 (* Language-independent bindings tests - we do it this way to
9789  * ensure there is parity in testing bindings across all languages.
9790  *)
9791 and generate_lang_bindtests call =
9792   call "test0" [CallString "abc"; CallOptString (Some "def");
9793                 CallStringList []; CallBool false;
9794                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9795   call "test0" [CallString "abc"; CallOptString None;
9796                 CallStringList []; CallBool false;
9797                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9798   call "test0" [CallString ""; CallOptString (Some "def");
9799                 CallStringList []; CallBool false;
9800                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9801   call "test0" [CallString ""; CallOptString (Some "");
9802                 CallStringList []; CallBool false;
9803                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9804   call "test0" [CallString "abc"; CallOptString (Some "def");
9805                 CallStringList ["1"]; CallBool false;
9806                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9807   call "test0" [CallString "abc"; CallOptString (Some "def");
9808                 CallStringList ["1"; "2"]; CallBool false;
9809                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9810   call "test0" [CallString "abc"; CallOptString (Some "def");
9811                 CallStringList ["1"]; CallBool true;
9812                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
9813   call "test0" [CallString "abc"; CallOptString (Some "def");
9814                 CallStringList ["1"]; CallBool false;
9815                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
9816   call "test0" [CallString "abc"; CallOptString (Some "def");
9817                 CallStringList ["1"]; CallBool false;
9818                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
9819   call "test0" [CallString "abc"; CallOptString (Some "def");
9820                 CallStringList ["1"]; CallBool false;
9821                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
9822   call "test0" [CallString "abc"; CallOptString (Some "def");
9823                 CallStringList ["1"]; CallBool false;
9824                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
9825   call "test0" [CallString "abc"; CallOptString (Some "def");
9826                 CallStringList ["1"]; CallBool false;
9827                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
9828   call "test0" [CallString "abc"; CallOptString (Some "def");
9829                 CallStringList ["1"]; CallBool false;
9830                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
9831
9832 (* XXX Add here tests of the return and error functions. *)
9833
9834 (* This is used to generate the src/MAX_PROC_NR file which
9835  * contains the maximum procedure number, a surrogate for the
9836  * ABI version number.  See src/Makefile.am for the details.
9837  *)
9838 and generate_max_proc_nr () =
9839   let proc_nrs = List.map (
9840     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9841   ) daemon_functions in
9842
9843   let max_proc_nr = List.fold_left max 0 proc_nrs in
9844
9845   pr "%d\n" max_proc_nr
9846
9847 let output_to filename =
9848   let filename_new = filename ^ ".new" in
9849   chan := open_out filename_new;
9850   let close () =
9851     close_out !chan;
9852     chan := stdout;
9853
9854     (* Is the new file different from the current file? *)
9855     if Sys.file_exists filename && files_equal filename filename_new then
9856       Unix.unlink filename_new          (* same, so skip it *)
9857     else (
9858       (* different, overwrite old one *)
9859       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9860       Unix.rename filename_new filename;
9861       Unix.chmod filename 0o444;
9862       printf "written %s\n%!" filename;
9863     )
9864   in
9865   close
9866
9867 (* Main program. *)
9868 let () =
9869   check_functions ();
9870
9871   if not (Sys.file_exists "HACKING") then (
9872     eprintf "\
9873 You are probably running this from the wrong directory.
9874 Run it from the top source directory using the command
9875   src/generator.ml
9876 ";
9877     exit 1
9878   );
9879
9880   let close = output_to "src/guestfs_protocol.x" in
9881   generate_xdr ();
9882   close ();
9883
9884   let close = output_to "src/guestfs-structs.h" in
9885   generate_structs_h ();
9886   close ();
9887
9888   let close = output_to "src/guestfs-actions.h" in
9889   generate_actions_h ();
9890   close ();
9891
9892   let close = output_to "src/guestfs-internal-actions.h" in
9893   generate_internal_actions_h ();
9894   close ();
9895
9896   let close = output_to "src/guestfs-actions.c" in
9897   generate_client_actions ();
9898   close ();
9899
9900   let close = output_to "daemon/actions.h" in
9901   generate_daemon_actions_h ();
9902   close ();
9903
9904   let close = output_to "daemon/stubs.c" in
9905   generate_daemon_actions ();
9906   close ();
9907
9908   let close = output_to "daemon/names.c" in
9909   generate_daemon_names ();
9910   close ();
9911
9912   let close = output_to "capitests/tests.c" in
9913   generate_tests ();
9914   close ();
9915
9916   let close = output_to "src/guestfs-bindtests.c" in
9917   generate_bindtests ();
9918   close ();
9919
9920   let close = output_to "fish/cmds.c" in
9921   generate_fish_cmds ();
9922   close ();
9923
9924   let close = output_to "fish/completion.c" in
9925   generate_fish_completion ();
9926   close ();
9927
9928   let close = output_to "guestfs-structs.pod" in
9929   generate_structs_pod ();
9930   close ();
9931
9932   let close = output_to "guestfs-actions.pod" in
9933   generate_actions_pod ();
9934   close ();
9935
9936   let close = output_to "guestfish-actions.pod" in
9937   generate_fish_actions_pod ();
9938   close ();
9939
9940   let close = output_to "ocaml/guestfs.mli" in
9941   generate_ocaml_mli ();
9942   close ();
9943
9944   let close = output_to "ocaml/guestfs.ml" in
9945   generate_ocaml_ml ();
9946   close ();
9947
9948   let close = output_to "ocaml/guestfs_c_actions.c" in
9949   generate_ocaml_c ();
9950   close ();
9951
9952   let close = output_to "ocaml/bindtests.ml" in
9953   generate_ocaml_bindtests ();
9954   close ();
9955
9956   let close = output_to "perl/Guestfs.xs" in
9957   generate_perl_xs ();
9958   close ();
9959
9960   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9961   generate_perl_pm ();
9962   close ();
9963
9964   let close = output_to "perl/bindtests.pl" in
9965   generate_perl_bindtests ();
9966   close ();
9967
9968   let close = output_to "python/guestfs-py.c" in
9969   generate_python_c ();
9970   close ();
9971
9972   let close = output_to "python/guestfs.py" in
9973   generate_python_py ();
9974   close ();
9975
9976   let close = output_to "python/bindtests.py" in
9977   generate_python_bindtests ();
9978   close ();
9979
9980   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9981   generate_ruby_c ();
9982   close ();
9983
9984   let close = output_to "ruby/bindtests.rb" in
9985   generate_ruby_bindtests ();
9986   close ();
9987
9988   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9989   generate_java_java ();
9990   close ();
9991
9992   List.iter (
9993     fun (typ, jtyp) ->
9994       let cols = cols_of_struct typ in
9995       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9996       let close = output_to filename in
9997       generate_java_struct jtyp cols;
9998       close ();
9999   ) java_structs;
10000
10001   let close = output_to "java/Makefile.inc" in
10002   generate_java_makefile_inc ();
10003   close ();
10004
10005   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10006   generate_java_c ();
10007   close ();
10008
10009   let close = output_to "java/Bindtests.java" in
10010   generate_java_bindtests ();
10011   close ();
10012
10013   let close = output_to "haskell/Guestfs.hs" in
10014   generate_haskell_hs ();
10015   close ();
10016
10017   let close = output_to "haskell/Bindtests.hs" in
10018   generate_haskell_bindtests ();
10019   close ();
10020
10021   let close = output_to "src/MAX_PROC_NR" in
10022   generate_max_proc_nr ();
10023   close ();
10024
10025   (* Always generate this file last, and unconditionally.  It's used
10026    * by the Makefile to know when we must re-run the generator.
10027    *)
10028   let chan = open_out "src/stamp-generator" in
10029   fprintf chan "1\n";
10030   close_out chan