Don't stash strings in the handle.
[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
28  * all the output files.
29  *
30  * IMPORTANT: This script should NOT print any warnings.  If it prints
31  * warnings, you should treat them as errors.
32  * [Need to add -warn-error to ocaml command line]
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     (* "RInt" as a return value means an int which is -1 for error
47      * or any value >= 0 on success.  Only use this for smallish
48      * positive ints (0 <= i < 2^30).
49      *)
50   | RInt of string
51     (* "RInt64" is the same as RInt, but is guaranteed to be able
52      * to return a full 64 bit value, _except_ that -1 means error
53      * (so -1 cannot be a valid, non-error return value).
54      *)
55   | RInt64 of string
56     (* "RBool" is a bool return value which can be true/false or
57      * -1 for error.
58      *)
59   | RBool of string
60     (* "RConstString" is a string that refers to a constant value.
61      * Try to avoid using this.  In particular you cannot use this
62      * for values returned from the daemon, because there is no
63      * thread-safe way to return them in the C API.
64      *)
65   | RConstString of string
66     (* "RString" and "RStringList" are caller-frees. *)
67   | RString of string
68   | RStringList of string
69     (* Some limited tuples are possible: *)
70   | RIntBool of string * string
71     (* LVM PVs, VGs and LVs. *)
72   | RPVList of string
73   | RVGList of string
74   | RLVList of string
75     (* Stat buffers. *)
76   | RStat of string
77   | RStatVFS of string
78     (* Key-value pairs of untyped strings.  Turns into a hashtable or
79      * dictionary in languages which support it.  DON'T use this as a
80      * general "bucket" for results.  Prefer a stronger typed return
81      * value if one is available, or write a custom struct.  Don't use
82      * this if the list could potentially be very long, since it is
83      * inefficient.  Keys should be unique.  NULLs are not permitted.
84      *)
85   | RHashtable of string
86
87 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
88
89     (* Note in future we should allow a "variable args" parameter as
90      * the final parameter, to allow commands like
91      *   chmod mode file [file(s)...]
92      * This is not implemented yet, but many commands (such as chmod)
93      * are currently defined with the argument order keeping this future
94      * possibility in mind.
95      *)
96 and argt =
97   | String of string    (* const char *name, cannot be NULL *)
98   | OptString of string (* const char *name, may be NULL *)
99   | StringList of string(* list of strings (each string cannot be NULL) *)
100   | Bool of string      (* boolean *)
101   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
102     (* These are treated as filenames (simple string parameters) in
103      * the C API and bindings.  But in the RPC protocol, we transfer
104      * the actual file content up to or down from the daemon.
105      * FileIn: local machine -> daemon (in request)
106      * FileOut: daemon -> local machine (in reply)
107      * In guestfish (only), the special name "-" means read from
108      * stdin or write to stdout.
109      *)
110   | FileIn of string
111   | FileOut of string
112
113 type flags =
114   | ProtocolLimitWarning  (* display warning about protocol size limits *)
115   | DangerWillRobinson    (* flags particularly dangerous commands *)
116   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
117   | FishAction of string  (* call this function in guestfish *)
118   | NotInFish             (* do not export via guestfish *)
119
120 let protocol_limit_warning =
121   "Because of the message protocol, there is a transfer limit 
122 of somewhere between 2MB and 4MB.  To transfer large files you should use
123 FTP."
124
125 let danger_will_robinson =
126   "B<This command is dangerous.  Without careful use you
127 can easily destroy all your data>."
128
129 (* You can supply zero or as many tests as you want per API call.
130  *
131  * Note that the test environment has 3 block devices, of size 500MB,
132  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc).
133  * Note for partitioning purposes, the 500MB device has 63 cylinders.
134  *
135  * To be able to run the tests in a reasonable amount of time,
136  * the virtual machine and block devices are reused between tests.
137  * So don't try testing kill_subprocess :-x
138  *
139  * Between each test we blockdev-setrw, umount-all, lvm-remove-all
140  * (except InitNone).
141  *
142  * If the appliance is running an older Linux kernel (eg. RHEL 5) then
143  * devices are named /dev/hda etc.  To cope with this, the test suite
144  * adds some hairly logic to detect this case, and then automagically
145  * replaces all strings which match "/dev/sd.*" with "/dev/hd.*".
146  * When writing test cases you shouldn't have to worry about this
147  * difference.
148  *
149  * Don't assume anything about the previous contents of the block
150  * devices.  Use 'Init*' to create some initial scenarios.
151  *)
152 type tests = (test_init * test) list
153 and test =
154     (* Run the command sequence and just expect nothing to fail. *)
155   | TestRun of seq
156     (* Run the command sequence and expect the output of the final
157      * command to be the string.
158      *)
159   | TestOutput of seq * string
160     (* Run the command sequence and expect the output of the final
161      * command to be the list of strings.
162      *)
163   | TestOutputList of seq * string list
164     (* Run the command sequence and expect the output of the final
165      * command to be the integer.
166      *)
167   | TestOutputInt of seq * int
168     (* Run the command sequence and expect the output of the final
169      * command to be a true value (!= 0 or != NULL).
170      *)
171   | TestOutputTrue of seq
172     (* Run the command sequence and expect the output of the final
173      * command to be a false value (== 0 or == NULL, but not an error).
174      *)
175   | TestOutputFalse of seq
176     (* Run the command sequence and expect the output of the final
177      * command to be a list of the given length (but don't care about
178      * content).
179      *)
180   | TestOutputLength of seq * int
181     (* Run the command sequence and expect the output of the final
182      * command to be a structure.
183      *)
184   | TestOutputStruct of seq * test_field_compare list
185     (* Run the command sequence and expect the final command (only)
186      * to fail.
187      *)
188   | TestLastFail of seq
189
190 and test_field_compare =
191   | CompareWithInt of string * int
192   | CompareWithString of string * string
193   | CompareFieldsIntEq of string * string
194   | CompareFieldsStrEq of string * string
195
196 (* Some initial scenarios for testing. *)
197 and test_init =
198     (* Do nothing, block devices could contain random stuff including
199      * LVM PVs, and some filesystems might be mounted.  This is usually
200      * a bad idea.
201      *)
202   | InitNone
203     (* Block devices are empty and no filesystems are mounted. *)
204   | InitEmpty
205     (* /dev/sda contains a single partition /dev/sda1, which is formatted
206      * as ext2, empty [except for lost+found] and mounted on /.
207      * /dev/sdb and /dev/sdc may have random content.
208      * No LVM.
209      *)
210   | InitBasicFS
211     (* /dev/sda:
212      *   /dev/sda1 (is a PV):
213      *     /dev/VG/LV (size 8MB):
214      *       formatted as ext2, empty [except for lost+found], mounted on /
215      * /dev/sdb and /dev/sdc may have random content.
216      *)
217   | InitBasicFSonLVM
218
219 (* Sequence of commands for testing. *)
220 and seq = cmd list
221 and cmd = string list
222
223 (* Note about long descriptions: When referring to another
224  * action, use the format C<guestfs_other> (ie. the full name of
225  * the C function).  This will be replaced as appropriate in other
226  * language bindings.
227  *
228  * Apart from that, long descriptions are just perldoc paragraphs.
229  *)
230
231 let non_daemon_functions = [
232   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
233    [],
234    "launch the qemu subprocess",
235    "\
236 Internally libguestfs is implemented by running a virtual machine
237 using L<qemu(1)>.
238
239 You should call this after configuring the handle
240 (eg. adding drives) but before performing any actions.");
241
242   ("wait_ready", (RErr, []), -1, [NotInFish],
243    [],
244    "wait until the qemu subprocess launches",
245    "\
246 Internally libguestfs is implemented by running a virtual machine
247 using L<qemu(1)>.
248
249 You should call this after C<guestfs_launch> to wait for the launch
250 to complete.");
251
252   ("kill_subprocess", (RErr, []), -1, [],
253    [],
254    "kill the qemu subprocess",
255    "\
256 This kills the qemu subprocess.  You should never need to call this.");
257
258   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
259    [],
260    "add an image to examine or modify",
261    "\
262 This function adds a virtual machine disk image C<filename> to the
263 guest.  The first time you call this function, the disk appears as IDE
264 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
265 so on.
266
267 You don't necessarily need to be root when using libguestfs.  However
268 you obviously do need sufficient permissions to access the filename
269 for whatever operations you want to perform (ie. read access if you
270 just want to read the image or write access if you want to modify the
271 image).
272
273 This is equivalent to the qemu parameter C<-drive file=filename>.");
274
275   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
276    [],
277    "add a CD-ROM disk image to examine",
278    "\
279 This function adds a virtual CD-ROM disk image to the guest.
280
281 This is equivalent to the qemu parameter C<-cdrom filename>.");
282
283   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
284    [],
285    "add qemu parameters",
286    "\
287 This can be used to add arbitrary qemu command line parameters
288 of the form C<-param value>.  Actually it's not quite arbitrary - we
289 prevent you from setting some parameters which would interfere with
290 parameters that we use.
291
292 The first character of C<param> string must be a C<-> (dash).
293
294 C<value> can be NULL.");
295
296   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
297    [],
298    "set the qemu binary",
299    "\
300 Set the qemu binary that we will use.
301
302 The default is chosen when the library was compiled by the
303 configure script.
304
305 You can also override this by setting the C<LIBGUESTFS_QEMU>
306 environment variable.
307
308 Setting C<qemu> to C<NULL> restores the default qemu binary.");
309
310   ("get_qemu", (RConstString "qemu", []), -1, [],
311    [],
312    "get the qemu binary",
313    "\
314 Return the current qemu binary.
315
316 This is always non-NULL.  If it wasn't set already, then this will
317 return the default qemu binary name.");
318
319   ("set_path", (RErr, [String "path"]), -1, [FishAlias "path"],
320    [],
321    "set the search path",
322    "\
323 Set the path that libguestfs searches for kernel and initrd.img.
324
325 The default is C<$libdir/guestfs> unless overridden by setting
326 C<LIBGUESTFS_PATH> environment variable.
327
328 Setting C<path> to C<NULL> restores the default path.");
329
330   ("get_path", (RConstString "path", []), -1, [],
331    [],
332    "get the search path",
333    "\
334 Return the current search path.
335
336 This is always non-NULL.  If it wasn't set already, then this will
337 return the default path.");
338
339   ("set_append", (RErr, [String "append"]), -1, [FishAlias "append"],
340    [],
341    "add options to kernel command line",
342    "\
343 This function is used to add additional options to the
344 guest kernel command line.
345
346 The default is C<NULL> unless overridden by setting
347 C<LIBGUESTFS_APPEND> environment variable.
348
349 Setting C<append> to C<NULL> means I<no> additional options
350 are passed (libguestfs always adds a few of its own).");
351
352   ("get_append", (RConstString "append", []), -1, [],
353    [],
354    "get the additional kernel options",
355    "\
356 Return the additional kernel options which are added to the
357 guest kernel command line.
358
359 If C<NULL> then no options are added.");
360
361   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
362    [],
363    "set autosync mode",
364    "\
365 If C<autosync> is true, this enables autosync.  Libguestfs will make a
366 best effort attempt to run C<guestfs_umount_all> followed by
367 C<guestfs_sync> when the handle is closed
368 (also if the program exits without closing handles).
369
370 This is disabled by default (except in guestfish where it is
371 enabled by default).");
372
373   ("get_autosync", (RBool "autosync", []), -1, [],
374    [],
375    "get autosync mode",
376    "\
377 Get the autosync flag.");
378
379   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
380    [],
381    "set verbose mode",
382    "\
383 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
384
385 Verbose messages are disabled unless the environment variable
386 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
387
388   ("get_verbose", (RBool "verbose", []), -1, [],
389    [],
390    "get verbose mode",
391    "\
392 This returns the verbose messages flag.");
393
394   ("is_ready", (RBool "ready", []), -1, [],
395    [],
396    "is ready to accept commands",
397    "\
398 This returns true iff this handle is ready to accept commands
399 (in the C<READY> state).
400
401 For more information on states, see L<guestfs(3)>.");
402
403   ("is_config", (RBool "config", []), -1, [],
404    [],
405    "is in configuration state",
406    "\
407 This returns true iff this handle is being configured
408 (in the C<CONFIG> state).
409
410 For more information on states, see L<guestfs(3)>.");
411
412   ("is_launching", (RBool "launching", []), -1, [],
413    [],
414    "is launching subprocess",
415    "\
416 This returns true iff this handle is launching the subprocess
417 (in the C<LAUNCHING> state).
418
419 For more information on states, see L<guestfs(3)>.");
420
421   ("is_busy", (RBool "busy", []), -1, [],
422    [],
423    "is busy processing a command",
424    "\
425 This returns true iff this handle is busy processing a command
426 (in the C<BUSY> state).
427
428 For more information on states, see L<guestfs(3)>.");
429
430   ("get_state", (RInt "state", []), -1, [],
431    [],
432    "get the current state",
433    "\
434 This returns the current state as an opaque integer.  This is
435 only useful for printing debug and internal error messages.
436
437 For more information on states, see L<guestfs(3)>.");
438
439   ("set_busy", (RErr, []), -1, [NotInFish],
440    [],
441    "set state to busy",
442    "\
443 This sets the state to C<BUSY>.  This is only used when implementing
444 actions using the low-level API.
445
446 For more information on states, see L<guestfs(3)>.");
447
448   ("set_ready", (RErr, []), -1, [NotInFish],
449    [],
450    "set state to ready",
451    "\
452 This sets the state to C<READY>.  This is only used when implementing
453 actions using the low-level API.
454
455 For more information on states, see L<guestfs(3)>.");
456
457   ("end_busy", (RErr, []), -1, [NotInFish],
458    [],
459    "leave the busy state",
460    "\
461 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
462 state as is.  This is only used when implementing
463 actions using the low-level API.
464
465 For more information on states, see L<guestfs(3)>.");
466
467 ]
468
469 let daemon_functions = [
470   ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
471    [InitEmpty, TestOutput (
472       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
473        ["mkfs"; "ext2"; "/dev/sda1"];
474        ["mount"; "/dev/sda1"; "/"];
475        ["write_file"; "/new"; "new file contents"; "0"];
476        ["cat"; "/new"]], "new file contents")],
477    "mount a guest disk at a position in the filesystem",
478    "\
479 Mount a guest disk at a position in the filesystem.  Block devices
480 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
481 the guest.  If those block devices contain partitions, they will have
482 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
483 names can be used.
484
485 The rules are the same as for L<mount(2)>:  A filesystem must
486 first be mounted on C</> before others can be mounted.  Other
487 filesystems can only be mounted on directories which already
488 exist.
489
490 The mounted filesystem is writable, if we have sufficient permissions
491 on the underlying device.
492
493 The filesystem options C<sync> and C<noatime> are set with this
494 call, in order to improve reliability.");
495
496   ("sync", (RErr, []), 2, [],
497    [ InitEmpty, TestRun [["sync"]]],
498    "sync disks, writes are flushed through to the disk image",
499    "\
500 This syncs the disk, so that any writes are flushed through to the
501 underlying disk image.
502
503 You should always call this if you have modified a disk image, before
504 closing the handle.");
505
506   ("touch", (RErr, [String "path"]), 3, [],
507    [InitBasicFS, TestOutputTrue (
508       [["touch"; "/new"];
509        ["exists"; "/new"]])],
510    "update file timestamps or create a new file",
511    "\
512 Touch acts like the L<touch(1)> command.  It can be used to
513 update the timestamps on a file, or, if the file does not exist,
514 to create a new zero-length file.");
515
516   ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
517    [InitBasicFS, TestOutput (
518       [["write_file"; "/new"; "new file contents"; "0"];
519        ["cat"; "/new"]], "new file contents")],
520    "list the contents of a file",
521    "\
522 Return the contents of the file named C<path>.
523
524 Note that this function cannot correctly handle binary files
525 (specifically, files containing C<\\0> character which is treated
526 as end of string).  For those you need to use the C<guestfs_download>
527 function which has a more complex interface.");
528
529   ("ll", (RString "listing", [String "directory"]), 5, [],
530    [], (* XXX Tricky to test because it depends on the exact format
531         * of the 'ls -l' command, which changes between F10 and F11.
532         *)
533    "list the files in a directory (long format)",
534    "\
535 List the files in C<directory> (relative to the root directory,
536 there is no cwd) in the format of 'ls -la'.
537
538 This command is mostly useful for interactive sessions.  It
539 is I<not> intended that you try to parse the output string.");
540
541   ("ls", (RStringList "listing", [String "directory"]), 6, [],
542    [InitBasicFS, TestOutputList (
543       [["touch"; "/new"];
544        ["touch"; "/newer"];
545        ["touch"; "/newest"];
546        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
547    "list the files in a directory",
548    "\
549 List the files in C<directory> (relative to the root directory,
550 there is no cwd).  The '.' and '..' entries are not returned, but
551 hidden files are shown.
552
553 This command is mostly useful for interactive sessions.  Programs
554 should probably use C<guestfs_readdir> instead.");
555
556   ("list_devices", (RStringList "devices", []), 7, [],
557    [InitEmpty, TestOutputList (
558       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"])],
559    "list the block devices",
560    "\
561 List all the block devices.
562
563 The full block device names are returned, eg. C</dev/sda>");
564
565   ("list_partitions", (RStringList "partitions", []), 8, [],
566    [InitBasicFS, TestOutputList (
567       [["list_partitions"]], ["/dev/sda1"]);
568     InitEmpty, TestOutputList (
569       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
570        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
571    "list the partitions",
572    "\
573 List all the partitions detected on all block devices.
574
575 The full partition device names are returned, eg. C</dev/sda1>
576
577 This does not return logical volumes.  For that you will need to
578 call C<guestfs_lvs>.");
579
580   ("pvs", (RStringList "physvols", []), 9, [],
581    [InitBasicFSonLVM, TestOutputList (
582       [["pvs"]], ["/dev/sda1"]);
583     InitEmpty, TestOutputList (
584       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
585        ["pvcreate"; "/dev/sda1"];
586        ["pvcreate"; "/dev/sda2"];
587        ["pvcreate"; "/dev/sda3"];
588        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
589    "list the LVM physical volumes (PVs)",
590    "\
591 List all the physical volumes detected.  This is the equivalent
592 of the L<pvs(8)> command.
593
594 This returns a list of just the device names that contain
595 PVs (eg. C</dev/sda2>).
596
597 See also C<guestfs_pvs_full>.");
598
599   ("vgs", (RStringList "volgroups", []), 10, [],
600    [InitBasicFSonLVM, TestOutputList (
601       [["vgs"]], ["VG"]);
602     InitEmpty, TestOutputList (
603       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
604        ["pvcreate"; "/dev/sda1"];
605        ["pvcreate"; "/dev/sda2"];
606        ["pvcreate"; "/dev/sda3"];
607        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
608        ["vgcreate"; "VG2"; "/dev/sda3"];
609        ["vgs"]], ["VG1"; "VG2"])],
610    "list the LVM volume groups (VGs)",
611    "\
612 List all the volumes groups detected.  This is the equivalent
613 of the L<vgs(8)> command.
614
615 This returns a list of just the volume group names that were
616 detected (eg. C<VolGroup00>).
617
618 See also C<guestfs_vgs_full>.");
619
620   ("lvs", (RStringList "logvols", []), 11, [],
621    [InitBasicFSonLVM, TestOutputList (
622       [["lvs"]], ["/dev/VG/LV"]);
623     InitEmpty, TestOutputList (
624       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
625        ["pvcreate"; "/dev/sda1"];
626        ["pvcreate"; "/dev/sda2"];
627        ["pvcreate"; "/dev/sda3"];
628        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
629        ["vgcreate"; "VG2"; "/dev/sda3"];
630        ["lvcreate"; "LV1"; "VG1"; "50"];
631        ["lvcreate"; "LV2"; "VG1"; "50"];
632        ["lvcreate"; "LV3"; "VG2"; "50"];
633        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
634    "list the LVM logical volumes (LVs)",
635    "\
636 List all the logical volumes detected.  This is the equivalent
637 of the L<lvs(8)> command.
638
639 This returns a list of the logical volume device names
640 (eg. C</dev/VolGroup00/LogVol00>).
641
642 See also C<guestfs_lvs_full>.");
643
644   ("pvs_full", (RPVList "physvols", []), 12, [],
645    [], (* XXX how to test? *)
646    "list the LVM physical volumes (PVs)",
647    "\
648 List all the physical volumes detected.  This is the equivalent
649 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
650
651   ("vgs_full", (RVGList "volgroups", []), 13, [],
652    [], (* XXX how to test? *)
653    "list the LVM volume groups (VGs)",
654    "\
655 List all the volumes groups detected.  This is the equivalent
656 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
657
658   ("lvs_full", (RLVList "logvols", []), 14, [],
659    [], (* XXX how to test? *)
660    "list the LVM logical volumes (LVs)",
661    "\
662 List all the logical volumes detected.  This is the equivalent
663 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
664
665   ("read_lines", (RStringList "lines", [String "path"]), 15, [],
666    [InitBasicFS, TestOutputList (
667       [["write_file"; "/new"; "line1\r\nline2\nline3"; "0"];
668        ["read_lines"; "/new"]], ["line1"; "line2"; "line3"]);
669     InitBasicFS, TestOutputList (
670       [["write_file"; "/new"; ""; "0"];
671        ["read_lines"; "/new"]], [])],
672    "read file as lines",
673    "\
674 Return the contents of the file named C<path>.
675
676 The file contents are returned as a list of lines.  Trailing
677 C<LF> and C<CRLF> character sequences are I<not> returned.
678
679 Note that this function cannot correctly handle binary files
680 (specifically, files containing C<\\0> character which is treated
681 as end of line).  For those you need to use the C<guestfs_read_file>
682 function which has a more complex interface.");
683
684   ("aug_init", (RErr, [String "root"; Int "flags"]), 16, [],
685    [], (* XXX Augeas code needs tests. *)
686    "create a new Augeas handle",
687    "\
688 Create a new Augeas handle for editing configuration files.
689 If there was any previous Augeas handle associated with this
690 guestfs session, then it is closed.
691
692 You must call this before using any other C<guestfs_aug_*>
693 commands.
694
695 C<root> is the filesystem root.  C<root> must not be NULL,
696 use C</> instead.
697
698 The flags are the same as the flags defined in
699 E<lt>augeas.hE<gt>, the logical I<or> of the following
700 integers:
701
702 =over 4
703
704 =item C<AUG_SAVE_BACKUP> = 1
705
706 Keep the original file with a C<.augsave> extension.
707
708 =item C<AUG_SAVE_NEWFILE> = 2
709
710 Save changes into a file with extension C<.augnew>, and
711 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
712
713 =item C<AUG_TYPE_CHECK> = 4
714
715 Typecheck lenses (can be expensive).
716
717 =item C<AUG_NO_STDINC> = 8
718
719 Do not use standard load path for modules.
720
721 =item C<AUG_SAVE_NOOP> = 16
722
723 Make save a no-op, just record what would have been changed.
724
725 =item C<AUG_NO_LOAD> = 32
726
727 Do not load the tree in C<guestfs_aug_init>.
728
729 =back
730
731 To close the handle, you can call C<guestfs_aug_close>.
732
733 To find out more about Augeas, see L<http://augeas.net/>.");
734
735   ("aug_close", (RErr, []), 26, [],
736    [], (* XXX Augeas code needs tests. *)
737    "close the current Augeas handle",
738    "\
739 Close the current Augeas handle and free up any resources
740 used by it.  After calling this, you have to call
741 C<guestfs_aug_init> again before you can use any other
742 Augeas functions.");
743
744   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
745    [], (* XXX Augeas code needs tests. *)
746    "define an Augeas variable",
747    "\
748 Defines an Augeas variable C<name> whose value is the result
749 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
750 undefined.
751
752 On success this returns the number of nodes in C<expr>, or
753 C<0> if C<expr> evaluates to something which is not a nodeset.");
754
755   ("aug_defnode", (RIntBool ("nrnodes", "created"), [String "name"; String "expr"; String "val"]), 18, [],
756    [], (* XXX Augeas code needs tests. *)
757    "define an Augeas node",
758    "\
759 Defines a variable C<name> whose value is the result of
760 evaluating C<expr>.
761
762 If C<expr> evaluates to an empty nodeset, a node is created,
763 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
764 C<name> will be the nodeset containing that single node.
765
766 On success this returns a pair containing the
767 number of nodes in the nodeset, and a boolean flag
768 if a node was created.");
769
770   ("aug_get", (RString "val", [String "path"]), 19, [],
771    [], (* XXX Augeas code needs tests. *)
772    "look up the value of an Augeas path",
773    "\
774 Look up the value associated with C<path>.  If C<path>
775 matches exactly one node, the C<value> is returned.");
776
777   ("aug_set", (RErr, [String "path"; String "val"]), 20, [],
778    [], (* XXX Augeas code needs tests. *)
779    "set Augeas path to value",
780    "\
781 Set the value associated with C<path> to C<value>.");
782
783   ("aug_insert", (RErr, [String "path"; String "label"; Bool "before"]), 21, [],
784    [], (* XXX Augeas code needs tests. *)
785    "insert a sibling Augeas node",
786    "\
787 Create a new sibling C<label> for C<path>, inserting it into
788 the tree before or after C<path> (depending on the boolean
789 flag C<before>).
790
791 C<path> must match exactly one existing node in the tree, and
792 C<label> must be a label, ie. not contain C</>, C<*> or end
793 with a bracketed index C<[N]>.");
794
795   ("aug_rm", (RInt "nrnodes", [String "path"]), 22, [],
796    [], (* XXX Augeas code needs tests. *)
797    "remove an Augeas path",
798    "\
799 Remove C<path> and all of its children.
800
801 On success this returns the number of entries which were removed.");
802
803   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
804    [], (* XXX Augeas code needs tests. *)
805    "move Augeas node",
806    "\
807 Move the node C<src> to C<dest>.  C<src> must match exactly
808 one node.  C<dest> is overwritten if it exists.");
809
810   ("aug_match", (RStringList "matches", [String "path"]), 24, [],
811    [], (* XXX Augeas code needs tests. *)
812    "return Augeas nodes which match path",
813    "\
814 Returns a list of paths which match the path expression C<path>.
815 The returned paths are sufficiently qualified so that they match
816 exactly one node in the current tree.");
817
818   ("aug_save", (RErr, []), 25, [],
819    [], (* XXX Augeas code needs tests. *)
820    "write all pending Augeas changes to disk",
821    "\
822 This writes all pending changes to disk.
823
824 The flags which were passed to C<guestfs_aug_init> affect exactly
825 how files are saved.");
826
827   ("aug_load", (RErr, []), 27, [],
828    [], (* XXX Augeas code needs tests. *)
829    "load files into the tree",
830    "\
831 Load files into the tree.
832
833 See C<aug_load> in the Augeas documentation for the full gory
834 details.");
835
836   ("aug_ls", (RStringList "matches", [String "path"]), 28, [],
837    [], (* XXX Augeas code needs tests. *)
838    "list Augeas nodes under a path",
839    "\
840 This is just a shortcut for listing C<guestfs_aug_match>
841 C<path/*> and sorting the resulting nodes into alphabetical order.");
842
843   ("rm", (RErr, [String "path"]), 29, [],
844    [InitBasicFS, TestRun
845       [["touch"; "/new"];
846        ["rm"; "/new"]];
847     InitBasicFS, TestLastFail
848       [["rm"; "/new"]];
849     InitBasicFS, TestLastFail
850       [["mkdir"; "/new"];
851        ["rm"; "/new"]]],
852    "remove a file",
853    "\
854 Remove the single file C<path>.");
855
856   ("rmdir", (RErr, [String "path"]), 30, [],
857    [InitBasicFS, TestRun
858       [["mkdir"; "/new"];
859        ["rmdir"; "/new"]];
860     InitBasicFS, TestLastFail
861       [["rmdir"; "/new"]];
862     InitBasicFS, TestLastFail
863       [["touch"; "/new"];
864        ["rmdir"; "/new"]]],
865    "remove a directory",
866    "\
867 Remove the single directory C<path>.");
868
869   ("rm_rf", (RErr, [String "path"]), 31, [],
870    [InitBasicFS, TestOutputFalse
871       [["mkdir"; "/new"];
872        ["mkdir"; "/new/foo"];
873        ["touch"; "/new/foo/bar"];
874        ["rm_rf"; "/new"];
875        ["exists"; "/new"]]],
876    "remove a file or directory recursively",
877    "\
878 Remove the file or directory C<path>, recursively removing the
879 contents if its a directory.  This is like the C<rm -rf> shell
880 command.");
881
882   ("mkdir", (RErr, [String "path"]), 32, [],
883    [InitBasicFS, TestOutputTrue
884       [["mkdir"; "/new"];
885        ["is_dir"; "/new"]];
886     InitBasicFS, TestLastFail
887       [["mkdir"; "/new/foo/bar"]]],
888    "create a directory",
889    "\
890 Create a directory named C<path>.");
891
892   ("mkdir_p", (RErr, [String "path"]), 33, [],
893    [InitBasicFS, TestOutputTrue
894       [["mkdir_p"; "/new/foo/bar"];
895        ["is_dir"; "/new/foo/bar"]];
896     InitBasicFS, TestOutputTrue
897       [["mkdir_p"; "/new/foo/bar"];
898        ["is_dir"; "/new/foo"]];
899     InitBasicFS, TestOutputTrue
900       [["mkdir_p"; "/new/foo/bar"];
901        ["is_dir"; "/new"]]],
902    "create a directory and parents",
903    "\
904 Create a directory named C<path>, creating any parent directories
905 as necessary.  This is like the C<mkdir -p> shell command.");
906
907   ("chmod", (RErr, [Int "mode"; String "path"]), 34, [],
908    [], (* XXX Need stat command to test *)
909    "change file mode",
910    "\
911 Change the mode (permissions) of C<path> to C<mode>.  Only
912 numeric modes are supported.");
913
914   ("chown", (RErr, [Int "owner"; Int "group"; String "path"]), 35, [],
915    [], (* XXX Need stat command to test *)
916    "change file owner and group",
917    "\
918 Change the file owner to C<owner> and group to C<group>.
919
920 Only numeric uid and gid are supported.  If you want to use
921 names, you will need to locate and parse the password file
922 yourself (Augeas support makes this relatively easy).");
923
924   ("exists", (RBool "existsflag", [String "path"]), 36, [],
925    [InitBasicFS, TestOutputTrue (
926       [["touch"; "/new"];
927        ["exists"; "/new"]]);
928     InitBasicFS, TestOutputTrue (
929       [["mkdir"; "/new"];
930        ["exists"; "/new"]])],
931    "test if file or directory exists",
932    "\
933 This returns C<true> if and only if there is a file, directory
934 (or anything) with the given C<path> name.
935
936 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
937
938   ("is_file", (RBool "fileflag", [String "path"]), 37, [],
939    [InitBasicFS, TestOutputTrue (
940       [["touch"; "/new"];
941        ["is_file"; "/new"]]);
942     InitBasicFS, TestOutputFalse (
943       [["mkdir"; "/new"];
944        ["is_file"; "/new"]])],
945    "test if file exists",
946    "\
947 This returns C<true> if and only if there is a file
948 with the given C<path> name.  Note that it returns false for
949 other objects like directories.
950
951 See also C<guestfs_stat>.");
952
953   ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
954    [InitBasicFS, TestOutputFalse (
955       [["touch"; "/new"];
956        ["is_dir"; "/new"]]);
957     InitBasicFS, TestOutputTrue (
958       [["mkdir"; "/new"];
959        ["is_dir"; "/new"]])],
960    "test if file exists",
961    "\
962 This returns C<true> if and only if there is a directory
963 with the given C<path> name.  Note that it returns false for
964 other objects like files.
965
966 See also C<guestfs_stat>.");
967
968   ("pvcreate", (RErr, [String "device"]), 39, [],
969    [InitEmpty, TestOutputList (
970       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
971        ["pvcreate"; "/dev/sda1"];
972        ["pvcreate"; "/dev/sda2"];
973        ["pvcreate"; "/dev/sda3"];
974        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
975    "create an LVM physical volume",
976    "\
977 This creates an LVM physical volume on the named C<device>,
978 where C<device> should usually be a partition name such
979 as C</dev/sda1>.");
980
981   ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
982    [InitEmpty, TestOutputList (
983       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
984        ["pvcreate"; "/dev/sda1"];
985        ["pvcreate"; "/dev/sda2"];
986        ["pvcreate"; "/dev/sda3"];
987        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
988        ["vgcreate"; "VG2"; "/dev/sda3"];
989        ["vgs"]], ["VG1"; "VG2"])],
990    "create an LVM volume group",
991    "\
992 This creates an LVM volume group called C<volgroup>
993 from the non-empty list of physical volumes C<physvols>.");
994
995   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
996    [InitEmpty, TestOutputList (
997       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
998        ["pvcreate"; "/dev/sda1"];
999        ["pvcreate"; "/dev/sda2"];
1000        ["pvcreate"; "/dev/sda3"];
1001        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1002        ["vgcreate"; "VG2"; "/dev/sda3"];
1003        ["lvcreate"; "LV1"; "VG1"; "50"];
1004        ["lvcreate"; "LV2"; "VG1"; "50"];
1005        ["lvcreate"; "LV3"; "VG2"; "50"];
1006        ["lvcreate"; "LV4"; "VG2"; "50"];
1007        ["lvcreate"; "LV5"; "VG2"; "50"];
1008        ["lvs"]],
1009       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1010        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1011    "create an LVM volume group",
1012    "\
1013 This creates an LVM volume group called C<logvol>
1014 on the volume group C<volgroup>, with C<size> megabytes.");
1015
1016   ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
1017    [InitEmpty, TestOutput (
1018       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1019        ["mkfs"; "ext2"; "/dev/sda1"];
1020        ["mount"; "/dev/sda1"; "/"];
1021        ["write_file"; "/new"; "new file contents"; "0"];
1022        ["cat"; "/new"]], "new file contents")],
1023    "make a filesystem",
1024    "\
1025 This creates a filesystem on C<device> (usually a partition
1026 or LVM logical volume).  The filesystem type is C<fstype>, for
1027 example C<ext3>.");
1028
1029   ("sfdisk", (RErr, [String "device";
1030                      Int "cyls"; Int "heads"; Int "sectors";
1031                      StringList "lines"]), 43, [DangerWillRobinson],
1032    [],
1033    "create partitions on a block device",
1034    "\
1035 This is a direct interface to the L<sfdisk(8)> program for creating
1036 partitions on block devices.
1037
1038 C<device> should be a block device, for example C</dev/sda>.
1039
1040 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1041 and sectors on the device, which are passed directly to sfdisk as
1042 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1043 of these, then the corresponding parameter is omitted.  Usually for
1044 'large' disks, you can just pass C<0> for these, but for small
1045 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1046 out the right geometry and you will need to tell it.
1047
1048 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1049 information refer to the L<sfdisk(8)> manpage.
1050
1051 To create a single partition occupying the whole disk, you would
1052 pass C<lines> as a single element list, when the single element being
1053 the string C<,> (comma).");
1054
1055   ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1056    [InitBasicFS, TestOutput (
1057       [["write_file"; "/new"; "new file contents"; "0"];
1058        ["cat"; "/new"]], "new file contents");
1059     InitBasicFS, TestOutput (
1060       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1061        ["cat"; "/new"]], "\nnew file contents\n");
1062     InitBasicFS, TestOutput (
1063       [["write_file"; "/new"; "\n\n"; "0"];
1064        ["cat"; "/new"]], "\n\n");
1065     InitBasicFS, TestOutput (
1066       [["write_file"; "/new"; ""; "0"];
1067        ["cat"; "/new"]], "");
1068     InitBasicFS, TestOutput (
1069       [["write_file"; "/new"; "\n\n\n"; "0"];
1070        ["cat"; "/new"]], "\n\n\n");
1071     InitBasicFS, TestOutput (
1072       [["write_file"; "/new"; "\n"; "0"];
1073        ["cat"; "/new"]], "\n")],
1074    "create a file",
1075    "\
1076 This call creates a file called C<path>.  The contents of the
1077 file is the string C<content> (which can contain any 8 bit data),
1078 with length C<size>.
1079
1080 As a special case, if C<size> is C<0>
1081 then the length is calculated using C<strlen> (so in this case
1082 the content cannot contain embedded ASCII NULs).
1083
1084 I<NB.> Owing to a bug, writing content containing ASCII NUL
1085 characters does I<not> work, even if the length is specified.
1086 We hope to resolve this bug in a future version.  In the meantime
1087 use C<guestfs_upload>.");
1088
1089   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1090    [InitEmpty, TestOutputList (
1091       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1092        ["mkfs"; "ext2"; "/dev/sda1"];
1093        ["mount"; "/dev/sda1"; "/"];
1094        ["mounts"]], ["/dev/sda1"]);
1095     InitEmpty, TestOutputList (
1096       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ","];
1097        ["mkfs"; "ext2"; "/dev/sda1"];
1098        ["mount"; "/dev/sda1"; "/"];
1099        ["umount"; "/"];
1100        ["mounts"]], [])],
1101    "unmount a filesystem",
1102    "\
1103 This unmounts the given filesystem.  The filesystem may be
1104 specified either by its mountpoint (path) or the device which
1105 contains the filesystem.");
1106
1107   ("mounts", (RStringList "devices", []), 46, [],
1108    [InitBasicFS, TestOutputList (
1109       [["mounts"]], ["/dev/sda1"])],
1110    "show mounted filesystems",
1111    "\
1112 This returns the list of currently mounted filesystems.  It returns
1113 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1114
1115 Some internal mounts are not shown.");
1116
1117   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1118    [InitBasicFS, TestOutputList (
1119       [["umount_all"];
1120        ["mounts"]], []);
1121     (* check that umount_all can unmount nested mounts correctly: *)
1122     InitEmpty, TestOutputList (
1123       [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"];
1124        ["mkfs"; "ext2"; "/dev/sda1"];
1125        ["mkfs"; "ext2"; "/dev/sda2"];
1126        ["mkfs"; "ext2"; "/dev/sda3"];
1127        ["mount"; "/dev/sda1"; "/"];
1128        ["mkdir"; "/mp1"];
1129        ["mount"; "/dev/sda2"; "/mp1"];
1130        ["mkdir"; "/mp1/mp2"];
1131        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1132        ["mkdir"; "/mp1/mp2/mp3"];
1133        ["umount_all"];
1134        ["mounts"]], [])],
1135    "unmount all filesystems",
1136    "\
1137 This unmounts all mounted filesystems.
1138
1139 Some internal mounts are not unmounted by this call.");
1140
1141   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1142    [],
1143    "remove all LVM LVs, VGs and PVs",
1144    "\
1145 This command removes all LVM logical volumes, volume groups
1146 and physical volumes.");
1147
1148   ("file", (RString "description", [String "path"]), 49, [],
1149    [InitBasicFS, TestOutput (
1150       [["touch"; "/new"];
1151        ["file"; "/new"]], "empty");
1152     InitBasicFS, TestOutput (
1153       [["write_file"; "/new"; "some content\n"; "0"];
1154        ["file"; "/new"]], "ASCII text");
1155     InitBasicFS, TestLastFail (
1156       [["file"; "/nofile"]])],
1157    "determine file type",
1158    "\
1159 This call uses the standard L<file(1)> command to determine
1160 the type or contents of the file.  This also works on devices,
1161 for example to find out whether a partition contains a filesystem.
1162
1163 The exact command which runs is C<file -bsL path>.  Note in
1164 particular that the filename is not prepended to the output
1165 (the C<-b> option).");
1166
1167   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1168    [InitBasicFS, TestOutput (
1169       [["upload"; "test-command"; "/test-command"];
1170        ["chmod"; "493"; "/test-command"];
1171        ["command"; "/test-command 1"]], "Result1");
1172     InitBasicFS, TestOutput (
1173       [["upload"; "test-command"; "/test-command"];
1174        ["chmod"; "493"; "/test-command"];
1175        ["command"; "/test-command 2"]], "Result2\n");
1176     InitBasicFS, TestOutput (
1177       [["upload"; "test-command"; "/test-command"];
1178        ["chmod"; "493"; "/test-command"];
1179        ["command"; "/test-command 3"]], "\nResult3");
1180     InitBasicFS, TestOutput (
1181       [["upload"; "test-command"; "/test-command"];
1182        ["chmod"; "493"; "/test-command"];
1183        ["command"; "/test-command 4"]], "\nResult4\n");
1184     InitBasicFS, TestOutput (
1185       [["upload"; "test-command"; "/test-command"];
1186        ["chmod"; "493"; "/test-command"];
1187        ["command"; "/test-command 5"]], "\nResult5\n\n");
1188     InitBasicFS, TestOutput (
1189       [["upload"; "test-command"; "/test-command"];
1190        ["chmod"; "493"; "/test-command"];
1191        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1192     InitBasicFS, TestOutput (
1193       [["upload"; "test-command"; "/test-command"];
1194        ["chmod"; "493"; "/test-command"];
1195        ["command"; "/test-command 7"]], "");
1196     InitBasicFS, TestOutput (
1197       [["upload"; "test-command"; "/test-command"];
1198        ["chmod"; "493"; "/test-command"];
1199        ["command"; "/test-command 8"]], "\n");
1200     InitBasicFS, TestOutput (
1201       [["upload"; "test-command"; "/test-command"];
1202        ["chmod"; "493"; "/test-command"];
1203        ["command"; "/test-command 9"]], "\n\n");
1204     InitBasicFS, TestOutput (
1205       [["upload"; "test-command"; "/test-command"];
1206        ["chmod"; "493"; "/test-command"];
1207        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1208     InitBasicFS, TestOutput (
1209       [["upload"; "test-command"; "/test-command"];
1210        ["chmod"; "493"; "/test-command"];
1211        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1212     InitBasicFS, TestLastFail (
1213       [["upload"; "test-command"; "/test-command"];
1214        ["chmod"; "493"; "/test-command"];
1215        ["command"; "/test-command"]])],
1216    "run a command from the guest filesystem",
1217    "\
1218 This call runs a command from the guest filesystem.  The
1219 filesystem must be mounted, and must contain a compatible
1220 operating system (ie. something Linux, with the same
1221 or compatible processor architecture).
1222
1223 The single parameter is an argv-style list of arguments.
1224 The first element is the name of the program to run.
1225 Subsequent elements are parameters.  The list must be
1226 non-empty (ie. must contain a program name).
1227
1228 The return value is anything printed to I<stdout> by
1229 the command.
1230
1231 If the command returns a non-zero exit status, then
1232 this function returns an error message.  The error message
1233 string is the content of I<stderr> from the command.
1234
1235 The C<$PATH> environment variable will contain at least
1236 C</usr/bin> and C</bin>.  If you require a program from
1237 another location, you should provide the full path in the
1238 first parameter.
1239
1240 Shared libraries and data files required by the program
1241 must be available on filesystems which are mounted in the
1242 correct places.  It is the caller's responsibility to ensure
1243 all filesystems that are needed are mounted at the right
1244 locations.");
1245
1246   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1247    [InitBasicFS, TestOutputList (
1248       [["upload"; "test-command"; "/test-command"];
1249        ["chmod"; "493"; "/test-command"];
1250        ["command_lines"; "/test-command 1"]], ["Result1"]);
1251     InitBasicFS, TestOutputList (
1252       [["upload"; "test-command"; "/test-command"];
1253        ["chmod"; "493"; "/test-command"];
1254        ["command_lines"; "/test-command 2"]], ["Result2"]);
1255     InitBasicFS, TestOutputList (
1256       [["upload"; "test-command"; "/test-command"];
1257        ["chmod"; "493"; "/test-command"];
1258        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1259     InitBasicFS, TestOutputList (
1260       [["upload"; "test-command"; "/test-command"];
1261        ["chmod"; "493"; "/test-command"];
1262        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1263     InitBasicFS, TestOutputList (
1264       [["upload"; "test-command"; "/test-command"];
1265        ["chmod"; "493"; "/test-command"];
1266        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1267     InitBasicFS, TestOutputList (
1268       [["upload"; "test-command"; "/test-command"];
1269        ["chmod"; "493"; "/test-command"];
1270        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1271     InitBasicFS, TestOutputList (
1272       [["upload"; "test-command"; "/test-command"];
1273        ["chmod"; "493"; "/test-command"];
1274        ["command_lines"; "/test-command 7"]], []);
1275     InitBasicFS, TestOutputList (
1276       [["upload"; "test-command"; "/test-command"];
1277        ["chmod"; "493"; "/test-command"];
1278        ["command_lines"; "/test-command 8"]], [""]);
1279     InitBasicFS, TestOutputList (
1280       [["upload"; "test-command"; "/test-command"];
1281        ["chmod"; "493"; "/test-command"];
1282        ["command_lines"; "/test-command 9"]], ["";""]);
1283     InitBasicFS, TestOutputList (
1284       [["upload"; "test-command"; "/test-command"];
1285        ["chmod"; "493"; "/test-command"];
1286        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1287     InitBasicFS, TestOutputList (
1288       [["upload"; "test-command"; "/test-command"];
1289        ["chmod"; "493"; "/test-command"];
1290        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1291    "run a command, returning lines",
1292    "\
1293 This is the same as C<guestfs_command>, but splits the
1294 result into a list of lines.");
1295
1296   ("stat", (RStat "statbuf", [String "path"]), 52, [],
1297    [InitBasicFS, TestOutputStruct (
1298       [["touch"; "/new"];
1299        ["stat"; "/new"]], [CompareWithInt ("size", 0)])],
1300    "get file information",
1301    "\
1302 Returns file information for the given C<path>.
1303
1304 This is the same as the C<stat(2)> system call.");
1305
1306   ("lstat", (RStat "statbuf", [String "path"]), 53, [],
1307    [InitBasicFS, TestOutputStruct (
1308       [["touch"; "/new"];
1309        ["lstat"; "/new"]], [CompareWithInt ("size", 0)])],
1310    "get file information for a symbolic link",
1311    "\
1312 Returns file information for the given C<path>.
1313
1314 This is the same as C<guestfs_stat> except that if C<path>
1315 is a symbolic link, then the link is stat-ed, not the file it
1316 refers to.
1317
1318 This is the same as the C<lstat(2)> system call.");
1319
1320   ("statvfs", (RStatVFS "statbuf", [String "path"]), 54, [],
1321    [InitBasicFS, TestOutputStruct (
1322       [["statvfs"; "/"]], [CompareWithInt ("bfree", 487702);
1323                            CompareWithInt ("blocks", 490020);
1324                            CompareWithInt ("bsize", 1024)])],
1325    "get file system statistics",
1326    "\
1327 Returns file system statistics for any mounted file system.
1328 C<path> should be a file or directory in the mounted file system
1329 (typically it is the mount point itself, but it doesn't need to be).
1330
1331 This is the same as the C<statvfs(2)> system call.");
1332
1333   ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [],
1334    [], (* XXX test *)
1335    "get ext2/ext3/ext4 superblock details",
1336    "\
1337 This returns the contents of the ext2, ext3 or ext4 filesystem
1338 superblock on C<device>.
1339
1340 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1341 manpage for more details.  The list of fields returned isn't
1342 clearly defined, and depends on both the version of C<tune2fs>
1343 that libguestfs was built against, and the filesystem itself.");
1344
1345   ("blockdev_setro", (RErr, [String "device"]), 56, [],
1346    [InitEmpty, TestOutputTrue (
1347       [["blockdev_setro"; "/dev/sda"];
1348        ["blockdev_getro"; "/dev/sda"]])],
1349    "set block device to read-only",
1350    "\
1351 Sets the block device named C<device> to read-only.
1352
1353 This uses the L<blockdev(8)> command.");
1354
1355   ("blockdev_setrw", (RErr, [String "device"]), 57, [],
1356    [InitEmpty, TestOutputFalse (
1357       [["blockdev_setrw"; "/dev/sda"];
1358        ["blockdev_getro"; "/dev/sda"]])],
1359    "set block device to read-write",
1360    "\
1361 Sets the block device named C<device> to read-write.
1362
1363 This uses the L<blockdev(8)> command.");
1364
1365   ("blockdev_getro", (RBool "ro", [String "device"]), 58, [],
1366    [InitEmpty, TestOutputTrue (
1367       [["blockdev_setro"; "/dev/sda"];
1368        ["blockdev_getro"; "/dev/sda"]])],
1369    "is block device set to read-only",
1370    "\
1371 Returns a boolean indicating if the block device is read-only
1372 (true if read-only, false if not).
1373
1374 This uses the L<blockdev(8)> command.");
1375
1376   ("blockdev_getss", (RInt "sectorsize", [String "device"]), 59, [],
1377    [InitEmpty, TestOutputInt (
1378       [["blockdev_getss"; "/dev/sda"]], 512)],
1379    "get sectorsize of block device",
1380    "\
1381 This returns the size of sectors on a block device.
1382 Usually 512, but can be larger for modern devices.
1383
1384 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1385 for that).
1386
1387 This uses the L<blockdev(8)> command.");
1388
1389   ("blockdev_getbsz", (RInt "blocksize", [String "device"]), 60, [],
1390    [InitEmpty, TestOutputInt (
1391       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1392    "get blocksize of block device",
1393    "\
1394 This returns the block size of a device.
1395
1396 (Note this is different from both I<size in blocks> and
1397 I<filesystem block size>).
1398
1399 This uses the L<blockdev(8)> command.");
1400
1401   ("blockdev_setbsz", (RErr, [String "device"; Int "blocksize"]), 61, [],
1402    [], (* XXX test *)
1403    "set blocksize of block device",
1404    "\
1405 This sets the block size of a device.
1406
1407 (Note this is different from both I<size in blocks> and
1408 I<filesystem block size>).
1409
1410 This uses the L<blockdev(8)> command.");
1411
1412   ("blockdev_getsz", (RInt64 "sizeinsectors", [String "device"]), 62, [],
1413    [InitEmpty, TestOutputInt (
1414       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1415    "get total size of device in 512-byte sectors",
1416    "\
1417 This returns the size of the device in units of 512-byte sectors
1418 (even if the sectorsize isn't 512 bytes ... weird).
1419
1420 See also C<guestfs_blockdev_getss> for the real sector size of
1421 the device, and C<guestfs_blockdev_getsize64> for the more
1422 useful I<size in bytes>.
1423
1424 This uses the L<blockdev(8)> command.");
1425
1426   ("blockdev_getsize64", (RInt64 "sizeinbytes", [String "device"]), 63, [],
1427    [InitEmpty, TestOutputInt (
1428       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1429    "get total size of device in bytes",
1430    "\
1431 This returns the size of the device in bytes.
1432
1433 See also C<guestfs_blockdev_getsz>.
1434
1435 This uses the L<blockdev(8)> command.");
1436
1437   ("blockdev_flushbufs", (RErr, [String "device"]), 64, [],
1438    [InitEmpty, TestRun
1439       [["blockdev_flushbufs"; "/dev/sda"]]],
1440    "flush device buffers",
1441    "\
1442 This tells the kernel to flush internal buffers associated
1443 with C<device>.
1444
1445 This uses the L<blockdev(8)> command.");
1446
1447   ("blockdev_rereadpt", (RErr, [String "device"]), 65, [],
1448    [InitEmpty, TestRun
1449       [["blockdev_rereadpt"; "/dev/sda"]]],
1450    "reread partition table",
1451    "\
1452 Reread the partition table on C<device>.
1453
1454 This uses the L<blockdev(8)> command.");
1455
1456   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1457    [InitBasicFS, TestOutput (
1458       (* Pick a file from cwd which isn't likely to change. *)
1459     [["upload"; "COPYING.LIB"; "/COPYING.LIB"];
1460      ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
1461    "upload a file from the local machine",
1462    "\
1463 Upload local file C<filename> to C<remotefilename> on the
1464 filesystem.
1465
1466 C<filename> can also be a named pipe.
1467
1468 See also C<guestfs_download>.");
1469
1470   ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
1471    [InitBasicFS, TestOutput (
1472       (* Pick a file from cwd which isn't likely to change. *)
1473     [["upload"; "COPYING.LIB"; "/COPYING.LIB"];
1474      ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1475      ["upload"; "testdownload.tmp"; "/upload"];
1476      ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
1477    "download a file to the local machine",
1478    "\
1479 Download file C<remotefilename> and save it as C<filename>
1480 on the local machine.
1481
1482 C<filename> can also be a named pipe.
1483
1484 See also C<guestfs_upload>, C<guestfs_cat>.");
1485
1486   ("checksum", (RString "checksum", [String "csumtype"; String "path"]), 68, [],
1487    [InitBasicFS, TestOutput (
1488       [["write_file"; "/new"; "test\n"; "0"];
1489        ["checksum"; "crc"; "/new"]], "935282863");
1490     InitBasicFS, TestLastFail (
1491       [["checksum"; "crc"; "/new"]]);
1492     InitBasicFS, TestOutput (
1493       [["write_file"; "/new"; "test\n"; "0"];
1494        ["checksum"; "md5"; "/new"]], "d8e8fca2dc0f896fd7cb4cb0031ba249");
1495     InitBasicFS, TestOutput (
1496       [["write_file"; "/new"; "test\n"; "0"];
1497        ["checksum"; "sha1"; "/new"]], "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83");
1498     InitBasicFS, TestOutput (
1499       [["write_file"; "/new"; "test\n"; "0"];
1500        ["checksum"; "sha224"; "/new"]], "52f1bf093f4b7588726035c176c0cdb4376cfea53819f1395ac9e6ec");
1501     InitBasicFS, TestOutput (
1502       [["write_file"; "/new"; "test\n"; "0"];
1503        ["checksum"; "sha256"; "/new"]], "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2");
1504     InitBasicFS, TestOutput (
1505       [["write_file"; "/new"; "test\n"; "0"];
1506        ["checksum"; "sha384"; "/new"]], "109bb6b5b6d5547c1ce03c7a8bd7d8f80c1cb0957f50c4f7fda04692079917e4f9cad52b878f3d8234e1a170b154b72d");
1507     InitBasicFS, TestOutput (
1508       [["write_file"; "/new"; "test\n"; "0"];
1509        ["checksum"; "sha512"; "/new"]], "0e3e75234abc68f4378a86b3f4b32a198ba301845b0cd6e50106e874345700cc6663a86c1ea125dc5e92be17c98f9a0f85ca9d5f595db2012f7cc3571945c123")],
1510    "compute MD5, SHAx or CRC checksum of file",
1511    "\
1512 This call computes the MD5, SHAx or CRC checksum of the
1513 file named C<path>.
1514
1515 The type of checksum to compute is given by the C<csumtype>
1516 parameter which must have one of the following values:
1517
1518 =over 4
1519
1520 =item C<crc>
1521
1522 Compute the cyclic redundancy check (CRC) specified by POSIX
1523 for the C<cksum> command.
1524
1525 =item C<md5>
1526
1527 Compute the MD5 hash (using the C<md5sum> program).
1528
1529 =item C<sha1>
1530
1531 Compute the SHA1 hash (using the C<sha1sum> program).
1532
1533 =item C<sha224>
1534
1535 Compute the SHA224 hash (using the C<sha224sum> program).
1536
1537 =item C<sha256>
1538
1539 Compute the SHA256 hash (using the C<sha256sum> program).
1540
1541 =item C<sha384>
1542
1543 Compute the SHA384 hash (using the C<sha384sum> program).
1544
1545 =item C<sha512>
1546
1547 Compute the SHA512 hash (using the C<sha512sum> program).
1548
1549 =back
1550
1551 The checksum is returned as a printable string.");
1552
1553   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1554    [InitBasicFS, TestOutput (
1555       [["tar_in"; "images/helloworld.tar"; "/"];
1556        ["cat"; "/hello"]], "hello\n")],
1557    "unpack tarfile to directory",
1558    "\
1559 This command uploads and unpacks local file C<tarfile> (an
1560 I<uncompressed> tar file) into C<directory>.
1561
1562 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1563
1564   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1565    [],
1566    "pack directory into tarfile",
1567    "\
1568 This command packs the contents of C<directory> and downloads
1569 it to local file C<tarfile>.
1570
1571 To download a compressed tarball, use C<guestfs_tgz_out>.");
1572
1573   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1574    [InitBasicFS, TestOutput (
1575       [["tgz_in"; "images/helloworld.tar.gz"; "/"];
1576        ["cat"; "/hello"]], "hello\n")],
1577    "unpack compressed tarball to directory",
1578    "\
1579 This command uploads and unpacks local file C<tarball> (a
1580 I<gzip compressed> tar file) into C<directory>.
1581
1582 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1583
1584   ("tgz_out", (RErr, [String "directory"; FileOut "tarball"]), 72, [],
1585    [],
1586    "pack directory into compressed tarball",
1587    "\
1588 This command packs the contents of C<directory> and downloads
1589 it to local file C<tarball>.
1590
1591 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1592
1593   ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [],
1594    [InitBasicFS, TestLastFail (
1595       [["umount"; "/"];
1596        ["mount_ro"; "/dev/sda1"; "/"];
1597        ["touch"; "/new"]]);
1598     InitBasicFS, TestOutput (
1599       [["write_file"; "/new"; "data"; "0"];
1600        ["umount"; "/"];
1601        ["mount_ro"; "/dev/sda1"; "/"];
1602        ["cat"; "/new"]], "data")],
1603    "mount a guest disk, read-only",
1604    "\
1605 This is the same as the C<guestfs_mount> command, but it
1606 mounts the filesystem with the read-only (I<-o ro>) flag.");
1607
1608   ("mount_options", (RErr, [String "options"; String "device"; String "mountpoint"]), 74, [],
1609    [],
1610    "mount a guest disk with mount options",
1611    "\
1612 This is the same as the C<guestfs_mount> command, but it
1613 allows you to set the mount options as for the
1614 L<mount(8)> I<-o> flag.");
1615
1616   ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [],
1617    [],
1618    "mount a guest disk with mount options and vfstype",
1619    "\
1620 This is the same as the C<guestfs_mount> command, but it
1621 allows you to set both the mount options and the vfstype
1622 as for the L<mount(8)> I<-o> and I<-t> flags.");
1623
1624   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1625    [],
1626    "debugging and internals",
1627    "\
1628 The C<guestfs_debug> command exposes some internals of
1629 C<guestfsd> (the guestfs daemon) that runs inside the
1630 qemu subprocess.
1631
1632 There is no comprehensive help for this command.  You have
1633 to look at the file C<daemon/debug.c> in the libguestfs source
1634 to find out what you can do.");
1635
1636   ("lvremove", (RErr, [String "device"]), 77, [],
1637    [InitEmpty, TestOutputList (
1638       [["pvcreate"; "/dev/sda"];
1639        ["vgcreate"; "VG"; "/dev/sda"];
1640        ["lvcreate"; "LV1"; "VG"; "50"];
1641        ["lvcreate"; "LV2"; "VG"; "50"];
1642        ["lvremove"; "/dev/VG/LV1"];
1643        ["lvs"]], ["/dev/VG/LV2"]);
1644     InitEmpty, TestOutputList (
1645       [["pvcreate"; "/dev/sda"];
1646        ["vgcreate"; "VG"; "/dev/sda"];
1647        ["lvcreate"; "LV1"; "VG"; "50"];
1648        ["lvcreate"; "LV2"; "VG"; "50"];
1649        ["lvremove"; "/dev/VG"];
1650        ["lvs"]], []);
1651     InitEmpty, TestOutputList (
1652       [["pvcreate"; "/dev/sda"];
1653        ["vgcreate"; "VG"; "/dev/sda"];
1654        ["lvcreate"; "LV1"; "VG"; "50"];
1655        ["lvcreate"; "LV2"; "VG"; "50"];
1656        ["lvremove"; "/dev/VG"];
1657        ["vgs"]], ["VG"])],
1658    "remove an LVM logical volume",
1659    "\
1660 Remove an LVM logical volume C<device>, where C<device> is
1661 the path to the LV, such as C</dev/VG/LV>.
1662
1663 You can also remove all LVs in a volume group by specifying
1664 the VG name, C</dev/VG>.");
1665
1666   ("vgremove", (RErr, [String "vgname"]), 78, [],
1667    [InitEmpty, TestOutputList (
1668       [["pvcreate"; "/dev/sda"];
1669        ["vgcreate"; "VG"; "/dev/sda"];
1670        ["lvcreate"; "LV1"; "VG"; "50"];
1671        ["lvcreate"; "LV2"; "VG"; "50"];
1672        ["vgremove"; "VG"];
1673        ["lvs"]], []);
1674     InitEmpty, TestOutputList (
1675       [["pvcreate"; "/dev/sda"];
1676        ["vgcreate"; "VG"; "/dev/sda"];
1677        ["lvcreate"; "LV1"; "VG"; "50"];
1678        ["lvcreate"; "LV2"; "VG"; "50"];
1679        ["vgremove"; "VG"];
1680        ["vgs"]], [])],
1681    "remove an LVM volume group",
1682    "\
1683 Remove an LVM volume group C<vgname>, (for example C<VG>).
1684
1685 This also forcibly removes all logical volumes in the volume
1686 group (if any).");
1687
1688   ("pvremove", (RErr, [String "device"]), 79, [],
1689    [InitEmpty, TestOutputList (
1690       [["pvcreate"; "/dev/sda"];
1691        ["vgcreate"; "VG"; "/dev/sda"];
1692        ["lvcreate"; "LV1"; "VG"; "50"];
1693        ["lvcreate"; "LV2"; "VG"; "50"];
1694        ["vgremove"; "VG"];
1695        ["pvremove"; "/dev/sda"];
1696        ["lvs"]], []);
1697     InitEmpty, TestOutputList (
1698       [["pvcreate"; "/dev/sda"];
1699        ["vgcreate"; "VG"; "/dev/sda"];
1700        ["lvcreate"; "LV1"; "VG"; "50"];
1701        ["lvcreate"; "LV2"; "VG"; "50"];
1702        ["vgremove"; "VG"];
1703        ["pvremove"; "/dev/sda"];
1704        ["vgs"]], []);
1705     InitEmpty, TestOutputList (
1706       [["pvcreate"; "/dev/sda"];
1707        ["vgcreate"; "VG"; "/dev/sda"];
1708        ["lvcreate"; "LV1"; "VG"; "50"];
1709        ["lvcreate"; "LV2"; "VG"; "50"];
1710        ["vgremove"; "VG"];
1711        ["pvremove"; "/dev/sda"];
1712        ["pvs"]], [])],
1713    "remove an LVM physical volume",
1714    "\
1715 This wipes a physical volume C<device> so that LVM will no longer
1716 recognise it.
1717
1718 The implementation uses the C<pvremove> command which refuses to
1719 wipe physical volumes that contain any volume groups, so you have
1720 to remove those first.");
1721
1722   ("set_e2label", (RErr, [String "device"; String "label"]), 80, [],
1723    [InitBasicFS, TestOutput (
1724       [["set_e2label"; "/dev/sda1"; "testlabel"];
1725        ["get_e2label"; "/dev/sda1"]], "testlabel")],
1726    "set the ext2/3/4 filesystem label",
1727    "\
1728 This sets the ext2/3/4 filesystem label of the filesystem on
1729 C<device> to C<label>.  Filesystem labels are limited to
1730 16 characters.
1731
1732 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
1733 to return the existing label on a filesystem.");
1734
1735   ("get_e2label", (RString "label", [String "device"]), 81, [],
1736    [],
1737    "get the ext2/3/4 filesystem label",
1738    "\
1739 This returns the ext2/3/4 filesystem label of the filesystem on
1740 C<device>.");
1741
1742   ("set_e2uuid", (RErr, [String "device"; String "uuid"]), 82, [],
1743    [InitBasicFS, TestOutput (
1744       [["set_e2uuid"; "/dev/sda1"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
1745        ["get_e2uuid"; "/dev/sda1"]], "a3a61220-882b-4f61-89f4-cf24dcc7297d");
1746     InitBasicFS, TestOutput (
1747       [["set_e2uuid"; "/dev/sda1"; "clear"];
1748        ["get_e2uuid"; "/dev/sda1"]], "");
1749     (* We can't predict what UUIDs will be, so just check the commands run. *)
1750     InitBasicFS, TestRun (
1751       [["set_e2uuid"; "/dev/sda1"; "random"]]);
1752     InitBasicFS, TestRun (
1753       [["set_e2uuid"; "/dev/sda1"; "time"]])],
1754    "set the ext2/3/4 filesystem UUID",
1755    "\
1756 This sets the ext2/3/4 filesystem UUID of the filesystem on
1757 C<device> to C<uuid>.  The format of the UUID and alternatives
1758 such as C<clear>, C<random> and C<time> are described in the
1759 L<tune2fs(8)> manpage.
1760
1761 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
1762 to return the existing UUID of a filesystem.");
1763
1764   ("get_e2uuid", (RString "uuid", [String "device"]), 83, [],
1765    [],
1766    "get the ext2/3/4 filesystem UUID",
1767    "\
1768 This returns the ext2/3/4 filesystem UUID of the filesystem on
1769 C<device>.");
1770
1771   ("fsck", (RInt "status", [String "fstype"; String "device"]), 84, [],
1772    [InitBasicFS, TestOutputInt (
1773       [["umount"; "/dev/sda1"];
1774        ["fsck"; "ext2"; "/dev/sda1"]], 0);
1775     InitBasicFS, TestOutputInt (
1776       [["umount"; "/dev/sda1"];
1777        ["zero"; "/dev/sda1"];
1778        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
1779    "run the filesystem checker",
1780    "\
1781 This runs the filesystem checker (fsck) on C<device> which
1782 should have filesystem type C<fstype>.
1783
1784 The returned integer is the status.  See L<fsck(8)> for the
1785 list of status codes from C<fsck>.
1786
1787 Notes:
1788
1789 =over 4
1790
1791 =item *
1792
1793 Multiple status codes can be summed together.
1794
1795 =item *
1796
1797 A non-zero return code can mean \"success\", for example if
1798 errors have been corrected on the filesystem.
1799
1800 =item *
1801
1802 Checking or repairing NTFS volumes is not supported
1803 (by linux-ntfs).
1804
1805 =back
1806
1807 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
1808
1809   ("zero", (RErr, [String "device"]), 85, [],
1810    [InitBasicFS, TestOutput (
1811       [["umount"; "/dev/sda1"];
1812        ["zero"; "/dev/sda1"];
1813        ["file"; "/dev/sda1"]], "data")],
1814    "write zeroes to the device",
1815    "\
1816 This command writes zeroes over the first few blocks of C<device>.
1817
1818 How many blocks are zeroed isn't specified (but it's I<not> enough
1819 to securely wipe the device).  It should be sufficient to remove
1820 any partition tables, filesystem superblocks and so on.");
1821
1822   ("grub_install", (RErr, [String "root"; String "device"]), 86, [],
1823    [InitBasicFS, TestOutputTrue (
1824       [["grub_install"; "/"; "/dev/sda1"];
1825        ["is_dir"; "/boot"]])],
1826    "install GRUB",
1827    "\
1828 This command installs GRUB (the Grand Unified Bootloader) on
1829 C<device>, with the root directory being C<root>.");
1830
1831   ("cp", (RErr, [String "src"; String "dest"]), 87, [],
1832    [InitBasicFS, TestOutput (
1833       [["write_file"; "/old"; "file content"; "0"];
1834        ["cp"; "/old"; "/new"];
1835        ["cat"; "/new"]], "file content");
1836     InitBasicFS, TestOutputTrue (
1837       [["write_file"; "/old"; "file content"; "0"];
1838        ["cp"; "/old"; "/new"];
1839        ["is_file"; "/old"]]);
1840     InitBasicFS, TestOutput (
1841       [["write_file"; "/old"; "file content"; "0"];
1842        ["mkdir"; "/dir"];
1843        ["cp"; "/old"; "/dir/new"];
1844        ["cat"; "/dir/new"]], "file content")],
1845    "copy a file",
1846    "\
1847 This copies a file from C<src> to C<dest> where C<dest> is
1848 either a destination filename or destination directory.");
1849
1850   ("cp_a", (RErr, [String "src"; String "dest"]), 88, [],
1851    [InitBasicFS, TestOutput (
1852       [["mkdir"; "/olddir"];
1853        ["mkdir"; "/newdir"];
1854        ["write_file"; "/olddir/file"; "file content"; "0"];
1855        ["cp_a"; "/olddir"; "/newdir"];
1856        ["cat"; "/newdir/olddir/file"]], "file content")],
1857    "copy a file or directory recursively",
1858    "\
1859 This copies a file or directory from C<src> to C<dest>
1860 recursively using the C<cp -a> command.");
1861
1862   ("mv", (RErr, [String "src"; String "dest"]), 89, [],
1863    [InitBasicFS, TestOutput (
1864       [["write_file"; "/old"; "file content"; "0"];
1865        ["mv"; "/old"; "/new"];
1866        ["cat"; "/new"]], "file content");
1867     InitBasicFS, TestOutputFalse (
1868       [["write_file"; "/old"; "file content"; "0"];
1869        ["mv"; "/old"; "/new"];
1870        ["is_file"; "/old"]])],
1871    "move a file",
1872    "\
1873 This moves a file from C<src> to C<dest> where C<dest> is
1874 either a destination filename or destination directory.");
1875
1876   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
1877    [InitEmpty, TestRun (
1878       [["drop_caches"; "3"]])],
1879    "drop kernel page cache, dentries and inodes",
1880    "\
1881 This instructs the guest kernel to drop its page cache,
1882 and/or dentries and inode caches.  The parameter C<whattodrop>
1883 tells the kernel what precisely to drop, see
1884 L<http://linux-mm.org/Drop_Caches>
1885
1886 Setting C<whattodrop> to 3 should drop everything.
1887
1888 This automatically calls L<sync(2)> before the operation,
1889 so that the maximum guest memory is freed.");
1890
1891   ("dmesg", (RString "kmsgs", []), 91, [],
1892    [InitEmpty, TestRun (
1893       [["dmesg"]])],
1894    "return kernel messages",
1895    "\
1896 This returns the kernel messages (C<dmesg> output) from
1897 the guest kernel.  This is sometimes useful for extended
1898 debugging of problems.
1899
1900 Another way to get the same information is to enable
1901 verbose messages with C<guestfs_set_verbose> or by setting
1902 the environment variable C<LIBGUESTFS_DEBUG=1> before
1903 running the program.");
1904
1905   ("ping_daemon", (RErr, []), 92, [],
1906    [InitEmpty, TestRun (
1907       [["ping_daemon"]])],
1908    "ping the guest daemon",
1909    "\
1910 This is a test probe into the guestfs daemon running inside
1911 the qemu subprocess.  Calling this function checks that the
1912 daemon responds to the ping message, without affecting the daemon
1913 or attached block device(s) in any other way.");
1914
1915   ("equal", (RBool "equality", [String "file1"; String "file2"]), 93, [],
1916    [InitBasicFS, TestOutputTrue (
1917       [["write_file"; "/file1"; "contents of a file"; "0"];
1918        ["cp"; "/file1"; "/file2"];
1919        ["equal"; "/file1"; "/file2"]]);
1920     InitBasicFS, TestOutputFalse (
1921       [["write_file"; "/file1"; "contents of a file"; "0"];
1922        ["write_file"; "/file2"; "contents of another file"; "0"];
1923        ["equal"; "/file1"; "/file2"]]);
1924     InitBasicFS, TestLastFail (
1925       [["equal"; "/file1"; "/file2"]])],
1926    "test if two files have equal contents",
1927    "\
1928 This compares the two files C<file1> and C<file2> and returns
1929 true if their content is exactly equal, or false otherwise.
1930
1931 The external L<cmp(1)> program is used for the comparison.");
1932
1933   ("strings", (RStringList "stringsout", [String "path"]), 94, [ProtocolLimitWarning],
1934    [InitBasicFS, TestOutputList (
1935       [["write_file"; "/new"; "hello\nworld\n"; "0"];
1936        ["strings"; "/new"]], ["hello"; "world"]);
1937     InitBasicFS, TestOutputList (
1938       [["touch"; "/new"];
1939        ["strings"; "/new"]], [])],
1940    "print the printable strings in a file",
1941    "\
1942 This runs the L<strings(1)> command on a file and returns
1943 the list of printable strings found.");
1944
1945   ("strings_e", (RStringList "stringsout", [String "encoding"; String "path"]), 95, [ProtocolLimitWarning],
1946    [InitBasicFS, TestOutputList (
1947       [["write_file"; "/new"; "hello\nworld\n"; "0"];
1948        ["strings_e"; "b"; "/new"]], []);
1949     (*InitBasicFS, TestOutputList (
1950       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
1951        ["strings_e"; "b"; "/new"]], ["hello"; "world"])*)],
1952    "print the printable strings in a file",
1953    "\
1954 This is like the C<guestfs_strings> command, but allows you to
1955 specify the encoding.
1956
1957 See the L<strings(1)> manpage for the full list of encodings.
1958
1959 Commonly useful encodings are C<l> (lower case L) which will
1960 show strings inside Windows/x86 files.
1961
1962 The returned strings are transcoded to UTF-8.");
1963
1964   ("hexdump", (RString "dump", [String "path"]), 96, [ProtocolLimitWarning],
1965    [InitBasicFS, TestOutput (
1966       [["write_file"; "/new"; "hello\nworld\n"; "12"];
1967        ["hexdump"; "/new"]], "00000000  68 65 6c 6c 6f 0a 77 6f  72 6c 64 0a              |hello.world.|\n0000000c\n")],
1968    "dump a file in hexadecimal",
1969    "\
1970 This runs C<hexdump -C> on the given C<path>.  The result is
1971 the human-readable, canonical hex dump of the file.");
1972
1973 ]
1974
1975 let all_functions = non_daemon_functions @ daemon_functions
1976
1977 (* In some places we want the functions to be displayed sorted
1978  * alphabetically, so this is useful:
1979  *)
1980 let all_functions_sorted =
1981   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
1982                compare n1 n2) all_functions
1983
1984 (* Column names and types from LVM PVs/VGs/LVs. *)
1985 let pv_cols = [
1986   "pv_name", `String;
1987   "pv_uuid", `UUID;
1988   "pv_fmt", `String;
1989   "pv_size", `Bytes;
1990   "dev_size", `Bytes;
1991   "pv_free", `Bytes;
1992   "pv_used", `Bytes;
1993   "pv_attr", `String (* XXX *);
1994   "pv_pe_count", `Int;
1995   "pv_pe_alloc_count", `Int;
1996   "pv_tags", `String;
1997   "pe_start", `Bytes;
1998   "pv_mda_count", `Int;
1999   "pv_mda_free", `Bytes;
2000 (* Not in Fedora 10:
2001   "pv_mda_size", `Bytes;
2002 *)
2003 ]
2004 let vg_cols = [
2005   "vg_name", `String;
2006   "vg_uuid", `UUID;
2007   "vg_fmt", `String;
2008   "vg_attr", `String (* XXX *);
2009   "vg_size", `Bytes;
2010   "vg_free", `Bytes;
2011   "vg_sysid", `String;
2012   "vg_extent_size", `Bytes;
2013   "vg_extent_count", `Int;
2014   "vg_free_count", `Int;
2015   "max_lv", `Int;
2016   "max_pv", `Int;
2017   "pv_count", `Int;
2018   "lv_count", `Int;
2019   "snap_count", `Int;
2020   "vg_seqno", `Int;
2021   "vg_tags", `String;
2022   "vg_mda_count", `Int;
2023   "vg_mda_free", `Bytes;
2024 (* Not in Fedora 10:
2025   "vg_mda_size", `Bytes;
2026 *)
2027 ]
2028 let lv_cols = [
2029   "lv_name", `String;
2030   "lv_uuid", `UUID;
2031   "lv_attr", `String (* XXX *);
2032   "lv_major", `Int;
2033   "lv_minor", `Int;
2034   "lv_kernel_major", `Int;
2035   "lv_kernel_minor", `Int;
2036   "lv_size", `Bytes;
2037   "seg_count", `Int;
2038   "origin", `String;
2039   "snap_percent", `OptPercent;
2040   "copy_percent", `OptPercent;
2041   "move_pv", `String;
2042   "lv_tags", `String;
2043   "mirror_log", `String;
2044   "modules", `String;
2045 ]
2046
2047 (* Column names and types from stat structures.
2048  * NB. Can't use things like 'st_atime' because glibc header files
2049  * define some of these as macros.  Ugh.
2050  *)
2051 let stat_cols = [
2052   "dev", `Int;
2053   "ino", `Int;
2054   "mode", `Int;
2055   "nlink", `Int;
2056   "uid", `Int;
2057   "gid", `Int;
2058   "rdev", `Int;
2059   "size", `Int;
2060   "blksize", `Int;
2061   "blocks", `Int;
2062   "atime", `Int;
2063   "mtime", `Int;
2064   "ctime", `Int;
2065 ]
2066 let statvfs_cols = [
2067   "bsize", `Int;
2068   "frsize", `Int;
2069   "blocks", `Int;
2070   "bfree", `Int;
2071   "bavail", `Int;
2072   "files", `Int;
2073   "ffree", `Int;
2074   "favail", `Int;
2075   "fsid", `Int;
2076   "flag", `Int;
2077   "namemax", `Int;
2078 ]
2079
2080 (* Useful functions.
2081  * Note we don't want to use any external OCaml libraries which
2082  * makes this a bit harder than it should be.
2083  *)
2084 let failwithf fs = ksprintf failwith fs
2085
2086 let replace_char s c1 c2 =
2087   let s2 = String.copy s in
2088   let r = ref false in
2089   for i = 0 to String.length s2 - 1 do
2090     if String.unsafe_get s2 i = c1 then (
2091       String.unsafe_set s2 i c2;
2092       r := true
2093     )
2094   done;
2095   if not !r then s else s2
2096
2097 let isspace c =
2098   c = ' '
2099   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
2100
2101 let triml ?(test = isspace) str =
2102   let i = ref 0 in
2103   let n = ref (String.length str) in
2104   while !n > 0 && test str.[!i]; do
2105     decr n;
2106     incr i
2107   done;
2108   if !i = 0 then str
2109   else String.sub str !i !n
2110
2111 let trimr ?(test = isspace) str =
2112   let n = ref (String.length str) in
2113   while !n > 0 && test str.[!n-1]; do
2114     decr n
2115   done;
2116   if !n = String.length str then str
2117   else String.sub str 0 !n
2118
2119 let trim ?(test = isspace) str =
2120   trimr ~test (triml ~test str)
2121
2122 let rec find s sub =
2123   let len = String.length s in
2124   let sublen = String.length sub in
2125   let rec loop i =
2126     if i <= len-sublen then (
2127       let rec loop2 j =
2128         if j < sublen then (
2129           if s.[i+j] = sub.[j] then loop2 (j+1)
2130           else -1
2131         ) else
2132           i (* found *)
2133       in
2134       let r = loop2 0 in
2135       if r = -1 then loop (i+1) else r
2136     ) else
2137       -1 (* not found *)
2138   in
2139   loop 0
2140
2141 let rec replace_str s s1 s2 =
2142   let len = String.length s in
2143   let sublen = String.length s1 in
2144   let i = find s s1 in
2145   if i = -1 then s
2146   else (
2147     let s' = String.sub s 0 i in
2148     let s'' = String.sub s (i+sublen) (len-i-sublen) in
2149     s' ^ s2 ^ replace_str s'' s1 s2
2150   )
2151
2152 let rec string_split sep str =
2153   let len = String.length str in
2154   let seplen = String.length sep in
2155   let i = find str sep in
2156   if i = -1 then [str]
2157   else (
2158     let s' = String.sub str 0 i in
2159     let s'' = String.sub str (i+seplen) (len-i-seplen) in
2160     s' :: string_split sep s''
2161   )
2162
2163 let files_equal n1 n2 =
2164   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
2165   match Sys.command cmd with
2166   | 0 -> true
2167   | 1 -> false
2168   | i -> failwithf "%s: failed with error code %d" cmd i
2169
2170 let rec find_map f = function
2171   | [] -> raise Not_found
2172   | x :: xs ->
2173       match f x with
2174       | Some y -> y
2175       | None -> find_map f xs
2176
2177 let iteri f xs =
2178   let rec loop i = function
2179     | [] -> ()
2180     | x :: xs -> f i x; loop (i+1) xs
2181   in
2182   loop 0 xs
2183
2184 let mapi f xs =
2185   let rec loop i = function
2186     | [] -> []
2187     | x :: xs -> let r = f i x in r :: loop (i+1) xs
2188   in
2189   loop 0 xs
2190
2191 let name_of_argt = function
2192   | String n | OptString n | StringList n | Bool n | Int n
2193   | FileIn n | FileOut n -> n
2194
2195 let seq_of_test = function
2196   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
2197   | TestOutputInt (s, _) | TestOutputTrue s | TestOutputFalse s
2198   | TestOutputLength (s, _) | TestOutputStruct (s, _)
2199   | TestLastFail s -> s
2200
2201 (* Check function names etc. for consistency. *)
2202 let check_functions () =
2203   let contains_uppercase str =
2204     let len = String.length str in
2205     let rec loop i =
2206       if i >= len then false
2207       else (
2208         let c = str.[i] in
2209         if c >= 'A' && c <= 'Z' then true
2210         else loop (i+1)
2211       )
2212     in
2213     loop 0
2214   in
2215
2216   (* Check function names. *)
2217   List.iter (
2218     fun (name, _, _, _, _, _, _) ->
2219       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
2220         failwithf "function name %s does not need 'guestfs' prefix" name;
2221       if contains_uppercase name then
2222         failwithf "function name %s should not contain uppercase chars" name;
2223       if String.contains name '-' then
2224         failwithf "function name %s should not contain '-', use '_' instead."
2225           name
2226   ) all_functions;
2227
2228   (* Check function parameter/return names. *)
2229   List.iter (
2230     fun (name, style, _, _, _, _, _) ->
2231       let check_arg_ret_name n =
2232         if contains_uppercase n then
2233           failwithf "%s param/ret %s should not contain uppercase chars"
2234             name n;
2235         if String.contains n '-' || String.contains n '_' then
2236           failwithf "%s param/ret %s should not contain '-' or '_'"
2237             name n;
2238         if n = "value" then
2239           failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" n;
2240         if n = "argv" || n = "args" then
2241           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" n
2242       in
2243
2244       (match fst style with
2245        | RErr -> ()
2246        | RInt n | RInt64 n | RBool n | RConstString n | RString n
2247        | RStringList n | RPVList n | RVGList n | RLVList n
2248        | RStat n | RStatVFS n
2249        | RHashtable n ->
2250            check_arg_ret_name n
2251        | RIntBool (n,m) ->
2252            check_arg_ret_name n;
2253            check_arg_ret_name m
2254       );
2255       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
2256   ) all_functions;
2257
2258   (* Check short descriptions. *)
2259   List.iter (
2260     fun (name, _, _, _, _, shortdesc, _) ->
2261       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
2262         failwithf "short description of %s should begin with lowercase." name;
2263       let c = shortdesc.[String.length shortdesc-1] in
2264       if c = '\n' || c = '.' then
2265         failwithf "short description of %s should not end with . or \\n." name
2266   ) all_functions;
2267
2268   (* Check long dscriptions. *)
2269   List.iter (
2270     fun (name, _, _, _, _, _, longdesc) ->
2271       if longdesc.[String.length longdesc-1] = '\n' then
2272         failwithf "long description of %s should not end with \\n." name
2273   ) all_functions;
2274
2275   (* Check proc_nrs. *)
2276   List.iter (
2277     fun (name, _, proc_nr, _, _, _, _) ->
2278       if proc_nr <= 0 then
2279         failwithf "daemon function %s should have proc_nr > 0" name
2280   ) daemon_functions;
2281
2282   List.iter (
2283     fun (name, _, proc_nr, _, _, _, _) ->
2284       if proc_nr <> -1 then
2285         failwithf "non-daemon function %s should have proc_nr -1" name
2286   ) non_daemon_functions;
2287
2288   let proc_nrs =
2289     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
2290       daemon_functions in
2291   let proc_nrs =
2292     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
2293   let rec loop = function
2294     | [] -> ()
2295     | [_] -> ()
2296     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
2297         loop rest
2298     | (name1,nr1) :: (name2,nr2) :: _ ->
2299         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
2300           name1 name2 nr1 nr2
2301   in
2302   loop proc_nrs;
2303
2304   (* Check tests. *)
2305   List.iter (
2306     function
2307       (* Ignore functions that have no tests.  We generate a
2308        * warning when the user does 'make check' instead.
2309        *)
2310     | name, _, _, _, [], _, _ -> ()
2311     | name, _, _, _, tests, _, _ ->
2312         let funcs =
2313           List.map (
2314             fun (_, test) ->
2315               match seq_of_test test with
2316               | [] ->
2317                   failwithf "%s has a test containing an empty sequence" name
2318               | cmds -> List.map List.hd cmds
2319           ) tests in
2320         let funcs = List.flatten funcs in
2321
2322         let tested = List.mem name funcs in
2323
2324         if not tested then
2325           failwithf "function %s has tests but does not test itself" name
2326   ) all_functions
2327
2328 (* 'pr' prints to the current output file. *)
2329 let chan = ref stdout
2330 let pr fs = ksprintf (output_string !chan) fs
2331
2332 (* Generate a header block in a number of standard styles. *)
2333 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
2334 type license = GPLv2 | LGPLv2
2335
2336 let generate_header comment license =
2337   let c = match comment with
2338     | CStyle ->     pr "/* "; " *"
2339     | HashStyle ->  pr "# ";  "#"
2340     | OCamlStyle -> pr "(* "; " *"
2341     | HaskellStyle -> pr "{- "; "  " in
2342   pr "libguestfs generated file\n";
2343   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
2344   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
2345   pr "%s\n" c;
2346   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
2347   pr "%s\n" c;
2348   (match license with
2349    | GPLv2 ->
2350        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
2351        pr "%s it under the terms of the GNU General Public License as published by\n" c;
2352        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
2353        pr "%s (at your option) any later version.\n" c;
2354        pr "%s\n" c;
2355        pr "%s This program is distributed in the hope that it will be useful,\n" c;
2356        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
2357        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
2358        pr "%s GNU General Public License for more details.\n" c;
2359        pr "%s\n" c;
2360        pr "%s You should have received a copy of the GNU General Public License along\n" c;
2361        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
2362        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
2363
2364    | LGPLv2 ->
2365        pr "%s This library is free software; you can redistribute it and/or\n" c;
2366        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
2367        pr "%s License as published by the Free Software Foundation; either\n" c;
2368        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
2369        pr "%s\n" c;
2370        pr "%s This library is distributed in the hope that it will be useful,\n" c;
2371        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
2372        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
2373        pr "%s Lesser General Public License for more details.\n" c;
2374        pr "%s\n" c;
2375        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
2376        pr "%s License along with this library; if not, write to the Free Software\n" c;
2377        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
2378   );
2379   (match comment with
2380    | CStyle -> pr " */\n"
2381    | HashStyle -> ()
2382    | OCamlStyle -> pr " *)\n"
2383    | HaskellStyle -> pr "-}\n"
2384   );
2385   pr "\n"
2386
2387 (* Start of main code generation functions below this line. *)
2388
2389 (* Generate the pod documentation for the C API. *)
2390 let rec generate_actions_pod () =
2391   List.iter (
2392     fun (shortname, style, _, flags, _, _, longdesc) ->
2393       let name = "guestfs_" ^ shortname in
2394       pr "=head2 %s\n\n" name;
2395       pr " ";
2396       generate_prototype ~extern:false ~handle:"handle" name style;
2397       pr "\n\n";
2398       pr "%s\n\n" longdesc;
2399       (match fst style with
2400        | RErr ->
2401            pr "This function returns 0 on success or -1 on error.\n\n"
2402        | RInt _ ->
2403            pr "On error this function returns -1.\n\n"
2404        | RInt64 _ ->
2405            pr "On error this function returns -1.\n\n"
2406        | RBool _ ->
2407            pr "This function returns a C truth value on success or -1 on error.\n\n"
2408        | RConstString _ ->
2409            pr "This function returns a string, or NULL on error.
2410 The string is owned by the guest handle and must I<not> be freed.\n\n"
2411        | RString _ ->
2412            pr "This function returns a string, or NULL on error.
2413 I<The caller must free the returned string after use>.\n\n"
2414        | RStringList _ ->
2415            pr "This function returns a NULL-terminated array of strings
2416 (like L<environ(3)>), or NULL if there was an error.
2417 I<The caller must free the strings and the array after use>.\n\n"
2418        | RIntBool _ ->
2419            pr "This function returns a C<struct guestfs_int_bool *>,
2420 or NULL if there was an error.
2421 I<The caller must call C<guestfs_free_int_bool> after use>.\n\n"
2422        | RPVList _ ->
2423            pr "This function returns a C<struct guestfs_lvm_pv_list *>
2424 (see E<lt>guestfs-structs.hE<gt>),
2425 or NULL if there was an error.
2426 I<The caller must call C<guestfs_free_lvm_pv_list> after use>.\n\n"
2427        | RVGList _ ->
2428            pr "This function returns a C<struct guestfs_lvm_vg_list *>
2429 (see E<lt>guestfs-structs.hE<gt>),
2430 or NULL if there was an error.
2431 I<The caller must call C<guestfs_free_lvm_vg_list> after use>.\n\n"
2432        | RLVList _ ->
2433            pr "This function returns a C<struct guestfs_lvm_lv_list *>
2434 (see E<lt>guestfs-structs.hE<gt>),
2435 or NULL if there was an error.
2436 I<The caller must call C<guestfs_free_lvm_lv_list> after use>.\n\n"
2437        | RStat _ ->
2438            pr "This function returns a C<struct guestfs_stat *>
2439 (see L<stat(2)> and E<lt>guestfs-structs.hE<gt>),
2440 or NULL if there was an error.
2441 I<The caller must call C<free> after use>.\n\n"
2442        | RStatVFS _ ->
2443            pr "This function returns a C<struct guestfs_statvfs *>
2444 (see L<statvfs(2)> and E<lt>guestfs-structs.hE<gt>),
2445 or NULL if there was an error.
2446 I<The caller must call C<free> after use>.\n\n"
2447        | RHashtable _ ->
2448            pr "This function returns a NULL-terminated array of
2449 strings, or NULL if there was an error.
2450 The array of strings will always have length C<2n+1>, where
2451 C<n> keys and values alternate, followed by the trailing NULL entry.
2452 I<The caller must free the strings and the array after use>.\n\n"
2453       );
2454       if List.mem ProtocolLimitWarning flags then
2455         pr "%s\n\n" protocol_limit_warning;
2456       if List.mem DangerWillRobinson flags then
2457         pr "%s\n\n" danger_will_robinson;
2458   ) all_functions_sorted
2459
2460 and generate_structs_pod () =
2461   (* LVM structs documentation. *)
2462   List.iter (
2463     fun (typ, cols) ->
2464       pr "=head2 guestfs_lvm_%s\n" typ;
2465       pr "\n";
2466       pr " struct guestfs_lvm_%s {\n" typ;
2467       List.iter (
2468         function
2469         | name, `String -> pr "  char *%s;\n" name
2470         | name, `UUID ->
2471             pr "  /* The next field is NOT nul-terminated, be careful when printing it: */\n";
2472             pr "  char %s[32];\n" name
2473         | name, `Bytes -> pr "  uint64_t %s;\n" name
2474         | name, `Int -> pr "  int64_t %s;\n" name
2475         | name, `OptPercent ->
2476             pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
2477             pr "  float %s;\n" name
2478       ) cols;
2479       pr " \n";
2480       pr " struct guestfs_lvm_%s_list {\n" typ;
2481       pr "   uint32_t len; /* Number of elements in list. */\n";
2482       pr "   struct guestfs_lvm_%s *val; /* Elements. */\n" typ;
2483       pr " };\n";
2484       pr " \n";
2485       pr " void guestfs_free_lvm_%s_list (struct guestfs_free_lvm_%s_list *);\n"
2486         typ typ;
2487       pr "\n"
2488   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
2489
2490 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
2491  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
2492  *
2493  * We have to use an underscore instead of a dash because otherwise
2494  * rpcgen generates incorrect code.
2495  *
2496  * This header is NOT exported to clients, but see also generate_structs_h.
2497  *)
2498 and generate_xdr () =
2499   generate_header CStyle LGPLv2;
2500
2501   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
2502   pr "typedef string str<>;\n";
2503   pr "\n";
2504
2505   (* LVM internal structures. *)
2506   List.iter (
2507     function
2508     | typ, cols ->
2509         pr "struct guestfs_lvm_int_%s {\n" typ;
2510         List.iter (function
2511                    | name, `String -> pr "  string %s<>;\n" name
2512                    | name, `UUID -> pr "  opaque %s[32];\n" name
2513                    | name, `Bytes -> pr "  hyper %s;\n" name
2514                    | name, `Int -> pr "  hyper %s;\n" name
2515                    | name, `OptPercent -> pr "  float %s;\n" name
2516                   ) cols;
2517         pr "};\n";
2518         pr "\n";
2519         pr "typedef struct guestfs_lvm_int_%s guestfs_lvm_int_%s_list<>;\n" typ typ;
2520         pr "\n";
2521   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
2522
2523   (* Stat internal structures. *)
2524   List.iter (
2525     function
2526     | typ, cols ->
2527         pr "struct guestfs_int_%s {\n" typ;
2528         List.iter (function
2529                    | name, `Int -> pr "  hyper %s;\n" name
2530                   ) cols;
2531         pr "};\n";
2532         pr "\n";
2533   ) ["stat", stat_cols; "statvfs", statvfs_cols];
2534
2535   List.iter (
2536     fun (shortname, style, _, _, _, _, _) ->
2537       let name = "guestfs_" ^ shortname in
2538
2539       (match snd style with
2540        | [] -> ()
2541        | args ->
2542            pr "struct %s_args {\n" name;
2543            List.iter (
2544              function
2545              | String n -> pr "  string %s<>;\n" n
2546              | OptString n -> pr "  str *%s;\n" n
2547              | StringList n -> pr "  str %s<>;\n" n
2548              | Bool n -> pr "  bool %s;\n" n
2549              | Int n -> pr "  int %s;\n" n
2550              | FileIn _ | FileOut _ -> ()
2551            ) args;
2552            pr "};\n\n"
2553       );
2554       (match fst style with
2555        | RErr -> ()
2556        | RInt n ->
2557            pr "struct %s_ret {\n" name;
2558            pr "  int %s;\n" n;
2559            pr "};\n\n"
2560        | RInt64 n ->
2561            pr "struct %s_ret {\n" name;
2562            pr "  hyper %s;\n" n;
2563            pr "};\n\n"
2564        | RBool n ->
2565            pr "struct %s_ret {\n" name;
2566            pr "  bool %s;\n" n;
2567            pr "};\n\n"
2568        | RConstString _ ->
2569            failwithf "RConstString cannot be returned from a daemon function"
2570        | RString n ->
2571            pr "struct %s_ret {\n" name;
2572            pr "  string %s<>;\n" n;
2573            pr "};\n\n"
2574        | RStringList n ->
2575            pr "struct %s_ret {\n" name;
2576            pr "  str %s<>;\n" n;
2577            pr "};\n\n"
2578        | RIntBool (n,m) ->
2579            pr "struct %s_ret {\n" name;
2580            pr "  int %s;\n" n;
2581            pr "  bool %s;\n" m;
2582            pr "};\n\n"
2583        | RPVList n ->
2584            pr "struct %s_ret {\n" name;
2585            pr "  guestfs_lvm_int_pv_list %s;\n" n;
2586            pr "};\n\n"
2587        | RVGList n ->
2588            pr "struct %s_ret {\n" name;
2589            pr "  guestfs_lvm_int_vg_list %s;\n" n;
2590            pr "};\n\n"
2591        | RLVList n ->
2592            pr "struct %s_ret {\n" name;
2593            pr "  guestfs_lvm_int_lv_list %s;\n" n;
2594            pr "};\n\n"
2595        | RStat n ->
2596            pr "struct %s_ret {\n" name;
2597            pr "  guestfs_int_stat %s;\n" n;
2598            pr "};\n\n"
2599        | RStatVFS n ->
2600            pr "struct %s_ret {\n" name;
2601            pr "  guestfs_int_statvfs %s;\n" n;
2602            pr "};\n\n"
2603        | RHashtable n ->
2604            pr "struct %s_ret {\n" name;
2605            pr "  str %s<>;\n" n;
2606            pr "};\n\n"
2607       );
2608   ) daemon_functions;
2609
2610   (* Table of procedure numbers. *)
2611   pr "enum guestfs_procedure {\n";
2612   List.iter (
2613     fun (shortname, _, proc_nr, _, _, _, _) ->
2614       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
2615   ) daemon_functions;
2616   pr "  GUESTFS_PROC_NR_PROCS\n";
2617   pr "};\n";
2618   pr "\n";
2619
2620   (* Having to choose a maximum message size is annoying for several
2621    * reasons (it limits what we can do in the API), but it (a) makes
2622    * the protocol a lot simpler, and (b) provides a bound on the size
2623    * of the daemon which operates in limited memory space.  For large
2624    * file transfers you should use FTP.
2625    *)
2626   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
2627   pr "\n";
2628
2629   (* Message header, etc. *)
2630   pr "\
2631 /* The communication protocol is now documented in the guestfs(3)
2632  * manpage.
2633  */
2634
2635 const GUESTFS_PROGRAM = 0x2000F5F5;
2636 const GUESTFS_PROTOCOL_VERSION = 1;
2637
2638 /* These constants must be larger than any possible message length. */
2639 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
2640 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
2641
2642 enum guestfs_message_direction {
2643   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
2644   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
2645 };
2646
2647 enum guestfs_message_status {
2648   GUESTFS_STATUS_OK = 0,
2649   GUESTFS_STATUS_ERROR = 1
2650 };
2651
2652 const GUESTFS_ERROR_LEN = 256;
2653
2654 struct guestfs_message_error {
2655   string error_message<GUESTFS_ERROR_LEN>;
2656 };
2657
2658 struct guestfs_message_header {
2659   unsigned prog;                     /* GUESTFS_PROGRAM */
2660   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
2661   guestfs_procedure proc;            /* GUESTFS_PROC_x */
2662   guestfs_message_direction direction;
2663   unsigned serial;                   /* message serial number */
2664   guestfs_message_status status;
2665 };
2666
2667 const GUESTFS_MAX_CHUNK_SIZE = 8192;
2668
2669 struct guestfs_chunk {
2670   int cancel;                        /* if non-zero, transfer is cancelled */
2671   /* data size is 0 bytes if the transfer has finished successfully */
2672   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
2673 };
2674 "
2675
2676 (* Generate the guestfs-structs.h file. *)
2677 and generate_structs_h () =
2678   generate_header CStyle LGPLv2;
2679
2680   (* This is a public exported header file containing various
2681    * structures.  The structures are carefully written to have
2682    * exactly the same in-memory format as the XDR structures that
2683    * we use on the wire to the daemon.  The reason for creating
2684    * copies of these structures here is just so we don't have to
2685    * export the whole of guestfs_protocol.h (which includes much
2686    * unrelated and XDR-dependent stuff that we don't want to be
2687    * public, or required by clients).
2688    *
2689    * To reiterate, we will pass these structures to and from the
2690    * client with a simple assignment or memcpy, so the format
2691    * must be identical to what rpcgen / the RFC defines.
2692    *)
2693
2694   (* guestfs_int_bool structure. *)
2695   pr "struct guestfs_int_bool {\n";
2696   pr "  int32_t i;\n";
2697   pr "  int32_t b;\n";
2698   pr "};\n";
2699   pr "\n";
2700
2701   (* LVM public structures. *)
2702   List.iter (
2703     function
2704     | typ, cols ->
2705         pr "struct guestfs_lvm_%s {\n" typ;
2706         List.iter (
2707           function
2708           | name, `String -> pr "  char *%s;\n" name
2709           | name, `UUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
2710           | name, `Bytes -> pr "  uint64_t %s;\n" name
2711           | name, `Int -> pr "  int64_t %s;\n" name
2712           | name, `OptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
2713         ) cols;
2714         pr "};\n";
2715         pr "\n";
2716         pr "struct guestfs_lvm_%s_list {\n" typ;
2717         pr "  uint32_t len;\n";
2718         pr "  struct guestfs_lvm_%s *val;\n" typ;
2719         pr "};\n";
2720         pr "\n"
2721   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
2722
2723   (* Stat structures. *)
2724   List.iter (
2725     function
2726     | typ, cols ->
2727         pr "struct guestfs_%s {\n" typ;
2728         List.iter (
2729           function
2730           | name, `Int -> pr "  int64_t %s;\n" name
2731         ) cols;
2732         pr "};\n";
2733         pr "\n"
2734   ) ["stat", stat_cols; "statvfs", statvfs_cols]
2735
2736 (* Generate the guestfs-actions.h file. *)
2737 and generate_actions_h () =
2738   generate_header CStyle LGPLv2;
2739   List.iter (
2740     fun (shortname, style, _, _, _, _, _) ->
2741       let name = "guestfs_" ^ shortname in
2742       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
2743         name style
2744   ) all_functions
2745
2746 (* Generate the client-side dispatch stubs. *)
2747 and generate_client_actions () =
2748   generate_header CStyle LGPLv2;
2749
2750   pr "\
2751 #include <stdio.h>
2752 #include <stdlib.h>
2753
2754 #include \"guestfs.h\"
2755 #include \"guestfs_protocol.h\"
2756
2757 #define error guestfs_error
2758 #define perrorf guestfs_perrorf
2759 #define safe_malloc guestfs_safe_malloc
2760 #define safe_realloc guestfs_safe_realloc
2761 #define safe_strdup guestfs_safe_strdup
2762 #define safe_memdup guestfs_safe_memdup
2763
2764 /* Check the return message from a call for validity. */
2765 static int
2766 check_reply_header (guestfs_h *g,
2767                     const struct guestfs_message_header *hdr,
2768                     int proc_nr, int serial)
2769 {
2770   if (hdr->prog != GUESTFS_PROGRAM) {
2771     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
2772     return -1;
2773   }
2774   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
2775     error (g, \"wrong protocol version (%%d/%%d)\",
2776            hdr->vers, GUESTFS_PROTOCOL_VERSION);
2777     return -1;
2778   }
2779   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
2780     error (g, \"unexpected message direction (%%d/%%d)\",
2781            hdr->direction, GUESTFS_DIRECTION_REPLY);
2782     return -1;
2783   }
2784   if (hdr->proc != proc_nr) {
2785     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
2786     return -1;
2787   }
2788   if (hdr->serial != serial) {
2789     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
2790     return -1;
2791   }
2792
2793   return 0;
2794 }
2795
2796 /* Check we are in the right state to run a high-level action. */
2797 static int
2798 check_state (guestfs_h *g, const char *caller)
2799 {
2800   if (!guestfs_is_ready (g)) {
2801     if (guestfs_is_config (g))
2802       error (g, \"%%s: call launch() before using this function\",
2803         caller);
2804     else if (guestfs_is_launching (g))
2805       error (g, \"%%s: call wait_ready() before using this function\",
2806         caller);
2807     else
2808       error (g, \"%%s called from the wrong state, %%d != READY\",
2809         caller, guestfs_get_state (g));
2810     return -1;
2811   }
2812   return 0;
2813 }
2814
2815 ";
2816
2817   (* Client-side stubs for each function. *)
2818   List.iter (
2819     fun (shortname, style, _, _, _, _, _) ->
2820       let name = "guestfs_" ^ shortname in
2821
2822       (* Generate the context struct which stores the high-level
2823        * state between callback functions.
2824        *)
2825       pr "struct %s_ctx {\n" shortname;
2826       pr "  /* This flag is set by the callbacks, so we know we've done\n";
2827       pr "   * the callbacks as expected, and in the right sequence.\n";
2828       pr "   * 0 = not called, 1 = reply_cb called.\n";
2829       pr "   */\n";
2830       pr "  int cb_sequence;\n";
2831       pr "  struct guestfs_message_header hdr;\n";
2832       pr "  struct guestfs_message_error err;\n";
2833       (match fst style with
2834        | RErr -> ()
2835        | RConstString _ ->
2836            failwithf "RConstString cannot be returned from a daemon function"
2837        | RInt _ | RInt64 _
2838        | RBool _ | RString _ | RStringList _
2839        | RIntBool _
2840        | RPVList _ | RVGList _ | RLVList _
2841        | RStat _ | RStatVFS _
2842        | RHashtable _ ->
2843            pr "  struct %s_ret ret;\n" name
2844       );
2845       pr "};\n";
2846       pr "\n";
2847
2848       (* Generate the reply callback function. *)
2849       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
2850       pr "{\n";
2851       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
2852       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
2853       pr "\n";
2854       pr "  /* This should definitely not happen. */\n";
2855       pr "  if (ctx->cb_sequence != 0) {\n";
2856       pr "    ctx->cb_sequence = 9999;\n";
2857       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
2858       pr "    return;\n";
2859       pr "  }\n";
2860       pr "\n";
2861       pr "  ml->main_loop_quit (ml, g);\n";
2862       pr "\n";
2863       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
2864       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
2865       pr "    return;\n";
2866       pr "  }\n";
2867       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
2868       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
2869       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
2870         name;
2871       pr "      return;\n";
2872       pr "    }\n";
2873       pr "    goto done;\n";
2874       pr "  }\n";
2875
2876       (match fst style with
2877        | RErr -> ()
2878        | RConstString _ ->
2879            failwithf "RConstString cannot be returned from a daemon function"
2880        | RInt _ | RInt64 _
2881        | RBool _ | RString _ | RStringList _
2882        | RIntBool _
2883        | RPVList _ | RVGList _ | RLVList _
2884        | RStat _ | RStatVFS _
2885        | RHashtable _ ->
2886             pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
2887             pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
2888             pr "    return;\n";
2889             pr "  }\n";
2890       );
2891
2892       pr " done:\n";
2893       pr "  ctx->cb_sequence = 1;\n";
2894       pr "}\n\n";
2895
2896       (* Generate the action stub. *)
2897       generate_prototype ~extern:false ~semicolon:false ~newline:true
2898         ~handle:"g" name style;
2899
2900       let error_code =
2901         match fst style with
2902         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
2903         | RConstString _ ->
2904             failwithf "RConstString cannot be returned from a daemon function"
2905         | RString _ | RStringList _ | RIntBool _
2906         | RPVList _ | RVGList _ | RLVList _
2907         | RStat _ | RStatVFS _
2908         | RHashtable _ ->
2909             "NULL" in
2910
2911       pr "{\n";
2912
2913       (match snd style with
2914        | [] -> ()
2915        | _ -> pr "  struct %s_args args;\n" name
2916       );
2917
2918       pr "  struct %s_ctx ctx;\n" shortname;
2919       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
2920       pr "  int serial;\n";
2921       pr "\n";
2922       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
2923       pr "  guestfs_set_busy (g);\n";
2924       pr "\n";
2925       pr "  memset (&ctx, 0, sizeof ctx);\n";
2926       pr "\n";
2927
2928       (* Send the main header and arguments. *)
2929       (match snd style with
2930        | [] ->
2931            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
2932              (String.uppercase shortname)
2933        | args ->
2934            List.iter (
2935              function
2936              | String n ->
2937                  pr "  args.%s = (char *) %s;\n" n n
2938              | OptString n ->
2939                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
2940              | StringList n ->
2941                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
2942                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
2943              | Bool n ->
2944                  pr "  args.%s = %s;\n" n n
2945              | Int n ->
2946                  pr "  args.%s = %s;\n" n n
2947              | FileIn _ | FileOut _ -> ()
2948            ) args;
2949            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
2950              (String.uppercase shortname);
2951            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
2952              name;
2953       );
2954       pr "  if (serial == -1) {\n";
2955       pr "    guestfs_end_busy (g);\n";
2956       pr "    return %s;\n" error_code;
2957       pr "  }\n";
2958       pr "\n";
2959
2960       (* Send any additional files (FileIn) requested. *)
2961       let need_read_reply_label = ref false in
2962       List.iter (
2963         function
2964         | FileIn n ->
2965             pr "  {\n";
2966             pr "    int r;\n";
2967             pr "\n";
2968             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
2969             pr "    if (r == -1) {\n";
2970             pr "      guestfs_end_busy (g);\n";
2971             pr "      return %s;\n" error_code;
2972             pr "    }\n";
2973             pr "    if (r == -2) /* daemon cancelled */\n";
2974             pr "      goto read_reply;\n";
2975             need_read_reply_label := true;
2976             pr "  }\n";
2977             pr "\n";
2978         | _ -> ()
2979       ) (snd style);
2980
2981       (* Wait for the reply from the remote end. *)
2982       if !need_read_reply_label then pr " read_reply:\n";
2983       pr "  guestfs__switch_to_receiving (g);\n";
2984       pr "  ctx.cb_sequence = 0;\n";
2985       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
2986       pr "  (void) ml->main_loop_run (ml, g);\n";
2987       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
2988       pr "  if (ctx.cb_sequence != 1) {\n";
2989       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
2990       pr "    guestfs_end_busy (g);\n";
2991       pr "    return %s;\n" error_code;
2992       pr "  }\n";
2993       pr "\n";
2994
2995       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
2996         (String.uppercase shortname);
2997       pr "    guestfs_end_busy (g);\n";
2998       pr "    return %s;\n" error_code;
2999       pr "  }\n";
3000       pr "\n";
3001
3002       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
3003       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
3004       pr "    free (ctx.err.error_message);\n";
3005       pr "    guestfs_end_busy (g);\n";
3006       pr "    return %s;\n" error_code;
3007       pr "  }\n";
3008       pr "\n";
3009
3010       (* Expecting to receive further files (FileOut)? *)
3011       List.iter (
3012         function
3013         | FileOut n ->
3014             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
3015             pr "    guestfs_end_busy (g);\n";
3016             pr "    return %s;\n" error_code;
3017             pr "  }\n";
3018             pr "\n";
3019         | _ -> ()
3020       ) (snd style);
3021
3022       pr "  guestfs_end_busy (g);\n";
3023
3024       (match fst style with
3025        | RErr -> pr "  return 0;\n"
3026        | RInt n | RInt64 n | RBool n ->
3027            pr "  return ctx.ret.%s;\n" n
3028        | RConstString _ ->
3029            failwithf "RConstString cannot be returned from a daemon function"
3030        | RString n ->
3031            pr "  return ctx.ret.%s; /* caller will free */\n" n
3032        | RStringList n | RHashtable n ->
3033            pr "  /* caller will free this, but we need to add a NULL entry */\n";
3034            pr "  ctx.ret.%s.%s_val =\n" n n;
3035            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
3036            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
3037              n n;
3038            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
3039            pr "  return ctx.ret.%s.%s_val;\n" n n
3040        | RIntBool _ ->
3041            pr "  /* caller with free this */\n";
3042            pr "  return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));\n"
3043        | RPVList n | RVGList n | RLVList n
3044        | RStat n | RStatVFS n ->
3045            pr "  /* caller will free this */\n";
3046            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
3047       );
3048
3049       pr "}\n\n"
3050   ) daemon_functions
3051
3052 (* Generate daemon/actions.h. *)
3053 and generate_daemon_actions_h () =
3054   generate_header CStyle GPLv2;
3055
3056   pr "#include \"../src/guestfs_protocol.h\"\n";
3057   pr "\n";
3058
3059   List.iter (
3060     fun (name, style, _, _, _, _, _) ->
3061         generate_prototype
3062           ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
3063           name style;
3064   ) daemon_functions
3065
3066 (* Generate the server-side stubs. *)
3067 and generate_daemon_actions () =
3068   generate_header CStyle GPLv2;
3069
3070   pr "#include <config.h>\n";
3071   pr "\n";
3072   pr "#include <stdio.h>\n";
3073   pr "#include <stdlib.h>\n";
3074   pr "#include <string.h>\n";
3075   pr "#include <inttypes.h>\n";
3076   pr "#include <ctype.h>\n";
3077   pr "#include <rpc/types.h>\n";
3078   pr "#include <rpc/xdr.h>\n";
3079   pr "\n";
3080   pr "#include \"daemon.h\"\n";
3081   pr "#include \"../src/guestfs_protocol.h\"\n";
3082   pr "#include \"actions.h\"\n";
3083   pr "\n";
3084
3085   List.iter (
3086     fun (name, style, _, _, _, _, _) ->
3087       (* Generate server-side stubs. *)
3088       pr "static void %s_stub (XDR *xdr_in)\n" name;
3089       pr "{\n";
3090       let error_code =
3091         match fst style with
3092         | RErr | RInt _ -> pr "  int r;\n"; "-1"
3093         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
3094         | RBool _ -> pr "  int r;\n"; "-1"
3095         | RConstString _ ->
3096             failwithf "RConstString cannot be returned from a daemon function"
3097         | RString _ -> pr "  char *r;\n"; "NULL"
3098         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
3099         | RIntBool _ -> pr "  guestfs_%s_ret *r;\n" name; "NULL"
3100         | RPVList _ -> pr "  guestfs_lvm_int_pv_list *r;\n"; "NULL"
3101         | RVGList _ -> pr "  guestfs_lvm_int_vg_list *r;\n"; "NULL"
3102         | RLVList _ -> pr "  guestfs_lvm_int_lv_list *r;\n"; "NULL"
3103         | RStat _ -> pr "  guestfs_int_stat *r;\n"; "NULL"
3104         | RStatVFS _ -> pr "  guestfs_int_statvfs *r;\n"; "NULL" in
3105
3106       (match snd style with
3107        | [] -> ()
3108        | args ->
3109            pr "  struct guestfs_%s_args args;\n" name;
3110            List.iter (
3111              function
3112              | String n
3113              | OptString n -> pr "  const char *%s;\n" n
3114              | StringList n -> pr "  char **%s;\n" n
3115              | Bool n -> pr "  int %s;\n" n
3116              | Int n -> pr "  int %s;\n" n
3117              | FileIn _ | FileOut _ -> ()
3118            ) args
3119       );
3120       pr "\n";
3121
3122       (match snd style with
3123        | [] -> ()
3124        | args ->
3125            pr "  memset (&args, 0, sizeof args);\n";
3126            pr "\n";
3127            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
3128            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
3129            pr "    return;\n";
3130            pr "  }\n";
3131            List.iter (
3132              function
3133              | String n -> pr "  %s = args.%s;\n" n n
3134              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
3135              | StringList n ->
3136                  pr "  %s = realloc (args.%s.%s_val,\n" n n n;
3137                  pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
3138                  pr "  if (%s == NULL) {\n" n;
3139                  pr "    reply_with_perror (\"realloc\");\n";
3140                  pr "    goto done;\n";
3141                  pr "  }\n";
3142                  pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
3143                  pr "  args.%s.%s_val = %s;\n" n n n;
3144              | Bool n -> pr "  %s = args.%s;\n" n n
3145              | Int n -> pr "  %s = args.%s;\n" n n
3146              | FileIn _ | FileOut _ -> ()
3147            ) args;
3148            pr "\n"
3149       );
3150
3151       (* Don't want to call the impl with any FileIn or FileOut
3152        * parameters, since these go "outside" the RPC protocol.
3153        *)
3154       let argsnofile =
3155         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
3156           (snd style) in
3157       pr "  r = do_%s " name;
3158       generate_call_args argsnofile;
3159       pr ";\n";
3160
3161       pr "  if (r == %s)\n" error_code;
3162       pr "    /* do_%s has already called reply_with_error */\n" name;
3163       pr "    goto done;\n";
3164       pr "\n";
3165
3166       (* If there are any FileOut parameters, then the impl must
3167        * send its own reply.
3168        *)
3169       let no_reply =
3170         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
3171       if no_reply then
3172         pr "  /* do_%s has already sent a reply */\n" name
3173       else (
3174         match fst style with
3175         | RErr -> pr "  reply (NULL, NULL);\n"
3176         | RInt n | RInt64 n | RBool n ->
3177             pr "  struct guestfs_%s_ret ret;\n" name;
3178             pr "  ret.%s = r;\n" n;
3179             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3180               name
3181         | RConstString _ ->
3182             failwithf "RConstString cannot be returned from a daemon function"
3183         | RString n ->
3184             pr "  struct guestfs_%s_ret ret;\n" name;
3185             pr "  ret.%s = r;\n" n;
3186             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3187               name;
3188             pr "  free (r);\n"
3189         | RStringList n | RHashtable n ->
3190             pr "  struct guestfs_%s_ret ret;\n" name;
3191             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
3192             pr "  ret.%s.%s_val = r;\n" n n;
3193             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
3194               name;
3195             pr "  free_strings (r);\n"
3196         | RIntBool _ ->
3197             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n"
3198               name;
3199             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
3200         | RPVList n | RVGList n | RLVList n
3201         | RStat n | RStatVFS n ->
3202             pr "  struct guestfs_%s_ret ret;\n" name;
3203             pr "  ret.%s = *r;\n" n;
3204             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
3205               name;
3206             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
3207               name
3208       );
3209
3210       (* Free the args. *)
3211       (match snd style with
3212        | [] ->
3213            pr "done: ;\n";
3214        | _ ->
3215            pr "done:\n";
3216            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
3217              name
3218       );
3219
3220       pr "}\n\n";
3221   ) daemon_functions;
3222
3223   (* Dispatch function. *)
3224   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
3225   pr "{\n";
3226   pr "  switch (proc_nr) {\n";
3227
3228   List.iter (
3229     fun (name, style, _, _, _, _, _) ->
3230         pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
3231         pr "      %s_stub (xdr_in);\n" name;
3232         pr "      break;\n"
3233   ) daemon_functions;
3234
3235   pr "    default:\n";
3236   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
3237   pr "  }\n";
3238   pr "}\n";
3239   pr "\n";
3240
3241   (* LVM columns and tokenization functions. *)
3242   (* XXX This generates crap code.  We should rethink how we
3243    * do this parsing.
3244    *)
3245   List.iter (
3246     function
3247     | typ, cols ->
3248         pr "static const char *lvm_%s_cols = \"%s\";\n"
3249           typ (String.concat "," (List.map fst cols));
3250         pr "\n";
3251
3252         pr "static int lvm_tokenize_%s (char *str, struct guestfs_lvm_int_%s *r)\n" typ typ;
3253         pr "{\n";
3254         pr "  char *tok, *p, *next;\n";
3255         pr "  int i, j;\n";
3256         pr "\n";
3257         (*
3258         pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
3259         pr "\n";
3260         *)
3261         pr "  if (!str) {\n";
3262         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
3263         pr "    return -1;\n";
3264         pr "  }\n";
3265         pr "  if (!*str || isspace (*str)) {\n";
3266         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
3267         pr "    return -1;\n";
3268         pr "  }\n";
3269         pr "  tok = str;\n";
3270         List.iter (
3271           fun (name, coltype) ->
3272             pr "  if (!tok) {\n";
3273             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
3274             pr "    return -1;\n";
3275             pr "  }\n";
3276             pr "  p = strchrnul (tok, ',');\n";
3277             pr "  if (*p) next = p+1; else next = NULL;\n";
3278             pr "  *p = '\\0';\n";
3279             (match coltype with
3280              | `String ->
3281                  pr "  r->%s = strdup (tok);\n" name;
3282                  pr "  if (r->%s == NULL) {\n" name;
3283                  pr "    perror (\"strdup\");\n";
3284                  pr "    return -1;\n";
3285                  pr "  }\n"
3286              | `UUID ->
3287                  pr "  for (i = j = 0; i < 32; ++j) {\n";
3288                  pr "    if (tok[j] == '\\0') {\n";
3289                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
3290                  pr "      return -1;\n";
3291                  pr "    } else if (tok[j] != '-')\n";
3292                  pr "      r->%s[i++] = tok[j];\n" name;
3293                  pr "  }\n";
3294              | `Bytes ->
3295                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
3296                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3297                  pr "    return -1;\n";
3298                  pr "  }\n";
3299              | `Int ->
3300                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
3301                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3302                  pr "    return -1;\n";
3303                  pr "  }\n";
3304              | `OptPercent ->
3305                  pr "  if (tok[0] == '\\0')\n";
3306                  pr "    r->%s = -1;\n" name;
3307                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
3308                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
3309                  pr "    return -1;\n";
3310                  pr "  }\n";
3311             );
3312             pr "  tok = next;\n";
3313         ) cols;
3314
3315         pr "  if (tok != NULL) {\n";
3316         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
3317         pr "    return -1;\n";
3318         pr "  }\n";
3319         pr "  return 0;\n";
3320         pr "}\n";
3321         pr "\n";
3322
3323         pr "guestfs_lvm_int_%s_list *\n" typ;
3324         pr "parse_command_line_%ss (void)\n" typ;
3325         pr "{\n";
3326         pr "  char *out, *err;\n";
3327         pr "  char *p, *pend;\n";
3328         pr "  int r, i;\n";
3329         pr "  guestfs_lvm_int_%s_list *ret;\n" typ;
3330         pr "  void *newp;\n";
3331         pr "\n";
3332         pr "  ret = malloc (sizeof *ret);\n";
3333         pr "  if (!ret) {\n";
3334         pr "    reply_with_perror (\"malloc\");\n";
3335         pr "    return NULL;\n";
3336         pr "  }\n";
3337         pr "\n";
3338         pr "  ret->guestfs_lvm_int_%s_list_len = 0;\n" typ;
3339         pr "  ret->guestfs_lvm_int_%s_list_val = NULL;\n" typ;
3340         pr "\n";
3341         pr "  r = command (&out, &err,\n";
3342         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
3343         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
3344         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
3345         pr "  if (r == -1) {\n";
3346         pr "    reply_with_error (\"%%s\", err);\n";
3347         pr "    free (out);\n";
3348         pr "    free (err);\n";
3349         pr "    free (ret);\n";
3350         pr "    return NULL;\n";
3351         pr "  }\n";
3352         pr "\n";
3353         pr "  free (err);\n";
3354         pr "\n";
3355         pr "  /* Tokenize each line of the output. */\n";
3356         pr "  p = out;\n";
3357         pr "  i = 0;\n";
3358         pr "  while (p) {\n";
3359         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
3360         pr "    if (pend) {\n";
3361         pr "      *pend = '\\0';\n";
3362         pr "      pend++;\n";
3363         pr "    }\n";
3364         pr "\n";
3365         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
3366         pr "      p++;\n";
3367         pr "\n";
3368         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
3369         pr "      p = pend;\n";
3370         pr "      continue;\n";
3371         pr "    }\n";
3372         pr "\n";
3373         pr "    /* Allocate some space to store this next entry. */\n";
3374         pr "    newp = realloc (ret->guestfs_lvm_int_%s_list_val,\n" typ;
3375         pr "                sizeof (guestfs_lvm_int_%s) * (i+1));\n" typ;
3376         pr "    if (newp == NULL) {\n";
3377         pr "      reply_with_perror (\"realloc\");\n";
3378         pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
3379         pr "      free (ret);\n";
3380         pr "      free (out);\n";
3381         pr "      return NULL;\n";
3382         pr "    }\n";
3383         pr "    ret->guestfs_lvm_int_%s_list_val = newp;\n" typ;
3384         pr "\n";
3385         pr "    /* Tokenize the next entry. */\n";
3386         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_lvm_int_%s_list_val[i]);\n" typ typ;
3387         pr "    if (r == -1) {\n";
3388         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
3389         pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
3390         pr "      free (ret);\n";
3391         pr "      free (out);\n";
3392         pr "      return NULL;\n";
3393         pr "    }\n";
3394         pr "\n";
3395         pr "    ++i;\n";
3396         pr "    p = pend;\n";
3397         pr "  }\n";
3398         pr "\n";
3399         pr "  ret->guestfs_lvm_int_%s_list_len = i;\n" typ;
3400         pr "\n";
3401         pr "  free (out);\n";
3402         pr "  return ret;\n";
3403         pr "}\n"
3404
3405   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
3406
3407 (* Generate the tests. *)
3408 and generate_tests () =
3409   generate_header CStyle GPLv2;
3410
3411   pr "\
3412 #include <stdio.h>
3413 #include <stdlib.h>
3414 #include <string.h>
3415 #include <unistd.h>
3416 #include <sys/types.h>
3417 #include <fcntl.h>
3418
3419 #include \"guestfs.h\"
3420
3421 static guestfs_h *g;
3422 static int suppress_error = 0;
3423
3424 /* This will be 's' or 'h' depending on whether the guest kernel
3425  * names IDE devices /dev/sd* or /dev/hd*.
3426  */
3427 static char devchar = 's';
3428
3429 static void print_error (guestfs_h *g, void *data, const char *msg)
3430 {
3431   if (!suppress_error)
3432     fprintf (stderr, \"%%s\\n\", msg);
3433 }
3434
3435 static void print_strings (char * const * const argv)
3436 {
3437   int argc;
3438
3439   for (argc = 0; argv[argc] != NULL; ++argc)
3440     printf (\"\\t%%s\\n\", argv[argc]);
3441 }
3442
3443 /*
3444 static void print_table (char * const * const argv)
3445 {
3446   int i;
3447
3448   for (i = 0; argv[i] != NULL; i += 2)
3449     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
3450 }
3451 */
3452
3453 static void no_test_warnings (void)
3454 {
3455 ";
3456
3457   List.iter (
3458     function
3459     | name, _, _, _, [], _, _ ->
3460         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
3461     | name, _, _, _, tests, _, _ -> ()
3462   ) all_functions;
3463
3464   pr "}\n";
3465   pr "\n";
3466
3467   (* Generate the actual tests.  Note that we generate the tests
3468    * in reverse order, deliberately, so that (in general) the
3469    * newest tests run first.  This makes it quicker and easier to
3470    * debug them.
3471    *)
3472   let test_names =
3473     List.map (
3474       fun (name, _, _, _, tests, _, _) ->
3475         mapi (generate_one_test name) tests
3476     ) (List.rev all_functions) in
3477   let test_names = List.concat test_names in
3478   let nr_tests = List.length test_names in
3479
3480   pr "\
3481 int main (int argc, char *argv[])
3482 {
3483   char c = 0;
3484   int failed = 0;
3485   const char *srcdir;
3486   const char *filename;
3487   int fd, i;
3488   int nr_tests, test_num = 0;
3489   char **devs;
3490
3491   no_test_warnings ();
3492
3493   g = guestfs_create ();
3494   if (g == NULL) {
3495     printf (\"guestfs_create FAILED\\n\");
3496     exit (1);
3497   }
3498
3499   guestfs_set_error_handler (g, print_error, NULL);
3500
3501   srcdir = getenv (\"srcdir\");
3502   if (!srcdir) srcdir = \".\";
3503   chdir (srcdir);
3504   guestfs_set_path (g, \".\");
3505
3506   filename = \"test1.img\";
3507   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3508   if (fd == -1) {
3509     perror (filename);
3510     exit (1);
3511   }
3512   if (lseek (fd, %d, SEEK_SET) == -1) {
3513     perror (\"lseek\");
3514     close (fd);
3515     unlink (filename);
3516     exit (1);
3517   }
3518   if (write (fd, &c, 1) == -1) {
3519     perror (\"write\");
3520     close (fd);
3521     unlink (filename);
3522     exit (1);
3523   }
3524   if (close (fd) == -1) {
3525     perror (filename);
3526     unlink (filename);
3527     exit (1);
3528   }
3529   if (guestfs_add_drive (g, filename) == -1) {
3530     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3531     exit (1);
3532   }
3533
3534   filename = \"test2.img\";
3535   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3536   if (fd == -1) {
3537     perror (filename);
3538     exit (1);
3539   }
3540   if (lseek (fd, %d, SEEK_SET) == -1) {
3541     perror (\"lseek\");
3542     close (fd);
3543     unlink (filename);
3544     exit (1);
3545   }
3546   if (write (fd, &c, 1) == -1) {
3547     perror (\"write\");
3548     close (fd);
3549     unlink (filename);
3550     exit (1);
3551   }
3552   if (close (fd) == -1) {
3553     perror (filename);
3554     unlink (filename);
3555     exit (1);
3556   }
3557   if (guestfs_add_drive (g, filename) == -1) {
3558     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3559     exit (1);
3560   }
3561
3562   filename = \"test3.img\";
3563   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
3564   if (fd == -1) {
3565     perror (filename);
3566     exit (1);
3567   }
3568   if (lseek (fd, %d, SEEK_SET) == -1) {
3569     perror (\"lseek\");
3570     close (fd);
3571     unlink (filename);
3572     exit (1);
3573   }
3574   if (write (fd, &c, 1) == -1) {
3575     perror (\"write\");
3576     close (fd);
3577     unlink (filename);
3578     exit (1);
3579   }
3580   if (close (fd) == -1) {
3581     perror (filename);
3582     unlink (filename);
3583     exit (1);
3584   }
3585   if (guestfs_add_drive (g, filename) == -1) {
3586     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
3587     exit (1);
3588   }
3589
3590   if (guestfs_launch (g) == -1) {
3591     printf (\"guestfs_launch FAILED\\n\");
3592     exit (1);
3593   }
3594   if (guestfs_wait_ready (g) == -1) {
3595     printf (\"guestfs_wait_ready FAILED\\n\");
3596     exit (1);
3597   }
3598
3599   /* Detect if the appliance uses /dev/sd* or /dev/hd* in device
3600    * names.  This changed between RHEL 5 and RHEL 6 so we have to
3601    * support both.
3602    */
3603   devs = guestfs_list_devices (g);
3604   if (devs == NULL || devs[0] == NULL) {
3605     printf (\"guestfs_list_devices FAILED\\n\");
3606     exit (1);
3607   }
3608   if (strncmp (devs[0], \"/dev/sd\", 7) == 0)
3609     devchar = 's';
3610   else if (strncmp (devs[0], \"/dev/hd\", 7) == 0)
3611     devchar = 'h';
3612   else {
3613     printf (\"guestfs_list_devices returned unexpected string '%%s'\\n\",
3614             devs[0]);
3615     exit (1);
3616   }
3617   for (i = 0; devs[i] != NULL; ++i)
3618     free (devs[i]);
3619   free (devs);
3620
3621   nr_tests = %d;
3622
3623 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
3624
3625   iteri (
3626     fun i test_name ->
3627       pr "  test_num++;\n";
3628       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
3629       pr "  if (%s () == -1) {\n" test_name;
3630       pr "    printf (\"%s FAILED\\n\");\n" test_name;
3631       pr "    failed++;\n";
3632       pr "  }\n";
3633   ) test_names;
3634   pr "\n";
3635
3636   pr "  guestfs_close (g);\n";
3637   pr "  unlink (\"test1.img\");\n";
3638   pr "  unlink (\"test2.img\");\n";
3639   pr "  unlink (\"test3.img\");\n";
3640   pr "\n";
3641
3642   pr "  if (failed > 0) {\n";
3643   pr "    printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
3644   pr "    exit (1);\n";
3645   pr "  }\n";
3646   pr "\n";
3647
3648   pr "  exit (0);\n";
3649   pr "}\n"
3650
3651 and generate_one_test name i (init, test) =
3652   let test_name = sprintf "test_%s_%d" name i in
3653
3654   pr "static int %s (void)\n" test_name;
3655   pr "{\n";
3656
3657   (match init with
3658    | InitNone -> ()
3659    | InitEmpty ->
3660        pr "  /* InitEmpty for %s (%d) */\n" name i;
3661        List.iter (generate_test_command_call test_name)
3662          [["blockdev_setrw"; "/dev/sda"];
3663           ["umount_all"];
3664           ["lvm_remove_all"]]