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