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