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