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