availability: Add guestfs_available.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Unix
39 open Printf
40
41 type style = ret * args
42 and ret =
43     (* "RErr" as a return value means an int used as a simple error
44      * indication, ie. 0 or -1.
45      *)
46   | RErr
47
48     (* "RInt" as a return value means an int which is -1 for error
49      * or any value >= 0 on success.  Only use this for smallish
50      * positive ints (0 <= i < 2^30).
51      *)
52   | RInt of string
53
54     (* "RInt64" is the same as RInt, but is guaranteed to be able
55      * to return a full 64 bit value, _except_ that -1 means error
56      * (so -1 cannot be a valid, non-error return value).
57      *)
58   | RInt64 of string
59
60     (* "RBool" is a bool return value which can be true/false or
61      * -1 for error.
62      *)
63   | RBool of string
64
65     (* "RConstString" is a string that refers to a constant value.
66      * The return value must NOT be NULL (since NULL indicates
67      * an error).
68      *
69      * Try to avoid using this.  In particular you cannot use this
70      * for values returned from the daemon, because there is no
71      * thread-safe way to return them in the C API.
72      *)
73   | RConstString of string
74
75     (* "RConstOptString" is an even more broken version of
76      * "RConstString".  The returned string may be NULL and there
77      * is no way to return an error indication.  Avoid using this!
78      *)
79   | RConstOptString of string
80
81     (* "RString" is a returned string.  It must NOT be NULL, since
82      * a NULL return indicates an error.  The caller frees this.
83      *)
84   | RString of string
85
86     (* "RStringList" is a list of strings.  No string in the list
87      * can be NULL.  The caller frees the strings and the array.
88      *)
89   | RStringList of string
90
91     (* "RStruct" is a function which returns a single named structure
92      * or an error indication (in C, a struct, and in other languages
93      * with varying representations, but usually very efficient).  See
94      * after the function list below for the structures.
95      *)
96   | RStruct of string * string          (* name of retval, name of struct *)
97
98     (* "RStructList" is a function which returns either a list/array
99      * of structures (could be zero-length), or an error indication.
100      *)
101   | RStructList of string * string      (* name of retval, name of struct *)
102
103     (* Key-value pairs of untyped strings.  Turns into a hashtable or
104      * dictionary in languages which support it.  DON'T use this as a
105      * general "bucket" for results.  Prefer a stronger typed return
106      * value if one is available, or write a custom struct.  Don't use
107      * this if the list could potentially be very long, since it is
108      * inefficient.  Keys should be unique.  NULLs are not permitted.
109      *)
110   | RHashtable of string
111
112     (* "RBufferOut" is handled almost exactly like RString, but
113      * it allows the string to contain arbitrary 8 bit data including
114      * ASCII NUL.  In the C API this causes an implicit extra parameter
115      * to be added of type <size_t *size_r>.  The extra parameter
116      * returns the actual size of the return buffer in bytes.
117      *
118      * Other programming languages support strings with arbitrary 8 bit
119      * data.
120      *
121      * At the RPC layer we have to use the opaque<> type instead of
122      * string<>.  Returned data is still limited to the max message
123      * size (ie. ~ 2 MB).
124      *)
125   | RBufferOut of string
126
127 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
128
129     (* Note in future we should allow a "variable args" parameter as
130      * the final parameter, to allow commands like
131      *   chmod mode file [file(s)...]
132      * This is not implemented yet, but many commands (such as chmod)
133      * are currently defined with the argument order keeping this future
134      * possibility in mind.
135      *)
136 and argt =
137   | String of string    (* const char *name, cannot be NULL *)
138   | Device of string    (* /dev device name, cannot be NULL *)
139   | Pathname of string  (* file name, cannot be NULL *)
140   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
141   | OptString of string (* const char *name, may be NULL *)
142   | StringList of string(* list of strings (each string cannot be NULL) *)
143   | DeviceList of string(* list of Device names (each cannot be NULL) *)
144   | Bool of string      (* boolean *)
145   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
146   | Int64 of string     (* any 64 bit int *)
147     (* These are treated as filenames (simple string parameters) in
148      * the C API and bindings.  But in the RPC protocol, we transfer
149      * the actual file content up to or down from the daemon.
150      * FileIn: local machine -> daemon (in request)
151      * FileOut: daemon -> local machine (in reply)
152      * In guestfish (only), the special name "-" means read from
153      * stdin or write to stdout.
154      *)
155   | FileIn of string
156   | FileOut of string
157 (* Not implemented:
158     (* Opaque buffer which can contain arbitrary 8 bit data.
159      * In the C API, this is expressed as <char *, int> pair.
160      * Most other languages have a string type which can contain
161      * ASCII NUL.  We use whatever type is appropriate for each
162      * language.
163      * Buffers are limited by the total message size.  To transfer
164      * large blocks of data, use FileIn/FileOut parameters instead.
165      * To return an arbitrary buffer, use RBufferOut.
166      *)
167   | BufferIn of string
168 *)
169
170 type flags =
171   | ProtocolLimitWarning  (* display warning about protocol size limits *)
172   | DangerWillRobinson    (* flags particularly dangerous commands *)
173   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
174   | FishAction of string  (* call this function in guestfish *)
175   | NotInFish             (* do not export via guestfish *)
176   | NotInDocs             (* do not add this function to documentation *)
177   | DeprecatedBy of string (* function is deprecated, use .. instead *)
178
179 (* You can supply zero or as many tests as you want per API call.
180  *
181  * Note that the test environment has 3 block devices, of size 500MB,
182  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
183  * a fourth ISO block device with some known files on it (/dev/sdd).
184  *
185  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
186  * Number of cylinders was 63 for IDE emulated disks with precisely
187  * the same size.  How exactly this is calculated is a mystery.
188  *
189  * The ISO block device (/dev/sdd) comes from images/test.iso.
190  *
191  * To be able to run the tests in a reasonable amount of time,
192  * the virtual machine and block devices are reused between tests.
193  * So don't try testing kill_subprocess :-x
194  *
195  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
196  *
197  * Don't assume anything about the previous contents of the block
198  * devices.  Use 'Init*' to create some initial scenarios.
199  *
200  * You can add a prerequisite clause to any individual test.  This
201  * is a run-time check, which, if it fails, causes the test to be
202  * skipped.  Useful if testing a command which might not work on
203  * all variations of libguestfs builds.  A test that has prerequisite
204  * of 'Always' is run unconditionally.
205  *
206  * In addition, packagers can skip individual tests by setting the
207  * environment variables:     eg:
208  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
209  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
210  *)
211 type tests = (test_init * test_prereq * test) list
212 and test =
213     (* Run the command sequence and just expect nothing to fail. *)
214   | TestRun of seq
215
216     (* Run the command sequence and expect the output of the final
217      * command to be the string.
218      *)
219   | TestOutput of seq * string
220
221     (* Run the command sequence and expect the output of the final
222      * command to be the list of strings.
223      *)
224   | TestOutputList of seq * string list
225
226     (* Run the command sequence and expect the output of the final
227      * command to be the list of block devices (could be either
228      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
229      * character of each string).
230      *)
231   | TestOutputListOfDevices of seq * string list
232
233     (* Run the command sequence and expect the output of the final
234      * command to be the integer.
235      *)
236   | TestOutputInt of seq * int
237
238     (* Run the command sequence and expect the output of the final
239      * command to be <op> <int>, eg. ">=", "1".
240      *)
241   | TestOutputIntOp of seq * string * int
242
243     (* Run the command sequence and expect the output of the final
244      * command to be a true value (!= 0 or != NULL).
245      *)
246   | TestOutputTrue of seq
247
248     (* Run the command sequence and expect the output of the final
249      * command to be a false value (== 0 or == NULL, but not an error).
250      *)
251   | TestOutputFalse of seq
252
253     (* Run the command sequence and expect the output of the final
254      * command to be a list of the given length (but don't care about
255      * content).
256      *)
257   | TestOutputLength of seq * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a buffer (RBufferOut), ie. string + size.
261      *)
262   | TestOutputBuffer of seq * string
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a structure.
266      *)
267   | TestOutputStruct of seq * test_field_compare list
268
269     (* Run the command sequence and expect the final command (only)
270      * to fail.
271      *)
272   | TestLastFail of seq
273
274 and test_field_compare =
275   | CompareWithInt of string * int
276   | CompareWithIntOp of string * string * int
277   | CompareWithString of string * string
278   | CompareFieldsIntEq of string * string
279   | CompareFieldsStrEq of string * string
280
281 (* Test prerequisites. *)
282 and test_prereq =
283     (* Test always runs. *)
284   | Always
285
286     (* Test is currently disabled - eg. it fails, or it tests some
287      * unimplemented feature.
288      *)
289   | Disabled
290
291     (* 'string' is some C code (a function body) that should return
292      * true or false.  The test will run if the code returns true.
293      *)
294   | If of string
295
296     (* As for 'If' but the test runs _unless_ the code returns true. *)
297   | Unless of string
298
299 (* Some initial scenarios for testing. *)
300 and test_init =
301     (* Do nothing, block devices could contain random stuff including
302      * LVM PVs, and some filesystems might be mounted.  This is usually
303      * a bad idea.
304      *)
305   | InitNone
306
307     (* Block devices are empty and no filesystems are mounted. *)
308   | InitEmpty
309
310     (* /dev/sda contains a single partition /dev/sda1, with random
311      * content.  /dev/sdb and /dev/sdc may have random content.
312      * No LVM.
313      *)
314   | InitPartition
315
316     (* /dev/sda contains a single partition /dev/sda1, which is formatted
317      * as ext2, empty [except for lost+found] and mounted on /.
318      * /dev/sdb and /dev/sdc may have random content.
319      * No LVM.
320      *)
321   | InitBasicFS
322
323     (* /dev/sda:
324      *   /dev/sda1 (is a PV):
325      *     /dev/VG/LV (size 8MB):
326      *       formatted as ext2, empty [except for lost+found], mounted on /
327      * /dev/sdb and /dev/sdc may have random content.
328      *)
329   | InitBasicFSonLVM
330
331     (* /dev/sdd (the ISO, see images/ directory in source)
332      * is mounted on /
333      *)
334   | InitISOFS
335
336 (* Sequence of commands for testing. *)
337 and seq = cmd list
338 and cmd = string list
339
340 (* Note about long descriptions: When referring to another
341  * action, use the format C<guestfs_other> (ie. the full name of
342  * the C function).  This will be replaced as appropriate in other
343  * language bindings.
344  *
345  * Apart from that, long descriptions are just perldoc paragraphs.
346  *)
347
348 (* Generate a random UUID (used in tests). *)
349 let uuidgen () =
350   let chan = open_process_in "uuidgen" in
351   let uuid = input_line chan in
352   (match close_process_in chan with
353    | WEXITED 0 -> ()
354    | WEXITED _ ->
355        failwith "uuidgen: process exited with non-zero status"
356    | WSIGNALED _ | WSTOPPED _ ->
357        failwith "uuidgen: process signalled or stopped by signal"
358   );
359   uuid
360
361 (* These test functions are used in the language binding tests. *)
362
363 let test_all_args = [
364   String "str";
365   OptString "optstr";
366   StringList "strlist";
367   Bool "b";
368   Int "integer";
369   Int64 "integer64";
370   FileIn "filein";
371   FileOut "fileout";
372 ]
373
374 let test_all_rets = [
375   (* except for RErr, which is tested thoroughly elsewhere *)
376   "test0rint",         RInt "valout";
377   "test0rint64",       RInt64 "valout";
378   "test0rbool",        RBool "valout";
379   "test0rconststring", RConstString "valout";
380   "test0rconstoptstring", RConstOptString "valout";
381   "test0rstring",      RString "valout";
382   "test0rstringlist",  RStringList "valout";
383   "test0rstruct",      RStruct ("valout", "lvm_pv");
384   "test0rstructlist",  RStructList ("valout", "lvm_pv");
385   "test0rhashtable",   RHashtable "valout";
386 ]
387
388 let test_functions = [
389   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
390    [],
391    "internal test function - do not use",
392    "\
393 This is an internal test function which is used to test whether
394 the automatically generated bindings can handle every possible
395 parameter type correctly.
396
397 It echos the contents of each parameter to stdout.
398
399 You probably don't want to call this function.");
400 ] @ List.flatten (
401   List.map (
402     fun (name, ret) ->
403       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
404         [],
405         "internal test function - do not use",
406         "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 return type correctly.
410
411 It converts string C<val> to the return type.
412
413 You probably don't want to call this function.");
414        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 This function always returns an error.
423
424 You probably don't want to call this function.")]
425   ) test_all_rets
426 )
427
428 (* non_daemon_functions are any functions which don't get processed
429  * in the daemon, eg. functions for setting and getting local
430  * configuration values.
431  *)
432
433 let non_daemon_functions = test_functions @ [
434   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
435    [],
436    "launch the qemu subprocess",
437    "\
438 Internally libguestfs is implemented by running a virtual machine
439 using L<qemu(1)>.
440
441 You should call this after configuring the handle
442 (eg. adding drives) but before performing any actions.");
443
444   ("wait_ready", (RErr, []), -1, [NotInFish],
445    [],
446    "wait until the qemu subprocess launches (no op)",
447    "\
448 This function is a no op.
449
450 In versions of the API E<lt> 1.0.71 you had to call this function
451 just after calling C<guestfs_launch> to wait for the launch
452 to complete.  However this is no longer necessary because
453 C<guestfs_launch> now does the waiting.
454
455 If you see any calls to this function in code then you can just
456 remove them, unless you want to retain compatibility with older
457 versions of the API.");
458
459   ("kill_subprocess", (RErr, []), -1, [],
460    [],
461    "kill the qemu subprocess",
462    "\
463 This kills the qemu subprocess.  You should never need to call this.");
464
465   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
466    [],
467    "add an image to examine or modify",
468    "\
469 This function adds a virtual machine disk image C<filename> to the
470 guest.  The first time you call this function, the disk appears as IDE
471 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
472 so on.
473
474 You don't necessarily need to be root when using libguestfs.  However
475 you obviously do need sufficient permissions to access the filename
476 for whatever operations you want to perform (ie. read access if you
477 just want to read the image or write access if you want to modify the
478 image).
479
480 This is equivalent to the qemu parameter
481 C<-drive file=filename,cache=off,if=...>.
482 C<cache=off> is omitted in cases where it is not supported by
483 the underlying filesystem.
484
485 Note that this call checks for the existence of C<filename>.  This
486 stops you from specifying other types of drive which are supported
487 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
488 the general C<guestfs_config> call instead.");
489
490   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
491    [],
492    "add a CD-ROM disk image to examine",
493    "\
494 This function adds a virtual CD-ROM disk image to the guest.
495
496 This is equivalent to the qemu parameter C<-cdrom filename>.
497
498 Note that this call checks for the existence of C<filename>.  This
499 stops you from specifying other types of drive which are supported
500 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
501 the general C<guestfs_config> call instead.");
502
503   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
504    [],
505    "add a drive in snapshot mode (read-only)",
506    "\
507 This adds a drive in snapshot mode, making it effectively
508 read-only.
509
510 Note that writes to the device are allowed, and will be seen for
511 the duration of the guestfs handle, but they are written
512 to a temporary file which is discarded as soon as the guestfs
513 handle is closed.  We don't currently have any method to enable
514 changes to be committed, although qemu can support this.
515
516 This is equivalent to the qemu parameter
517 C<-drive file=filename,snapshot=on,if=...>.
518
519 Note that this call checks for the existence of C<filename>.  This
520 stops you from specifying other types of drive which are supported
521 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
522 the general C<guestfs_config> call instead.");
523
524   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
525    [],
526    "add qemu parameters",
527    "\
528 This can be used to add arbitrary qemu command line parameters
529 of the form C<-param value>.  Actually it's not quite arbitrary - we
530 prevent you from setting some parameters which would interfere with
531 parameters that we use.
532
533 The first character of C<param> string must be a C<-> (dash).
534
535 C<value> can be NULL.");
536
537   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
538    [],
539    "set the qemu binary",
540    "\
541 Set the qemu binary that we will use.
542
543 The default is chosen when the library was compiled by the
544 configure script.
545
546 You can also override this by setting the C<LIBGUESTFS_QEMU>
547 environment variable.
548
549 Setting C<qemu> to C<NULL> restores the default qemu binary.");
550
551   ("get_qemu", (RConstString "qemu", []), -1, [],
552    [InitNone, Always, TestRun (
553       [["get_qemu"]])],
554    "get the qemu binary",
555    "\
556 Return the current qemu binary.
557
558 This is always non-NULL.  If it wasn't set already, then this will
559 return the default qemu binary name.");
560
561   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
562    [],
563    "set the search path",
564    "\
565 Set the path that libguestfs searches for kernel and initrd.img.
566
567 The default is C<$libdir/guestfs> unless overridden by setting
568 C<LIBGUESTFS_PATH> environment variable.
569
570 Setting C<path> to C<NULL> restores the default path.");
571
572   ("get_path", (RConstString "path", []), -1, [],
573    [InitNone, Always, TestRun (
574       [["get_path"]])],
575    "get the search path",
576    "\
577 Return the current search path.
578
579 This is always non-NULL.  If it wasn't set already, then this will
580 return the default path.");
581
582   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
583    [],
584    "add options to kernel command line",
585    "\
586 This function is used to add additional options to the
587 guest kernel command line.
588
589 The default is C<NULL> unless overridden by setting
590 C<LIBGUESTFS_APPEND> environment variable.
591
592 Setting C<append> to C<NULL> means I<no> additional options
593 are passed (libguestfs always adds a few of its own).");
594
595   ("get_append", (RConstOptString "append", []), -1, [],
596    (* This cannot be tested with the current framework.  The
597     * function can return NULL in normal operations, which the
598     * test framework interprets as an error.
599     *)
600    [],
601    "get the additional kernel options",
602    "\
603 Return the additional kernel options which are added to the
604 guest kernel command line.
605
606 If C<NULL> then no options are added.");
607
608   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
609    [],
610    "set autosync mode",
611    "\
612 If C<autosync> is true, this enables autosync.  Libguestfs will make a
613 best effort attempt to run C<guestfs_umount_all> followed by
614 C<guestfs_sync> when the handle is closed
615 (also if the program exits without closing handles).
616
617 This is disabled by default (except in guestfish where it is
618 enabled by default).");
619
620   ("get_autosync", (RBool "autosync", []), -1, [],
621    [InitNone, Always, TestRun (
622       [["get_autosync"]])],
623    "get autosync mode",
624    "\
625 Get the autosync flag.");
626
627   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
628    [],
629    "set verbose mode",
630    "\
631 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
632
633 Verbose messages are disabled unless the environment variable
634 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
635
636   ("get_verbose", (RBool "verbose", []), -1, [],
637    [],
638    "get verbose mode",
639    "\
640 This returns the verbose messages flag.");
641
642   ("is_ready", (RBool "ready", []), -1, [],
643    [InitNone, Always, TestOutputTrue (
644       [["is_ready"]])],
645    "is ready to accept commands",
646    "\
647 This returns true iff this handle is ready to accept commands
648 (in the C<READY> state).
649
650 For more information on states, see L<guestfs(3)>.");
651
652   ("is_config", (RBool "config", []), -1, [],
653    [InitNone, Always, TestOutputFalse (
654       [["is_config"]])],
655    "is in configuration state",
656    "\
657 This returns true iff this handle is being configured
658 (in the C<CONFIG> state).
659
660 For more information on states, see L<guestfs(3)>.");
661
662   ("is_launching", (RBool "launching", []), -1, [],
663    [InitNone, Always, TestOutputFalse (
664       [["is_launching"]])],
665    "is launching subprocess",
666    "\
667 This returns true iff this handle is launching the subprocess
668 (in the C<LAUNCHING> state).
669
670 For more information on states, see L<guestfs(3)>.");
671
672   ("is_busy", (RBool "busy", []), -1, [],
673    [InitNone, Always, TestOutputFalse (
674       [["is_busy"]])],
675    "is busy processing a command",
676    "\
677 This returns true iff this handle is busy processing a command
678 (in the C<BUSY> state).
679
680 For more information on states, see L<guestfs(3)>.");
681
682   ("get_state", (RInt "state", []), -1, [],
683    [],
684    "get the current state",
685    "\
686 This returns the current state as an opaque integer.  This is
687 only useful for printing debug and internal error messages.
688
689 For more information on states, see L<guestfs(3)>.");
690
691   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
692    [InitNone, Always, TestOutputInt (
693       [["set_memsize"; "500"];
694        ["get_memsize"]], 500)],
695    "set memory allocated to the qemu subprocess",
696    "\
697 This sets the memory size in megabytes allocated to the
698 qemu subprocess.  This only has any effect if called before
699 C<guestfs_launch>.
700
701 You can also change this by setting the environment
702 variable C<LIBGUESTFS_MEMSIZE> before the handle is
703 created.
704
705 For more information on the architecture of libguestfs,
706 see L<guestfs(3)>.");
707
708   ("get_memsize", (RInt "memsize", []), -1, [],
709    [InitNone, Always, TestOutputIntOp (
710       [["get_memsize"]], ">=", 256)],
711    "get memory allocated to the qemu subprocess",
712    "\
713 This gets the memory size in megabytes allocated to the
714 qemu subprocess.
715
716 If C<guestfs_set_memsize> was not called
717 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
718 then this returns the compiled-in default value for memsize.
719
720 For more information on the architecture of libguestfs,
721 see L<guestfs(3)>.");
722
723   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
724    [InitNone, Always, TestOutputIntOp (
725       [["get_pid"]], ">=", 1)],
726    "get PID of qemu subprocess",
727    "\
728 Return the process ID of the qemu subprocess.  If there is no
729 qemu subprocess, then this will return an error.
730
731 This is an internal call used for debugging and testing.");
732
733   ("version", (RStruct ("version", "version"), []), -1, [],
734    [InitNone, Always, TestOutputStruct (
735       [["version"]], [CompareWithInt ("major", 1)])],
736    "get the library version number",
737    "\
738 Return the libguestfs version number that the program is linked
739 against.
740
741 Note that because of dynamic linking this is not necessarily
742 the version of libguestfs that you compiled against.  You can
743 compile the program, and then at runtime dynamically link
744 against a completely different C<libguestfs.so> library.
745
746 This call was added in version C<1.0.58>.  In previous
747 versions of libguestfs there was no way to get the version
748 number.  From C code you can use ELF weak linking tricks to find out if
749 this symbol exists (if it doesn't, then it's an earlier version).
750
751 The call returns a structure with four elements.  The first
752 three (C<major>, C<minor> and C<release>) are numbers and
753 correspond to the usual version triplet.  The fourth element
754 (C<extra>) is a string and is normally empty, but may be
755 used for distro-specific information.
756
757 To construct the original version string:
758 C<$major.$minor.$release$extra>
759
760 I<Note:> Don't use this call to test for availability
761 of features.  Distro backports makes this unreliable.  Use
762 C<guestfs_available> instead.");
763
764   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
765    [InitNone, Always, TestOutputTrue (
766       [["set_selinux"; "true"];
767        ["get_selinux"]])],
768    "set SELinux enabled or disabled at appliance boot",
769    "\
770 This sets the selinux flag that is passed to the appliance
771 at boot time.  The default is C<selinux=0> (disabled).
772
773 Note that if SELinux is enabled, it is always in
774 Permissive mode (C<enforcing=0>).
775
776 For more information on the architecture of libguestfs,
777 see L<guestfs(3)>.");
778
779   ("get_selinux", (RBool "selinux", []), -1, [],
780    [],
781    "get SELinux enabled flag",
782    "\
783 This returns the current setting of the selinux flag which
784 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
785
786 For more information on the architecture of libguestfs,
787 see L<guestfs(3)>.");
788
789   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
790    [InitNone, Always, TestOutputFalse (
791       [["set_trace"; "false"];
792        ["get_trace"]])],
793    "enable or disable command traces",
794    "\
795 If the command trace flag is set to 1, then commands are
796 printed on stdout before they are executed in a format
797 which is very similar to the one used by guestfish.  In
798 other words, you can run a program with this enabled, and
799 you will get out a script which you can feed to guestfish
800 to perform the same set of actions.
801
802 If you want to trace C API calls into libguestfs (and
803 other libraries) then possibly a better way is to use
804 the external ltrace(1) command.
805
806 Command traces are disabled unless the environment variable
807 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
808
809   ("get_trace", (RBool "trace", []), -1, [],
810    [],
811    "get command trace enabled flag",
812    "\
813 Return the command trace flag.");
814
815   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
816    [InitNone, Always, TestOutputFalse (
817       [["set_direct"; "false"];
818        ["get_direct"]])],
819    "enable or disable direct appliance mode",
820    "\
821 If the direct appliance mode flag is enabled, then stdin and
822 stdout are passed directly through to the appliance once it
823 is launched.
824
825 One consequence of this is that log messages aren't caught
826 by the library and handled by C<guestfs_set_log_message_callback>,
827 but go straight to stdout.
828
829 You probably don't want to use this unless you know what you
830 are doing.
831
832 The default is disabled.");
833
834   ("get_direct", (RBool "direct", []), -1, [],
835    [],
836    "get direct appliance mode flag",
837    "\
838 Return the direct appliance mode flag.");
839
840   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
841    [InitNone, Always, TestOutputTrue (
842       [["set_recovery_proc"; "true"];
843        ["get_recovery_proc"]])],
844    "enable or disable the recovery process",
845    "\
846 If this is called with the parameter C<false> then
847 C<guestfs_launch> does not create a recovery process.  The
848 purpose of the recovery process is to stop runaway qemu
849 processes in the case where the main program aborts abruptly.
850
851 This only has any effect if called before C<guestfs_launch>,
852 and the default is true.
853
854 About the only time when you would want to disable this is
855 if the main process will fork itself into the background
856 (\"daemonize\" itself).  In this case the recovery process
857 thinks that the main program has disappeared and so kills
858 qemu, which is not very helpful.");
859
860   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
861    [],
862    "get recovery process enabled flag",
863    "\
864 Return the recovery process enabled flag.");
865
866 ]
867
868 (* daemon_functions are any functions which cause some action
869  * to take place in the daemon.
870  *)
871
872 let daemon_functions = [
873   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
874    [InitEmpty, Always, TestOutput (
875       [["part_disk"; "/dev/sda"; "mbr"];
876        ["mkfs"; "ext2"; "/dev/sda1"];
877        ["mount"; "/dev/sda1"; "/"];
878        ["write_file"; "/new"; "new file contents"; "0"];
879        ["cat"; "/new"]], "new file contents")],
880    "mount a guest disk at a position in the filesystem",
881    "\
882 Mount a guest disk at a position in the filesystem.  Block devices
883 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
884 the guest.  If those block devices contain partitions, they will have
885 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
886 names can be used.
887
888 The rules are the same as for L<mount(2)>:  A filesystem must
889 first be mounted on C</> before others can be mounted.  Other
890 filesystems can only be mounted on directories which already
891 exist.
892
893 The mounted filesystem is writable, if we have sufficient permissions
894 on the underlying device.
895
896 The filesystem options C<sync> and C<noatime> are set with this
897 call, in order to improve reliability.");
898
899   ("sync", (RErr, []), 2, [],
900    [ InitEmpty, Always, TestRun [["sync"]]],
901    "sync disks, writes are flushed through to the disk image",
902    "\
903 This syncs the disk, so that any writes are flushed through to the
904 underlying disk image.
905
906 You should always call this if you have modified a disk image, before
907 closing the handle.");
908
909   ("touch", (RErr, [Pathname "path"]), 3, [],
910    [InitBasicFS, Always, TestOutputTrue (
911       [["touch"; "/new"];
912        ["exists"; "/new"]])],
913    "update file timestamps or create a new file",
914    "\
915 Touch acts like the L<touch(1)> command.  It can be used to
916 update the timestamps on a file, or, if the file does not exist,
917 to create a new zero-length file.");
918
919   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
920    [InitISOFS, Always, TestOutput (
921       [["cat"; "/known-2"]], "abcdef\n")],
922    "list the contents of a file",
923    "\
924 Return the contents of the file named C<path>.
925
926 Note that this function cannot correctly handle binary files
927 (specifically, files containing C<\\0> character which is treated
928 as end of string).  For those you need to use the C<guestfs_read_file>
929 or C<guestfs_download> functions which have a more complex interface.");
930
931   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
932    [], (* XXX Tricky to test because it depends on the exact format
933         * of the 'ls -l' command, which changes between F10 and F11.
934         *)
935    "list the files in a directory (long format)",
936    "\
937 List the files in C<directory> (relative to the root directory,
938 there is no cwd) in the format of 'ls -la'.
939
940 This command is mostly useful for interactive sessions.  It
941 is I<not> intended that you try to parse the output string.");
942
943   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
944    [InitBasicFS, Always, TestOutputList (
945       [["touch"; "/new"];
946        ["touch"; "/newer"];
947        ["touch"; "/newest"];
948        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
949    "list the files in a directory",
950    "\
951 List the files in C<directory> (relative to the root directory,
952 there is no cwd).  The '.' and '..' entries are not returned, but
953 hidden files are shown.
954
955 This command is mostly useful for interactive sessions.  Programs
956 should probably use C<guestfs_readdir> instead.");
957
958   ("list_devices", (RStringList "devices", []), 7, [],
959    [InitEmpty, Always, TestOutputListOfDevices (
960       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
961    "list the block devices",
962    "\
963 List all the block devices.
964
965 The full block device names are returned, eg. C</dev/sda>");
966
967   ("list_partitions", (RStringList "partitions", []), 8, [],
968    [InitBasicFS, Always, TestOutputListOfDevices (
969       [["list_partitions"]], ["/dev/sda1"]);
970     InitEmpty, Always, TestOutputListOfDevices (
971       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
972        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
973    "list the partitions",
974    "\
975 List all the partitions detected on all block devices.
976
977 The full partition device names are returned, eg. C</dev/sda1>
978
979 This does not return logical volumes.  For that you will need to
980 call C<guestfs_lvs>.");
981
982   ("pvs", (RStringList "physvols", []), 9, [],
983    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
984       [["pvs"]], ["/dev/sda1"]);
985     InitEmpty, Always, TestOutputListOfDevices (
986       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
987        ["pvcreate"; "/dev/sda1"];
988        ["pvcreate"; "/dev/sda2"];
989        ["pvcreate"; "/dev/sda3"];
990        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
991    "list the LVM physical volumes (PVs)",
992    "\
993 List all the physical volumes detected.  This is the equivalent
994 of the L<pvs(8)> command.
995
996 This returns a list of just the device names that contain
997 PVs (eg. C</dev/sda2>).
998
999 See also C<guestfs_pvs_full>.");
1000
1001   ("vgs", (RStringList "volgroups", []), 10, [],
1002    [InitBasicFSonLVM, Always, TestOutputList (
1003       [["vgs"]], ["VG"]);
1004     InitEmpty, Always, TestOutputList (
1005       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1006        ["pvcreate"; "/dev/sda1"];
1007        ["pvcreate"; "/dev/sda2"];
1008        ["pvcreate"; "/dev/sda3"];
1009        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1010        ["vgcreate"; "VG2"; "/dev/sda3"];
1011        ["vgs"]], ["VG1"; "VG2"])],
1012    "list the LVM volume groups (VGs)",
1013    "\
1014 List all the volumes groups detected.  This is the equivalent
1015 of the L<vgs(8)> command.
1016
1017 This returns a list of just the volume group names that were
1018 detected (eg. C<VolGroup00>).
1019
1020 See also C<guestfs_vgs_full>.");
1021
1022   ("lvs", (RStringList "logvols", []), 11, [],
1023    [InitBasicFSonLVM, Always, TestOutputList (
1024       [["lvs"]], ["/dev/VG/LV"]);
1025     InitEmpty, Always, TestOutputList (
1026       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1027        ["pvcreate"; "/dev/sda1"];
1028        ["pvcreate"; "/dev/sda2"];
1029        ["pvcreate"; "/dev/sda3"];
1030        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1031        ["vgcreate"; "VG2"; "/dev/sda3"];
1032        ["lvcreate"; "LV1"; "VG1"; "50"];
1033        ["lvcreate"; "LV2"; "VG1"; "50"];
1034        ["lvcreate"; "LV3"; "VG2"; "50"];
1035        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1036    "list the LVM logical volumes (LVs)",
1037    "\
1038 List all the logical volumes detected.  This is the equivalent
1039 of the L<lvs(8)> command.
1040
1041 This returns a list of the logical volume device names
1042 (eg. C</dev/VolGroup00/LogVol00>).
1043
1044 See also C<guestfs_lvs_full>.");
1045
1046   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1047    [], (* XXX how to test? *)
1048    "list the LVM physical volumes (PVs)",
1049    "\
1050 List all the physical volumes detected.  This is the equivalent
1051 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1052
1053   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1054    [], (* XXX how to test? *)
1055    "list the LVM volume groups (VGs)",
1056    "\
1057 List all the volumes groups detected.  This is the equivalent
1058 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1059
1060   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1061    [], (* XXX how to test? *)
1062    "list the LVM logical volumes (LVs)",
1063    "\
1064 List all the logical volumes detected.  This is the equivalent
1065 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1066
1067   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1068    [InitISOFS, Always, TestOutputList (
1069       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1070     InitISOFS, Always, TestOutputList (
1071       [["read_lines"; "/empty"]], [])],
1072    "read file as lines",
1073    "\
1074 Return the contents of the file named C<path>.
1075
1076 The file contents are returned as a list of lines.  Trailing
1077 C<LF> and C<CRLF> character sequences are I<not> returned.
1078
1079 Note that this function cannot correctly handle binary files
1080 (specifically, files containing C<\\0> character which is treated
1081 as end of line).  For those you need to use the C<guestfs_read_file>
1082 function which has a more complex interface.");
1083
1084   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1085    [], (* XXX Augeas code needs tests. *)
1086    "create a new Augeas handle",
1087    "\
1088 Create a new Augeas handle for editing configuration files.
1089 If there was any previous Augeas handle associated with this
1090 guestfs session, then it is closed.
1091
1092 You must call this before using any other C<guestfs_aug_*>
1093 commands.
1094
1095 C<root> is the filesystem root.  C<root> must not be NULL,
1096 use C</> instead.
1097
1098 The flags are the same as the flags defined in
1099 E<lt>augeas.hE<gt>, the logical I<or> of the following
1100 integers:
1101
1102 =over 4
1103
1104 =item C<AUG_SAVE_BACKUP> = 1
1105
1106 Keep the original file with a C<.augsave> extension.
1107
1108 =item C<AUG_SAVE_NEWFILE> = 2
1109
1110 Save changes into a file with extension C<.augnew>, and
1111 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1112
1113 =item C<AUG_TYPE_CHECK> = 4
1114
1115 Typecheck lenses (can be expensive).
1116
1117 =item C<AUG_NO_STDINC> = 8
1118
1119 Do not use standard load path for modules.
1120
1121 =item C<AUG_SAVE_NOOP> = 16
1122
1123 Make save a no-op, just record what would have been changed.
1124
1125 =item C<AUG_NO_LOAD> = 32
1126
1127 Do not load the tree in C<guestfs_aug_init>.
1128
1129 =back
1130
1131 To close the handle, you can call C<guestfs_aug_close>.
1132
1133 To find out more about Augeas, see L<http://augeas.net/>.");
1134
1135   ("aug_close", (RErr, []), 26, [],
1136    [], (* XXX Augeas code needs tests. *)
1137    "close the current Augeas handle",
1138    "\
1139 Close the current Augeas handle and free up any resources
1140 used by it.  After calling this, you have to call
1141 C<guestfs_aug_init> again before you can use any other
1142 Augeas functions.");
1143
1144   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1145    [], (* XXX Augeas code needs tests. *)
1146    "define an Augeas variable",
1147    "\
1148 Defines an Augeas variable C<name> whose value is the result
1149 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1150 undefined.
1151
1152 On success this returns the number of nodes in C<expr>, or
1153 C<0> if C<expr> evaluates to something which is not a nodeset.");
1154
1155   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1156    [], (* XXX Augeas code needs tests. *)
1157    "define an Augeas node",
1158    "\
1159 Defines a variable C<name> whose value is the result of
1160 evaluating C<expr>.
1161
1162 If C<expr> evaluates to an empty nodeset, a node is created,
1163 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1164 C<name> will be the nodeset containing that single node.
1165
1166 On success this returns a pair containing the
1167 number of nodes in the nodeset, and a boolean flag
1168 if a node was created.");
1169
1170   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1171    [], (* XXX Augeas code needs tests. *)
1172    "look up the value of an Augeas path",
1173    "\
1174 Look up the value associated with C<path>.  If C<path>
1175 matches exactly one node, the C<value> is returned.");
1176
1177   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1178    [], (* XXX Augeas code needs tests. *)
1179    "set Augeas path to value",
1180    "\
1181 Set the value associated with C<path> to C<value>.");
1182
1183   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1184    [], (* XXX Augeas code needs tests. *)
1185    "insert a sibling Augeas node",
1186    "\
1187 Create a new sibling C<label> for C<path>, inserting it into
1188 the tree before or after C<path> (depending on the boolean
1189 flag C<before>).
1190
1191 C<path> must match exactly one existing node in the tree, and
1192 C<label> must be a label, ie. not contain C</>, C<*> or end
1193 with a bracketed index C<[N]>.");
1194
1195   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1196    [], (* XXX Augeas code needs tests. *)
1197    "remove an Augeas path",
1198    "\
1199 Remove C<path> and all of its children.
1200
1201 On success this returns the number of entries which were removed.");
1202
1203   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1204    [], (* XXX Augeas code needs tests. *)
1205    "move Augeas node",
1206    "\
1207 Move the node C<src> to C<dest>.  C<src> must match exactly
1208 one node.  C<dest> is overwritten if it exists.");
1209
1210   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1211    [], (* XXX Augeas code needs tests. *)
1212    "return Augeas nodes which match augpath",
1213    "\
1214 Returns a list of paths which match the path expression C<path>.
1215 The returned paths are sufficiently qualified so that they match
1216 exactly one node in the current tree.");
1217
1218   ("aug_save", (RErr, []), 25, [],
1219    [], (* XXX Augeas code needs tests. *)
1220    "write all pending Augeas changes to disk",
1221    "\
1222 This writes all pending changes to disk.
1223
1224 The flags which were passed to C<guestfs_aug_init> affect exactly
1225 how files are saved.");
1226
1227   ("aug_load", (RErr, []), 27, [],
1228    [], (* XXX Augeas code needs tests. *)
1229    "load files into the tree",
1230    "\
1231 Load files into the tree.
1232
1233 See C<aug_load> in the Augeas documentation for the full gory
1234 details.");
1235
1236   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1237    [], (* XXX Augeas code needs tests. *)
1238    "list Augeas nodes under augpath",
1239    "\
1240 This is just a shortcut for listing C<guestfs_aug_match>
1241 C<path/*> and sorting the resulting nodes into alphabetical order.");
1242
1243   ("rm", (RErr, [Pathname "path"]), 29, [],
1244    [InitBasicFS, Always, TestRun
1245       [["touch"; "/new"];
1246        ["rm"; "/new"]];
1247     InitBasicFS, Always, TestLastFail
1248       [["rm"; "/new"]];
1249     InitBasicFS, Always, TestLastFail
1250       [["mkdir"; "/new"];
1251        ["rm"; "/new"]]],
1252    "remove a file",
1253    "\
1254 Remove the single file C<path>.");
1255
1256   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1257    [InitBasicFS, Always, TestRun
1258       [["mkdir"; "/new"];
1259        ["rmdir"; "/new"]];
1260     InitBasicFS, Always, TestLastFail
1261       [["rmdir"; "/new"]];
1262     InitBasicFS, Always, TestLastFail
1263       [["touch"; "/new"];
1264        ["rmdir"; "/new"]]],
1265    "remove a directory",
1266    "\
1267 Remove the single directory C<path>.");
1268
1269   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1270    [InitBasicFS, Always, TestOutputFalse
1271       [["mkdir"; "/new"];
1272        ["mkdir"; "/new/foo"];
1273        ["touch"; "/new/foo/bar"];
1274        ["rm_rf"; "/new"];
1275        ["exists"; "/new"]]],
1276    "remove a file or directory recursively",
1277    "\
1278 Remove the file or directory C<path>, recursively removing the
1279 contents if its a directory.  This is like the C<rm -rf> shell
1280 command.");
1281
1282   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1283    [InitBasicFS, Always, TestOutputTrue
1284       [["mkdir"; "/new"];
1285        ["is_dir"; "/new"]];
1286     InitBasicFS, Always, TestLastFail
1287       [["mkdir"; "/new/foo/bar"]]],
1288    "create a directory",
1289    "\
1290 Create a directory named C<path>.");
1291
1292   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1293    [InitBasicFS, Always, TestOutputTrue
1294       [["mkdir_p"; "/new/foo/bar"];
1295        ["is_dir"; "/new/foo/bar"]];
1296     InitBasicFS, Always, TestOutputTrue
1297       [["mkdir_p"; "/new/foo/bar"];
1298        ["is_dir"; "/new/foo"]];
1299     InitBasicFS, Always, TestOutputTrue
1300       [["mkdir_p"; "/new/foo/bar"];
1301        ["is_dir"; "/new"]];
1302     (* Regression tests for RHBZ#503133: *)
1303     InitBasicFS, Always, TestRun
1304       [["mkdir"; "/new"];
1305        ["mkdir_p"; "/new"]];
1306     InitBasicFS, Always, TestLastFail
1307       [["touch"; "/new"];
1308        ["mkdir_p"; "/new"]]],
1309    "create a directory and parents",
1310    "\
1311 Create a directory named C<path>, creating any parent directories
1312 as necessary.  This is like the C<mkdir -p> shell command.");
1313
1314   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1315    [], (* XXX Need stat command to test *)
1316    "change file mode",
1317    "\
1318 Change the mode (permissions) of C<path> to C<mode>.  Only
1319 numeric modes are supported.");
1320
1321   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1322    [], (* XXX Need stat command to test *)
1323    "change file owner and group",
1324    "\
1325 Change the file owner to C<owner> and group to C<group>.
1326
1327 Only numeric uid and gid are supported.  If you want to use
1328 names, you will need to locate and parse the password file
1329 yourself (Augeas support makes this relatively easy).");
1330
1331   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1332    [InitISOFS, Always, TestOutputTrue (
1333       [["exists"; "/empty"]]);
1334     InitISOFS, Always, TestOutputTrue (
1335       [["exists"; "/directory"]])],
1336    "test if file or directory exists",
1337    "\
1338 This returns C<true> if and only if there is a file, directory
1339 (or anything) with the given C<path> name.
1340
1341 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1342
1343   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1344    [InitISOFS, Always, TestOutputTrue (
1345       [["is_file"; "/known-1"]]);
1346     InitISOFS, Always, TestOutputFalse (
1347       [["is_file"; "/directory"]])],
1348    "test if file exists",
1349    "\
1350 This returns C<true> if and only if there is a file
1351 with the given C<path> name.  Note that it returns false for
1352 other objects like directories.
1353
1354 See also C<guestfs_stat>.");
1355
1356   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1357    [InitISOFS, Always, TestOutputFalse (
1358       [["is_dir"; "/known-3"]]);
1359     InitISOFS, Always, TestOutputTrue (
1360       [["is_dir"; "/directory"]])],
1361    "test if file exists",
1362    "\
1363 This returns C<true> if and only if there is a directory
1364 with the given C<path> name.  Note that it returns false for
1365 other objects like files.
1366
1367 See also C<guestfs_stat>.");
1368
1369   ("pvcreate", (RErr, [Device "device"]), 39, [],
1370    [InitEmpty, Always, TestOutputListOfDevices (
1371       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1372        ["pvcreate"; "/dev/sda1"];
1373        ["pvcreate"; "/dev/sda2"];
1374        ["pvcreate"; "/dev/sda3"];
1375        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1376    "create an LVM physical volume",
1377    "\
1378 This creates an LVM physical volume on the named C<device>,
1379 where C<device> should usually be a partition name such
1380 as C</dev/sda1>.");
1381
1382   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1383    [InitEmpty, Always, TestOutputList (
1384       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1385        ["pvcreate"; "/dev/sda1"];
1386        ["pvcreate"; "/dev/sda2"];
1387        ["pvcreate"; "/dev/sda3"];
1388        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1389        ["vgcreate"; "VG2"; "/dev/sda3"];
1390        ["vgs"]], ["VG1"; "VG2"])],
1391    "create an LVM volume group",
1392    "\
1393 This creates an LVM volume group called C<volgroup>
1394 from the non-empty list of physical volumes C<physvols>.");
1395
1396   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1397    [InitEmpty, Always, TestOutputList (
1398       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1399        ["pvcreate"; "/dev/sda1"];
1400        ["pvcreate"; "/dev/sda2"];
1401        ["pvcreate"; "/dev/sda3"];
1402        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1403        ["vgcreate"; "VG2"; "/dev/sda3"];
1404        ["lvcreate"; "LV1"; "VG1"; "50"];
1405        ["lvcreate"; "LV2"; "VG1"; "50"];
1406        ["lvcreate"; "LV3"; "VG2"; "50"];
1407        ["lvcreate"; "LV4"; "VG2"; "50"];
1408        ["lvcreate"; "LV5"; "VG2"; "50"];
1409        ["lvs"]],
1410       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1411        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1412    "create an LVM volume group",
1413    "\
1414 This creates an LVM volume group called C<logvol>
1415 on the volume group C<volgroup>, with C<size> megabytes.");
1416
1417   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1418    [InitEmpty, Always, TestOutput (
1419       [["part_disk"; "/dev/sda"; "mbr"];
1420        ["mkfs"; "ext2"; "/dev/sda1"];
1421        ["mount"; "/dev/sda1"; "/"];
1422        ["write_file"; "/new"; "new file contents"; "0"];
1423        ["cat"; "/new"]], "new file contents")],
1424    "make a filesystem",
1425    "\
1426 This creates a filesystem on C<device> (usually a partition
1427 or LVM logical volume).  The filesystem type is C<fstype>, for
1428 example C<ext3>.");
1429
1430   ("sfdisk", (RErr, [Device "device";
1431                      Int "cyls"; Int "heads"; Int "sectors";
1432                      StringList "lines"]), 43, [DangerWillRobinson],
1433    [],
1434    "create partitions on a block device",
1435    "\
1436 This is a direct interface to the L<sfdisk(8)> program for creating
1437 partitions on block devices.
1438
1439 C<device> should be a block device, for example C</dev/sda>.
1440
1441 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1442 and sectors on the device, which are passed directly to sfdisk as
1443 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1444 of these, then the corresponding parameter is omitted.  Usually for
1445 'large' disks, you can just pass C<0> for these, but for small
1446 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1447 out the right geometry and you will need to tell it.
1448
1449 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1450 information refer to the L<sfdisk(8)> manpage.
1451
1452 To create a single partition occupying the whole disk, you would
1453 pass C<lines> as a single element list, when the single element being
1454 the string C<,> (comma).
1455
1456 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1457 C<guestfs_part_init>");
1458
1459   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1460    [InitBasicFS, Always, TestOutput (
1461       [["write_file"; "/new"; "new file contents"; "0"];
1462        ["cat"; "/new"]], "new file contents");
1463     InitBasicFS, Always, TestOutput (
1464       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1465        ["cat"; "/new"]], "\nnew file contents\n");
1466     InitBasicFS, Always, TestOutput (
1467       [["write_file"; "/new"; "\n\n"; "0"];
1468        ["cat"; "/new"]], "\n\n");
1469     InitBasicFS, Always, TestOutput (
1470       [["write_file"; "/new"; ""; "0"];
1471        ["cat"; "/new"]], "");
1472     InitBasicFS, Always, TestOutput (
1473       [["write_file"; "/new"; "\n\n\n"; "0"];
1474        ["cat"; "/new"]], "\n\n\n");
1475     InitBasicFS, Always, TestOutput (
1476       [["write_file"; "/new"; "\n"; "0"];
1477        ["cat"; "/new"]], "\n")],
1478    "create a file",
1479    "\
1480 This call creates a file called C<path>.  The contents of the
1481 file is the string C<content> (which can contain any 8 bit data),
1482 with length C<size>.
1483
1484 As a special case, if C<size> is C<0>
1485 then the length is calculated using C<strlen> (so in this case
1486 the content cannot contain embedded ASCII NULs).
1487
1488 I<NB.> Owing to a bug, writing content containing ASCII NUL
1489 characters does I<not> work, even if the length is specified.
1490 We hope to resolve this bug in a future version.  In the meantime
1491 use C<guestfs_upload>.");
1492
1493   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1494    [InitEmpty, Always, TestOutputListOfDevices (
1495       [["part_disk"; "/dev/sda"; "mbr"];
1496        ["mkfs"; "ext2"; "/dev/sda1"];
1497        ["mount"; "/dev/sda1"; "/"];
1498        ["mounts"]], ["/dev/sda1"]);
1499     InitEmpty, Always, TestOutputList (
1500       [["part_disk"; "/dev/sda"; "mbr"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mount"; "/dev/sda1"; "/"];
1503        ["umount"; "/"];
1504        ["mounts"]], [])],
1505    "unmount a filesystem",
1506    "\
1507 This unmounts the given filesystem.  The filesystem may be
1508 specified either by its mountpoint (path) or the device which
1509 contains the filesystem.");
1510
1511   ("mounts", (RStringList "devices", []), 46, [],
1512    [InitBasicFS, Always, TestOutputListOfDevices (
1513       [["mounts"]], ["/dev/sda1"])],
1514    "show mounted filesystems",
1515    "\
1516 This returns the list of currently mounted filesystems.  It returns
1517 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1518
1519 Some internal mounts are not shown.
1520
1521 See also: C<guestfs_mountpoints>");
1522
1523   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1524    [InitBasicFS, Always, TestOutputList (
1525       [["umount_all"];
1526        ["mounts"]], []);
1527     (* check that umount_all can unmount nested mounts correctly: *)
1528     InitEmpty, Always, TestOutputList (
1529       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1530        ["mkfs"; "ext2"; "/dev/sda1"];
1531        ["mkfs"; "ext2"; "/dev/sda2"];
1532        ["mkfs"; "ext2"; "/dev/sda3"];
1533        ["mount"; "/dev/sda1"; "/"];
1534        ["mkdir"; "/mp1"];
1535        ["mount"; "/dev/sda2"; "/mp1"];
1536        ["mkdir"; "/mp1/mp2"];
1537        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1538        ["mkdir"; "/mp1/mp2/mp3"];
1539        ["umount_all"];
1540        ["mounts"]], [])],
1541    "unmount all filesystems",
1542    "\
1543 This unmounts all mounted filesystems.
1544
1545 Some internal mounts are not unmounted by this call.");
1546
1547   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1548    [],
1549    "remove all LVM LVs, VGs and PVs",
1550    "\
1551 This command removes all LVM logical volumes, volume groups
1552 and physical volumes.");
1553
1554   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1555    [InitISOFS, Always, TestOutput (
1556       [["file"; "/empty"]], "empty");
1557     InitISOFS, Always, TestOutput (
1558       [["file"; "/known-1"]], "ASCII text");
1559     InitISOFS, Always, TestLastFail (
1560       [["file"; "/notexists"]])],
1561    "determine file type",
1562    "\
1563 This call uses the standard L<file(1)> command to determine
1564 the type or contents of the file.  This also works on devices,
1565 for example to find out whether a partition contains a filesystem.
1566
1567 This call will also transparently look inside various types
1568 of compressed file.
1569
1570 The exact command which runs is C<file -zbsL path>.  Note in
1571 particular that the filename is not prepended to the output
1572 (the C<-b> option).");
1573
1574   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1575    [InitBasicFS, Always, TestOutput (
1576       [["upload"; "test-command"; "/test-command"];
1577        ["chmod"; "0o755"; "/test-command"];
1578        ["command"; "/test-command 1"]], "Result1");
1579     InitBasicFS, Always, TestOutput (
1580       [["upload"; "test-command"; "/test-command"];
1581        ["chmod"; "0o755"; "/test-command"];
1582        ["command"; "/test-command 2"]], "Result2\n");
1583     InitBasicFS, Always, TestOutput (
1584       [["upload"; "test-command"; "/test-command"];
1585        ["chmod"; "0o755"; "/test-command"];
1586        ["command"; "/test-command 3"]], "\nResult3");
1587     InitBasicFS, Always, TestOutput (
1588       [["upload"; "test-command"; "/test-command"];
1589        ["chmod"; "0o755"; "/test-command"];
1590        ["command"; "/test-command 4"]], "\nResult4\n");
1591     InitBasicFS, Always, TestOutput (
1592       [["upload"; "test-command"; "/test-command"];
1593        ["chmod"; "0o755"; "/test-command"];
1594        ["command"; "/test-command 5"]], "\nResult5\n\n");
1595     InitBasicFS, Always, TestOutput (
1596       [["upload"; "test-command"; "/test-command"];
1597        ["chmod"; "0o755"; "/test-command"];
1598        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1599     InitBasicFS, Always, TestOutput (
1600       [["upload"; "test-command"; "/test-command"];
1601        ["chmod"; "0o755"; "/test-command"];
1602        ["command"; "/test-command 7"]], "");
1603     InitBasicFS, Always, TestOutput (
1604       [["upload"; "test-command"; "/test-command"];
1605        ["chmod"; "0o755"; "/test-command"];
1606        ["command"; "/test-command 8"]], "\n");
1607     InitBasicFS, Always, TestOutput (
1608       [["upload"; "test-command"; "/test-command"];
1609        ["chmod"; "0o755"; "/test-command"];
1610        ["command"; "/test-command 9"]], "\n\n");
1611     InitBasicFS, Always, TestOutput (
1612       [["upload"; "test-command"; "/test-command"];
1613        ["chmod"; "0o755"; "/test-command"];
1614        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1615     InitBasicFS, Always, TestOutput (
1616       [["upload"; "test-command"; "/test-command"];
1617        ["chmod"; "0o755"; "/test-command"];
1618        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1619     InitBasicFS, Always, TestLastFail (
1620       [["upload"; "test-command"; "/test-command"];
1621        ["chmod"; "0o755"; "/test-command"];
1622        ["command"; "/test-command"]])],
1623    "run a command from the guest filesystem",
1624    "\
1625 This call runs a command from the guest filesystem.  The
1626 filesystem must be mounted, and must contain a compatible
1627 operating system (ie. something Linux, with the same
1628 or compatible processor architecture).
1629
1630 The single parameter is an argv-style list of arguments.
1631 The first element is the name of the program to run.
1632 Subsequent elements are parameters.  The list must be
1633 non-empty (ie. must contain a program name).  Note that
1634 the command runs directly, and is I<not> invoked via
1635 the shell (see C<guestfs_sh>).
1636
1637 The return value is anything printed to I<stdout> by
1638 the command.
1639
1640 If the command returns a non-zero exit status, then
1641 this function returns an error message.  The error message
1642 string is the content of I<stderr> from the command.
1643
1644 The C<$PATH> environment variable will contain at least
1645 C</usr/bin> and C</bin>.  If you require a program from
1646 another location, you should provide the full path in the
1647 first parameter.
1648
1649 Shared libraries and data files required by the program
1650 must be available on filesystems which are mounted in the
1651 correct places.  It is the caller's responsibility to ensure
1652 all filesystems that are needed are mounted at the right
1653 locations.");
1654
1655   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1656    [InitBasicFS, Always, TestOutputList (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command_lines"; "/test-command 1"]], ["Result1"]);
1660     InitBasicFS, Always, TestOutputList (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command_lines"; "/test-command 2"]], ["Result2"]);
1664     InitBasicFS, Always, TestOutputList (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1668     InitBasicFS, Always, TestOutputList (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1672     InitBasicFS, Always, TestOutputList (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1676     InitBasicFS, Always, TestOutputList (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1680     InitBasicFS, Always, TestOutputList (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command_lines"; "/test-command 7"]], []);
1684     InitBasicFS, Always, TestOutputList (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command_lines"; "/test-command 8"]], [""]);
1688     InitBasicFS, Always, TestOutputList (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command_lines"; "/test-command 9"]], ["";""]);
1692     InitBasicFS, Always, TestOutputList (
1693       [["upload"; "test-command"; "/test-command"];
1694        ["chmod"; "0o755"; "/test-command"];
1695        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1696     InitBasicFS, Always, TestOutputList (
1697       [["upload"; "test-command"; "/test-command"];
1698        ["chmod"; "0o755"; "/test-command"];
1699        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1700    "run a command, returning lines",
1701    "\
1702 This is the same as C<guestfs_command>, but splits the
1703 result into a list of lines.
1704
1705 See also: C<guestfs_sh_lines>");
1706
1707   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1708    [InitISOFS, Always, TestOutputStruct (
1709       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1710    "get file information",
1711    "\
1712 Returns file information for the given C<path>.
1713
1714 This is the same as the C<stat(2)> system call.");
1715
1716   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1717    [InitISOFS, Always, TestOutputStruct (
1718       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1719    "get file information for a symbolic link",
1720    "\
1721 Returns file information for the given C<path>.
1722
1723 This is the same as C<guestfs_stat> except that if C<path>
1724 is a symbolic link, then the link is stat-ed, not the file it
1725 refers to.
1726
1727 This is the same as the C<lstat(2)> system call.");
1728
1729   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1730    [InitISOFS, Always, TestOutputStruct (
1731       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1732    "get file system statistics",
1733    "\
1734 Returns file system statistics for any mounted file system.
1735 C<path> should be a file or directory in the mounted file system
1736 (typically it is the mount point itself, but it doesn't need to be).
1737
1738 This is the same as the C<statvfs(2)> system call.");
1739
1740   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1741    [], (* XXX test *)
1742    "get ext2/ext3/ext4 superblock details",
1743    "\
1744 This returns the contents of the ext2, ext3 or ext4 filesystem
1745 superblock on C<device>.
1746
1747 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1748 manpage for more details.  The list of fields returned isn't
1749 clearly defined, and depends on both the version of C<tune2fs>
1750 that libguestfs was built against, and the filesystem itself.");
1751
1752   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1753    [InitEmpty, Always, TestOutputTrue (
1754       [["blockdev_setro"; "/dev/sda"];
1755        ["blockdev_getro"; "/dev/sda"]])],
1756    "set block device to read-only",
1757    "\
1758 Sets the block device named C<device> to read-only.
1759
1760 This uses the L<blockdev(8)> command.");
1761
1762   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1763    [InitEmpty, Always, TestOutputFalse (
1764       [["blockdev_setrw"; "/dev/sda"];
1765        ["blockdev_getro"; "/dev/sda"]])],
1766    "set block device to read-write",
1767    "\
1768 Sets the block device named C<device> to read-write.
1769
1770 This uses the L<blockdev(8)> command.");
1771
1772   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1773    [InitEmpty, Always, TestOutputTrue (
1774       [["blockdev_setro"; "/dev/sda"];
1775        ["blockdev_getro"; "/dev/sda"]])],
1776    "is block device set to read-only",
1777    "\
1778 Returns a boolean indicating if the block device is read-only
1779 (true if read-only, false if not).
1780
1781 This uses the L<blockdev(8)> command.");
1782
1783   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1784    [InitEmpty, Always, TestOutputInt (
1785       [["blockdev_getss"; "/dev/sda"]], 512)],
1786    "get sectorsize of block device",
1787    "\
1788 This returns the size of sectors on a block device.
1789 Usually 512, but can be larger for modern devices.
1790
1791 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1792 for that).
1793
1794 This uses the L<blockdev(8)> command.");
1795
1796   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1797    [InitEmpty, Always, TestOutputInt (
1798       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1799    "get blocksize of block device",
1800    "\
1801 This returns the block size of a device.
1802
1803 (Note this is different from both I<size in blocks> and
1804 I<filesystem block size>).
1805
1806 This uses the L<blockdev(8)> command.");
1807
1808   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1809    [], (* XXX test *)
1810    "set blocksize of block device",
1811    "\
1812 This sets the block size of a device.
1813
1814 (Note this is different from both I<size in blocks> and
1815 I<filesystem block size>).
1816
1817 This uses the L<blockdev(8)> command.");
1818
1819   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1820    [InitEmpty, Always, TestOutputInt (
1821       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1822    "get total size of device in 512-byte sectors",
1823    "\
1824 This returns the size of the device in units of 512-byte sectors
1825 (even if the sectorsize isn't 512 bytes ... weird).
1826
1827 See also C<guestfs_blockdev_getss> for the real sector size of
1828 the device, and C<guestfs_blockdev_getsize64> for the more
1829 useful I<size in bytes>.
1830
1831 This uses the L<blockdev(8)> command.");
1832
1833   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1834    [InitEmpty, Always, TestOutputInt (
1835       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1836    "get total size of device in bytes",
1837    "\
1838 This returns the size of the device in bytes.
1839
1840 See also C<guestfs_blockdev_getsz>.
1841
1842 This uses the L<blockdev(8)> command.");
1843
1844   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1845    [InitEmpty, Always, TestRun
1846       [["blockdev_flushbufs"; "/dev/sda"]]],
1847    "flush device buffers",
1848    "\
1849 This tells the kernel to flush internal buffers associated
1850 with C<device>.
1851
1852 This uses the L<blockdev(8)> command.");
1853
1854   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1855    [InitEmpty, Always, TestRun
1856       [["blockdev_rereadpt"; "/dev/sda"]]],
1857    "reread partition table",
1858    "\
1859 Reread the partition table on C<device>.
1860
1861 This uses the L<blockdev(8)> command.");
1862
1863   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1864    [InitBasicFS, Always, TestOutput (
1865       (* Pick a file from cwd which isn't likely to change. *)
1866       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1867        ["checksum"; "md5"; "/COPYING.LIB"]],
1868         Digest.to_hex (Digest.file "COPYING.LIB"))],
1869    "upload a file from the local machine",
1870    "\
1871 Upload local file C<filename> to C<remotefilename> on the
1872 filesystem.
1873
1874 C<filename> can also be a named pipe.
1875
1876 See also C<guestfs_download>.");
1877
1878   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1879    [InitBasicFS, Always, TestOutput (
1880       (* Pick a file from cwd which isn't likely to change. *)
1881       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1882        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1883        ["upload"; "testdownload.tmp"; "/upload"];
1884        ["checksum"; "md5"; "/upload"]],
1885         Digest.to_hex (Digest.file "COPYING.LIB"))],
1886    "download a file to the local machine",
1887    "\
1888 Download file C<remotefilename> and save it as C<filename>
1889 on the local machine.
1890
1891 C<filename> can also be a named pipe.
1892
1893 See also C<guestfs_upload>, C<guestfs_cat>.");
1894
1895   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1896    [InitISOFS, Always, TestOutput (
1897       [["checksum"; "crc"; "/known-3"]], "2891671662");
1898     InitISOFS, Always, TestLastFail (
1899       [["checksum"; "crc"; "/notexists"]]);
1900     InitISOFS, Always, TestOutput (
1901       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1902     InitISOFS, Always, TestOutput (
1903       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1904     InitISOFS, Always, TestOutput (
1905       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1906     InitISOFS, Always, TestOutput (
1907       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1908     InitISOFS, Always, TestOutput (
1909       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1910     InitISOFS, Always, TestOutput (
1911       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1912    "compute MD5, SHAx or CRC checksum of file",
1913    "\
1914 This call computes the MD5, SHAx or CRC checksum of the
1915 file named C<path>.
1916
1917 The type of checksum to compute is given by the C<csumtype>
1918 parameter which must have one of the following values:
1919
1920 =over 4
1921
1922 =item C<crc>
1923
1924 Compute the cyclic redundancy check (CRC) specified by POSIX
1925 for the C<cksum> command.
1926
1927 =item C<md5>
1928
1929 Compute the MD5 hash (using the C<md5sum> program).
1930
1931 =item C<sha1>
1932
1933 Compute the SHA1 hash (using the C<sha1sum> program).
1934
1935 =item C<sha224>
1936
1937 Compute the SHA224 hash (using the C<sha224sum> program).
1938
1939 =item C<sha256>
1940
1941 Compute the SHA256 hash (using the C<sha256sum> program).
1942
1943 =item C<sha384>
1944
1945 Compute the SHA384 hash (using the C<sha384sum> program).
1946
1947 =item C<sha512>
1948
1949 Compute the SHA512 hash (using the C<sha512sum> program).
1950
1951 =back
1952
1953 The checksum is returned as a printable string.");
1954
1955   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1956    [InitBasicFS, Always, TestOutput (
1957       [["tar_in"; "../images/helloworld.tar"; "/"];
1958        ["cat"; "/hello"]], "hello\n")],
1959    "unpack tarfile to directory",
1960    "\
1961 This command uploads and unpacks local file C<tarfile> (an
1962 I<uncompressed> tar file) into C<directory>.
1963
1964 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1965
1966   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1967    [],
1968    "pack directory into tarfile",
1969    "\
1970 This command packs the contents of C<directory> and downloads
1971 it to local file C<tarfile>.
1972
1973 To download a compressed tarball, use C<guestfs_tgz_out>.");
1974
1975   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1976    [InitBasicFS, Always, TestOutput (
1977       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1978        ["cat"; "/hello"]], "hello\n")],
1979    "unpack compressed tarball to directory",
1980    "\
1981 This command uploads and unpacks local file C<tarball> (a
1982 I<gzip compressed> tar file) into C<directory>.
1983
1984 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1985
1986   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1987    [],
1988    "pack directory into compressed tarball",
1989    "\
1990 This command packs the contents of C<directory> and downloads
1991 it to local file C<tarball>.
1992
1993 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1994
1995   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1996    [InitBasicFS, Always, TestLastFail (
1997       [["umount"; "/"];
1998        ["mount_ro"; "/dev/sda1"; "/"];
1999        ["touch"; "/new"]]);
2000     InitBasicFS, Always, TestOutput (
2001       [["write_file"; "/new"; "data"; "0"];
2002        ["umount"; "/"];
2003        ["mount_ro"; "/dev/sda1"; "/"];
2004        ["cat"; "/new"]], "data")],
2005    "mount a guest disk, read-only",
2006    "\
2007 This is the same as the C<guestfs_mount> command, but it
2008 mounts the filesystem with the read-only (I<-o ro>) flag.");
2009
2010   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2011    [],
2012    "mount a guest disk with mount options",
2013    "\
2014 This is the same as the C<guestfs_mount> command, but it
2015 allows you to set the mount options as for the
2016 L<mount(8)> I<-o> flag.");
2017
2018   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2019    [],
2020    "mount a guest disk with mount options and vfstype",
2021    "\
2022 This is the same as the C<guestfs_mount> command, but it
2023 allows you to set both the mount options and the vfstype
2024 as for the L<mount(8)> I<-o> and I<-t> flags.");
2025
2026   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2027    [],
2028    "debugging and internals",
2029    "\
2030 The C<guestfs_debug> command exposes some internals of
2031 C<guestfsd> (the guestfs daemon) that runs inside the
2032 qemu subprocess.
2033
2034 There is no comprehensive help for this command.  You have
2035 to look at the file C<daemon/debug.c> in the libguestfs source
2036 to find out what you can do.");
2037
2038   ("lvremove", (RErr, [Device "device"]), 77, [],
2039    [InitEmpty, Always, TestOutputList (
2040       [["part_disk"; "/dev/sda"; "mbr"];
2041        ["pvcreate"; "/dev/sda1"];
2042        ["vgcreate"; "VG"; "/dev/sda1"];
2043        ["lvcreate"; "LV1"; "VG"; "50"];
2044        ["lvcreate"; "LV2"; "VG"; "50"];
2045        ["lvremove"; "/dev/VG/LV1"];
2046        ["lvs"]], ["/dev/VG/LV2"]);
2047     InitEmpty, Always, TestOutputList (
2048       [["part_disk"; "/dev/sda"; "mbr"];
2049        ["pvcreate"; "/dev/sda1"];
2050        ["vgcreate"; "VG"; "/dev/sda1"];
2051        ["lvcreate"; "LV1"; "VG"; "50"];
2052        ["lvcreate"; "LV2"; "VG"; "50"];
2053        ["lvremove"; "/dev/VG"];
2054        ["lvs"]], []);
2055     InitEmpty, Always, TestOutputList (
2056       [["part_disk"; "/dev/sda"; "mbr"];
2057        ["pvcreate"; "/dev/sda1"];
2058        ["vgcreate"; "VG"; "/dev/sda1"];
2059        ["lvcreate"; "LV1"; "VG"; "50"];
2060        ["lvcreate"; "LV2"; "VG"; "50"];
2061        ["lvremove"; "/dev/VG"];
2062        ["vgs"]], ["VG"])],
2063    "remove an LVM logical volume",
2064    "\
2065 Remove an LVM logical volume C<device>, where C<device> is
2066 the path to the LV, such as C</dev/VG/LV>.
2067
2068 You can also remove all LVs in a volume group by specifying
2069 the VG name, C</dev/VG>.");
2070
2071   ("vgremove", (RErr, [String "vgname"]), 78, [],
2072    [InitEmpty, Always, TestOutputList (
2073       [["part_disk"; "/dev/sda"; "mbr"];
2074        ["pvcreate"; "/dev/sda1"];
2075        ["vgcreate"; "VG"; "/dev/sda1"];
2076        ["lvcreate"; "LV1"; "VG"; "50"];
2077        ["lvcreate"; "LV2"; "VG"; "50"];
2078        ["vgremove"; "VG"];
2079        ["lvs"]], []);
2080     InitEmpty, Always, TestOutputList (
2081       [["part_disk"; "/dev/sda"; "mbr"];
2082        ["pvcreate"; "/dev/sda1"];
2083        ["vgcreate"; "VG"; "/dev/sda1"];
2084        ["lvcreate"; "LV1"; "VG"; "50"];
2085        ["lvcreate"; "LV2"; "VG"; "50"];
2086        ["vgremove"; "VG"];
2087        ["vgs"]], [])],
2088    "remove an LVM volume group",
2089    "\
2090 Remove an LVM volume group C<vgname>, (for example C<VG>).
2091
2092 This also forcibly removes all logical volumes in the volume
2093 group (if any).");
2094
2095   ("pvremove", (RErr, [Device "device"]), 79, [],
2096    [InitEmpty, Always, TestOutputListOfDevices (
2097       [["part_disk"; "/dev/sda"; "mbr"];
2098        ["pvcreate"; "/dev/sda1"];
2099        ["vgcreate"; "VG"; "/dev/sda1"];
2100        ["lvcreate"; "LV1"; "VG"; "50"];
2101        ["lvcreate"; "LV2"; "VG"; "50"];
2102        ["vgremove"; "VG"];
2103        ["pvremove"; "/dev/sda1"];
2104        ["lvs"]], []);
2105     InitEmpty, Always, TestOutputListOfDevices (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["vgremove"; "VG"];
2112        ["pvremove"; "/dev/sda1"];
2113        ["vgs"]], []);
2114     InitEmpty, Always, TestOutputListOfDevices (
2115       [["part_disk"; "/dev/sda"; "mbr"];
2116        ["pvcreate"; "/dev/sda1"];
2117        ["vgcreate"; "VG"; "/dev/sda1"];
2118        ["lvcreate"; "LV1"; "VG"; "50"];
2119        ["lvcreate"; "LV2"; "VG"; "50"];
2120        ["vgremove"; "VG"];
2121        ["pvremove"; "/dev/sda1"];
2122        ["pvs"]], [])],
2123    "remove an LVM physical volume",
2124    "\
2125 This wipes a physical volume C<device> so that LVM will no longer
2126 recognise it.
2127
2128 The implementation uses the C<pvremove> command which refuses to
2129 wipe physical volumes that contain any volume groups, so you have
2130 to remove those first.");
2131
2132   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2133    [InitBasicFS, Always, TestOutput (
2134       [["set_e2label"; "/dev/sda1"; "testlabel"];
2135        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2136    "set the ext2/3/4 filesystem label",
2137    "\
2138 This sets the ext2/3/4 filesystem label of the filesystem on
2139 C<device> to C<label>.  Filesystem labels are limited to
2140 16 characters.
2141
2142 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2143 to return the existing label on a filesystem.");
2144
2145   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2146    [],
2147    "get the ext2/3/4 filesystem label",
2148    "\
2149 This returns the ext2/3/4 filesystem label of the filesystem on
2150 C<device>.");
2151
2152   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2153    (let uuid = uuidgen () in
2154     [InitBasicFS, Always, TestOutput (
2155        [["set_e2uuid"; "/dev/sda1"; uuid];
2156         ["get_e2uuid"; "/dev/sda1"]], uuid);
2157      InitBasicFS, Always, TestOutput (
2158        [["set_e2uuid"; "/dev/sda1"; "clear"];
2159         ["get_e2uuid"; "/dev/sda1"]], "");
2160      (* We can't predict what UUIDs will be, so just check the commands run. *)
2161      InitBasicFS, Always, TestRun (
2162        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2163      InitBasicFS, Always, TestRun (
2164        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2165    "set the ext2/3/4 filesystem UUID",
2166    "\
2167 This sets the ext2/3/4 filesystem UUID of the filesystem on
2168 C<device> to C<uuid>.  The format of the UUID and alternatives
2169 such as C<clear>, C<random> and C<time> are described in the
2170 L<tune2fs(8)> manpage.
2171
2172 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2173 to return the existing UUID of a filesystem.");
2174
2175   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2176    [],
2177    "get the ext2/3/4 filesystem UUID",
2178    "\
2179 This returns the ext2/3/4 filesystem UUID of the filesystem on
2180 C<device>.");
2181
2182   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2183    [InitBasicFS, Always, TestOutputInt (
2184       [["umount"; "/dev/sda1"];
2185        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2186     InitBasicFS, Always, TestOutputInt (
2187       [["umount"; "/dev/sda1"];
2188        ["zero"; "/dev/sda1"];
2189        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2190    "run the filesystem checker",
2191    "\
2192 This runs the filesystem checker (fsck) on C<device> which
2193 should have filesystem type C<fstype>.
2194
2195 The returned integer is the status.  See L<fsck(8)> for the
2196 list of status codes from C<fsck>.
2197
2198 Notes:
2199
2200 =over 4
2201
2202 =item *
2203
2204 Multiple status codes can be summed together.
2205
2206 =item *
2207
2208 A non-zero return code can mean \"success\", for example if
2209 errors have been corrected on the filesystem.
2210
2211 =item *
2212
2213 Checking or repairing NTFS volumes is not supported
2214 (by linux-ntfs).
2215
2216 =back
2217
2218 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2219
2220   ("zero", (RErr, [Device "device"]), 85, [],
2221    [InitBasicFS, Always, TestOutput (
2222       [["umount"; "/dev/sda1"];
2223        ["zero"; "/dev/sda1"];
2224        ["file"; "/dev/sda1"]], "data")],
2225    "write zeroes to the device",
2226    "\
2227 This command writes zeroes over the first few blocks of C<device>.
2228
2229 How many blocks are zeroed isn't specified (but it's I<not> enough
2230 to securely wipe the device).  It should be sufficient to remove
2231 any partition tables, filesystem superblocks and so on.
2232
2233 See also: C<guestfs_scrub_device>.");
2234
2235   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2236    (* Test disabled because grub-install incompatible with virtio-blk driver.
2237     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2238     *)
2239    [InitBasicFS, Disabled, TestOutputTrue (
2240       [["grub_install"; "/"; "/dev/sda1"];
2241        ["is_dir"; "/boot"]])],
2242    "install GRUB",
2243    "\
2244 This command installs GRUB (the Grand Unified Bootloader) on
2245 C<device>, with the root directory being C<root>.");
2246
2247   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2248    [InitBasicFS, Always, TestOutput (
2249       [["write_file"; "/old"; "file content"; "0"];
2250        ["cp"; "/old"; "/new"];
2251        ["cat"; "/new"]], "file content");
2252     InitBasicFS, Always, TestOutputTrue (
2253       [["write_file"; "/old"; "file content"; "0"];
2254        ["cp"; "/old"; "/new"];
2255        ["is_file"; "/old"]]);
2256     InitBasicFS, Always, TestOutput (
2257       [["write_file"; "/old"; "file content"; "0"];
2258        ["mkdir"; "/dir"];
2259        ["cp"; "/old"; "/dir/new"];
2260        ["cat"; "/dir/new"]], "file content")],
2261    "copy a file",
2262    "\
2263 This copies a file from C<src> to C<dest> where C<dest> is
2264 either a destination filename or destination directory.");
2265
2266   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2267    [InitBasicFS, Always, TestOutput (
2268       [["mkdir"; "/olddir"];
2269        ["mkdir"; "/newdir"];
2270        ["write_file"; "/olddir/file"; "file content"; "0"];
2271        ["cp_a"; "/olddir"; "/newdir"];
2272        ["cat"; "/newdir/olddir/file"]], "file content")],
2273    "copy a file or directory recursively",
2274    "\
2275 This copies a file or directory from C<src> to C<dest>
2276 recursively using the C<cp -a> command.");
2277
2278   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2279    [InitBasicFS, Always, TestOutput (
2280       [["write_file"; "/old"; "file content"; "0"];
2281        ["mv"; "/old"; "/new"];
2282        ["cat"; "/new"]], "file content");
2283     InitBasicFS, Always, TestOutputFalse (
2284       [["write_file"; "/old"; "file content"; "0"];
2285        ["mv"; "/old"; "/new"];
2286        ["is_file"; "/old"]])],
2287    "move a file",
2288    "\
2289 This moves a file from C<src> to C<dest> where C<dest> is
2290 either a destination filename or destination directory.");
2291
2292   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2293    [InitEmpty, Always, TestRun (
2294       [["drop_caches"; "3"]])],
2295    "drop kernel page cache, dentries and inodes",
2296    "\
2297 This instructs the guest kernel to drop its page cache,
2298 and/or dentries and inode caches.  The parameter C<whattodrop>
2299 tells the kernel what precisely to drop, see
2300 L<http://linux-mm.org/Drop_Caches>
2301
2302 Setting C<whattodrop> to 3 should drop everything.
2303
2304 This automatically calls L<sync(2)> before the operation,
2305 so that the maximum guest memory is freed.");
2306
2307   ("dmesg", (RString "kmsgs", []), 91, [],
2308    [InitEmpty, Always, TestRun (
2309       [["dmesg"]])],
2310    "return kernel messages",
2311    "\
2312 This returns the kernel messages (C<dmesg> output) from
2313 the guest kernel.  This is sometimes useful for extended
2314 debugging of problems.
2315
2316 Another way to get the same information is to enable
2317 verbose messages with C<guestfs_set_verbose> or by setting
2318 the environment variable C<LIBGUESTFS_DEBUG=1> before
2319 running the program.");
2320
2321   ("ping_daemon", (RErr, []), 92, [],
2322    [InitEmpty, Always, TestRun (
2323       [["ping_daemon"]])],
2324    "ping the guest daemon",
2325    "\
2326 This is a test probe into the guestfs daemon running inside
2327 the qemu subprocess.  Calling this function checks that the
2328 daemon responds to the ping message, without affecting the daemon
2329 or attached block device(s) in any other way.");
2330
2331   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2332    [InitBasicFS, Always, TestOutputTrue (
2333       [["write_file"; "/file1"; "contents of a file"; "0"];
2334        ["cp"; "/file1"; "/file2"];
2335        ["equal"; "/file1"; "/file2"]]);
2336     InitBasicFS, Always, TestOutputFalse (
2337       [["write_file"; "/file1"; "contents of a file"; "0"];
2338        ["write_file"; "/file2"; "contents of another file"; "0"];
2339        ["equal"; "/file1"; "/file2"]]);
2340     InitBasicFS, Always, TestLastFail (
2341       [["equal"; "/file1"; "/file2"]])],
2342    "test if two files have equal contents",
2343    "\
2344 This compares the two files C<file1> and C<file2> and returns
2345 true if their content is exactly equal, or false otherwise.
2346
2347 The external L<cmp(1)> program is used for the comparison.");
2348
2349   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2350    [InitISOFS, Always, TestOutputList (
2351       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2352     InitISOFS, Always, TestOutputList (
2353       [["strings"; "/empty"]], [])],
2354    "print the printable strings in a file",
2355    "\
2356 This runs the L<strings(1)> command on a file and returns
2357 the list of printable strings found.");
2358
2359   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2360    [InitISOFS, Always, TestOutputList (
2361       [["strings_e"; "b"; "/known-5"]], []);
2362     InitBasicFS, Disabled, TestOutputList (
2363       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2364        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2365    "print the printable strings in a file",
2366    "\
2367 This is like the C<guestfs_strings> command, but allows you to
2368 specify the encoding.
2369
2370 See the L<strings(1)> manpage for the full list of encodings.
2371
2372 Commonly useful encodings are C<l> (lower case L) which will
2373 show strings inside Windows/x86 files.
2374
2375 The returned strings are transcoded to UTF-8.");
2376
2377   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2378    [InitISOFS, Always, TestOutput (
2379       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2380     (* Test for RHBZ#501888c2 regression which caused large hexdump
2381      * commands to segfault.
2382      *)
2383     InitISOFS, Always, TestRun (
2384       [["hexdump"; "/100krandom"]])],
2385    "dump a file in hexadecimal",
2386    "\
2387 This runs C<hexdump -C> on the given C<path>.  The result is
2388 the human-readable, canonical hex dump of the file.");
2389
2390   ("zerofree", (RErr, [Device "device"]), 97, [],
2391    [InitNone, Always, TestOutput (
2392       [["part_disk"; "/dev/sda"; "mbr"];
2393        ["mkfs"; "ext3"; "/dev/sda1"];
2394        ["mount"; "/dev/sda1"; "/"];
2395        ["write_file"; "/new"; "test file"; "0"];
2396        ["umount"; "/dev/sda1"];
2397        ["zerofree"; "/dev/sda1"];
2398        ["mount"; "/dev/sda1"; "/"];
2399        ["cat"; "/new"]], "test file")],
2400    "zero unused inodes and disk blocks on ext2/3 filesystem",
2401    "\
2402 This runs the I<zerofree> program on C<device>.  This program
2403 claims to zero unused inodes and disk blocks on an ext2/3
2404 filesystem, thus making it possible to compress the filesystem
2405 more effectively.
2406
2407 You should B<not> run this program if the filesystem is
2408 mounted.
2409
2410 It is possible that using this program can damage the filesystem
2411 or data on the filesystem.");
2412
2413   ("pvresize", (RErr, [Device "device"]), 98, [],
2414    [],
2415    "resize an LVM physical volume",
2416    "\
2417 This resizes (expands or shrinks) an existing LVM physical
2418 volume to match the new size of the underlying device.");
2419
2420   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2421                        Int "cyls"; Int "heads"; Int "sectors";
2422                        String "line"]), 99, [DangerWillRobinson],
2423    [],
2424    "modify a single partition on a block device",
2425    "\
2426 This runs L<sfdisk(8)> option to modify just the single
2427 partition C<n> (note: C<n> counts from 1).
2428
2429 For other parameters, see C<guestfs_sfdisk>.  You should usually
2430 pass C<0> for the cyls/heads/sectors parameters.
2431
2432 See also: C<guestfs_part_add>");
2433
2434   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2435    [],
2436    "display the partition table",
2437    "\
2438 This displays the partition table on C<device>, in the
2439 human-readable output of the L<sfdisk(8)> command.  It is
2440 not intended to be parsed.
2441
2442 See also: C<guestfs_part_list>");
2443
2444   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2445    [],
2446    "display the kernel geometry",
2447    "\
2448 This displays the kernel's idea of the geometry of C<device>.
2449
2450 The result is in human-readable format, and not designed to
2451 be parsed.");
2452
2453   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2454    [],
2455    "display the disk geometry from the partition table",
2456    "\
2457 This displays the disk geometry of C<device> read from the
2458 partition table.  Especially in the case where the underlying
2459 block device has been resized, this can be different from the
2460 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2461
2462 The result is in human-readable format, and not designed to
2463 be parsed.");
2464
2465   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2466    [],
2467    "activate or deactivate all volume groups",
2468    "\
2469 This command activates or (if C<activate> is false) deactivates
2470 all logical volumes in all volume groups.
2471 If activated, then they are made known to the
2472 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2473 then those devices disappear.
2474
2475 This command is the same as running C<vgchange -a y|n>");
2476
2477   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2478    [],
2479    "activate or deactivate some volume groups",
2480    "\
2481 This command activates or (if C<activate> is false) deactivates
2482 all logical volumes in the listed volume groups C<volgroups>.
2483 If activated, then they are made known to the
2484 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2485 then those devices disappear.
2486
2487 This command is the same as running C<vgchange -a y|n volgroups...>
2488
2489 Note that if C<volgroups> is an empty list then B<all> volume groups
2490 are activated or deactivated.");
2491
2492   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2493    [InitNone, Always, TestOutput (
2494       [["part_disk"; "/dev/sda"; "mbr"];
2495        ["pvcreate"; "/dev/sda1"];
2496        ["vgcreate"; "VG"; "/dev/sda1"];
2497        ["lvcreate"; "LV"; "VG"; "10"];
2498        ["mkfs"; "ext2"; "/dev/VG/LV"];
2499        ["mount"; "/dev/VG/LV"; "/"];
2500        ["write_file"; "/new"; "test content"; "0"];
2501        ["umount"; "/"];
2502        ["lvresize"; "/dev/VG/LV"; "20"];
2503        ["e2fsck_f"; "/dev/VG/LV"];
2504        ["resize2fs"; "/dev/VG/LV"];
2505        ["mount"; "/dev/VG/LV"; "/"];
2506        ["cat"; "/new"]], "test content")],
2507    "resize an LVM logical volume",
2508    "\
2509 This resizes (expands or shrinks) an existing LVM logical
2510 volume to C<mbytes>.  When reducing, data in the reduced part
2511 is lost.");
2512
2513   ("resize2fs", (RErr, [Device "device"]), 106, [],
2514    [], (* lvresize tests this *)
2515    "resize an ext2/ext3 filesystem",
2516    "\
2517 This resizes an ext2 or ext3 filesystem to match the size of
2518 the underlying device.
2519
2520 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2521 on the C<device> before calling this command.  For unknown reasons
2522 C<resize2fs> sometimes gives an error about this and sometimes not.
2523 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2524 calling this function.");
2525
2526   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2527    [InitBasicFS, Always, TestOutputList (
2528       [["find"; "/"]], ["lost+found"]);
2529     InitBasicFS, Always, TestOutputList (
2530       [["touch"; "/a"];
2531        ["mkdir"; "/b"];
2532        ["touch"; "/b/c"];
2533        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2534     InitBasicFS, Always, TestOutputList (
2535       [["mkdir_p"; "/a/b/c"];
2536        ["touch"; "/a/b/c/d"];
2537        ["find"; "/a/b/"]], ["c"; "c/d"])],
2538    "find all files and directories",
2539    "\
2540 This command lists out all files and directories, recursively,
2541 starting at C<directory>.  It is essentially equivalent to
2542 running the shell command C<find directory -print> but some
2543 post-processing happens on the output, described below.
2544
2545 This returns a list of strings I<without any prefix>.  Thus
2546 if the directory structure was:
2547
2548  /tmp/a
2549  /tmp/b
2550  /tmp/c/d
2551
2552 then the returned list from C<guestfs_find> C</tmp> would be
2553 4 elements:
2554
2555  a
2556  b
2557  c
2558  c/d
2559
2560 If C<directory> is not a directory, then this command returns
2561 an error.
2562
2563 The returned list is sorted.
2564
2565 See also C<guestfs_find0>.");
2566
2567   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2568    [], (* lvresize tests this *)
2569    "check an ext2/ext3 filesystem",
2570    "\
2571 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2572 filesystem checker on C<device>, noninteractively (C<-p>),
2573 even if the filesystem appears to be clean (C<-f>).
2574
2575 This command is only needed because of C<guestfs_resize2fs>
2576 (q.v.).  Normally you should use C<guestfs_fsck>.");
2577
2578   ("sleep", (RErr, [Int "secs"]), 109, [],
2579    [InitNone, Always, TestRun (
2580       [["sleep"; "1"]])],
2581    "sleep for some seconds",
2582    "\
2583 Sleep for C<secs> seconds.");
2584
2585   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2586    [InitNone, Always, TestOutputInt (
2587       [["part_disk"; "/dev/sda"; "mbr"];
2588        ["mkfs"; "ntfs"; "/dev/sda1"];
2589        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2590     InitNone, Always, TestOutputInt (
2591       [["part_disk"; "/dev/sda"; "mbr"];
2592        ["mkfs"; "ext2"; "/dev/sda1"];
2593        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2594    "probe NTFS volume",
2595    "\
2596 This command runs the L<ntfs-3g.probe(8)> command which probes
2597 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2598 be mounted read-write, and some cannot be mounted at all).
2599
2600 C<rw> is a boolean flag.  Set it to true if you want to test
2601 if the volume can be mounted read-write.  Set it to false if
2602 you want to test if the volume can be mounted read-only.
2603
2604 The return value is an integer which C<0> if the operation
2605 would succeed, or some non-zero value documented in the
2606 L<ntfs-3g.probe(8)> manual page.");
2607
2608   ("sh", (RString "output", [String "command"]), 111, [],
2609    [], (* XXX needs tests *)
2610    "run a command via the shell",
2611    "\
2612 This call runs a command from the guest filesystem via the
2613 guest's C</bin/sh>.
2614
2615 This is like C<guestfs_command>, but passes the command to:
2616
2617  /bin/sh -c \"command\"
2618
2619 Depending on the guest's shell, this usually results in
2620 wildcards being expanded, shell expressions being interpolated
2621 and so on.
2622
2623 All the provisos about C<guestfs_command> apply to this call.");
2624
2625   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2626    [], (* XXX needs tests *)
2627    "run a command via the shell returning lines",
2628    "\
2629 This is the same as C<guestfs_sh>, but splits the result
2630 into a list of lines.
2631
2632 See also: C<guestfs_command_lines>");
2633
2634   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2635    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2636     * code in stubs.c, since all valid glob patterns must start with "/".
2637     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2638     *)
2639    [InitBasicFS, Always, TestOutputList (
2640       [["mkdir_p"; "/a/b/c"];
2641        ["touch"; "/a/b/c/d"];
2642        ["touch"; "/a/b/c/e"];
2643        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2644     InitBasicFS, Always, TestOutputList (
2645       [["mkdir_p"; "/a/b/c"];
2646        ["touch"; "/a/b/c/d"];
2647        ["touch"; "/a/b/c/e"];
2648        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2649     InitBasicFS, Always, TestOutputList (
2650       [["mkdir_p"; "/a/b/c"];
2651        ["touch"; "/a/b/c/d"];
2652        ["touch"; "/a/b/c/e"];
2653        ["glob_expand"; "/a/*/x/*"]], [])],
2654    "expand a wildcard path",
2655    "\
2656 This command searches for all the pathnames matching
2657 C<pattern> according to the wildcard expansion rules
2658 used by the shell.
2659
2660 If no paths match, then this returns an empty list
2661 (note: not an error).
2662
2663 It is just a wrapper around the C L<glob(3)> function
2664 with flags C<GLOB_MARK|GLOB_BRACE>.
2665 See that manual page for more details.");
2666
2667   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2668    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2669       [["scrub_device"; "/dev/sdc"]])],
2670    "scrub (securely wipe) a device",
2671    "\
2672 This command writes patterns over C<device> to make data retrieval
2673 more difficult.
2674
2675 It is an interface to the L<scrub(1)> program.  See that
2676 manual page for more details.");
2677
2678   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2679    [InitBasicFS, Always, TestRun (
2680       [["write_file"; "/file"; "content"; "0"];
2681        ["scrub_file"; "/file"]])],
2682    "scrub (securely wipe) a file",
2683    "\
2684 This command writes patterns over a file to make data retrieval
2685 more difficult.
2686
2687 The file is I<removed> after scrubbing.
2688
2689 It is an interface to the L<scrub(1)> program.  See that
2690 manual page for more details.");
2691
2692   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2693    [], (* XXX needs testing *)
2694    "scrub (securely wipe) free space",
2695    "\
2696 This command creates the directory C<dir> and then fills it
2697 with files until the filesystem is full, and scrubs the files
2698 as for C<guestfs_scrub_file>, and deletes them.
2699 The intention is to scrub any free space on the partition
2700 containing C<dir>.
2701
2702 It is an interface to the L<scrub(1)> program.  See that
2703 manual page for more details.");
2704
2705   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2706    [InitBasicFS, Always, TestRun (
2707       [["mkdir"; "/tmp"];
2708        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2709    "create a temporary directory",
2710    "\
2711 This command creates a temporary directory.  The
2712 C<template> parameter should be a full pathname for the
2713 temporary directory name with the final six characters being
2714 \"XXXXXX\".
2715
2716 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2717 the second one being suitable for Windows filesystems.
2718
2719 The name of the temporary directory that was created
2720 is returned.
2721
2722 The temporary directory is created with mode 0700
2723 and is owned by root.
2724
2725 The caller is responsible for deleting the temporary
2726 directory and its contents after use.
2727
2728 See also: L<mkdtemp(3)>");
2729
2730   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2731    [InitISOFS, Always, TestOutputInt (
2732       [["wc_l"; "/10klines"]], 10000)],
2733    "count lines in a file",
2734    "\
2735 This command counts the lines in a file, using the
2736 C<wc -l> external command.");
2737
2738   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2739    [InitISOFS, Always, TestOutputInt (
2740       [["wc_w"; "/10klines"]], 10000)],
2741    "count words in a file",
2742    "\
2743 This command counts the words in a file, using the
2744 C<wc -w> external command.");
2745
2746   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2747    [InitISOFS, Always, TestOutputInt (
2748       [["wc_c"; "/100kallspaces"]], 102400)],
2749    "count characters in a file",
2750    "\
2751 This command counts the characters in a file, using the
2752 C<wc -c> external command.");
2753
2754   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2755    [InitISOFS, Always, TestOutputList (
2756       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2757    "return first 10 lines of a file",
2758    "\
2759 This command returns up to the first 10 lines of a file as
2760 a list of strings.");
2761
2762   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2763    [InitISOFS, Always, TestOutputList (
2764       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2765     InitISOFS, Always, TestOutputList (
2766       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2767     InitISOFS, Always, TestOutputList (
2768       [["head_n"; "0"; "/10klines"]], [])],
2769    "return first N lines of a file",
2770    "\
2771 If the parameter C<nrlines> is a positive number, this returns the first
2772 C<nrlines> lines of the file C<path>.
2773
2774 If the parameter C<nrlines> is a negative number, this returns lines
2775 from the file C<path>, excluding the last C<nrlines> lines.
2776
2777 If the parameter C<nrlines> is zero, this returns an empty list.");
2778
2779   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2780    [InitISOFS, Always, TestOutputList (
2781       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2782    "return last 10 lines of a file",
2783    "\
2784 This command returns up to the last 10 lines of a file as
2785 a list of strings.");
2786
2787   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2788    [InitISOFS, Always, TestOutputList (
2789       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2790     InitISOFS, Always, TestOutputList (
2791       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2792     InitISOFS, Always, TestOutputList (
2793       [["tail_n"; "0"; "/10klines"]], [])],
2794    "return last N lines of a file",
2795    "\
2796 If the parameter C<nrlines> is a positive number, this returns the last
2797 C<nrlines> lines of the file C<path>.
2798
2799 If the parameter C<nrlines> is a negative number, this returns lines
2800 from the file C<path>, starting with the C<-nrlines>th line.
2801
2802 If the parameter C<nrlines> is zero, this returns an empty list.");
2803
2804   ("df", (RString "output", []), 125, [],
2805    [], (* XXX Tricky to test because it depends on the exact format
2806         * of the 'df' command and other imponderables.
2807         *)
2808    "report file system disk space usage",
2809    "\
2810 This command runs the C<df> command to report disk space used.
2811
2812 This command is mostly useful for interactive sessions.  It
2813 is I<not> intended that you try to parse the output string.
2814 Use C<statvfs> from programs.");
2815
2816   ("df_h", (RString "output", []), 126, [],
2817    [], (* XXX Tricky to test because it depends on the exact format
2818         * of the 'df' command and other imponderables.
2819         *)
2820    "report file system disk space usage (human readable)",
2821    "\
2822 This command runs the C<df -h> command to report disk space used
2823 in human-readable format.
2824
2825 This command is mostly useful for interactive sessions.  It
2826 is I<not> intended that you try to parse the output string.
2827 Use C<statvfs> from programs.");
2828
2829   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2830    [InitISOFS, Always, TestOutputInt (
2831       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2832    "estimate file space usage",
2833    "\
2834 This command runs the C<du -s> command to estimate file space
2835 usage for C<path>.
2836
2837 C<path> can be a file or a directory.  If C<path> is a directory
2838 then the estimate includes the contents of the directory and all
2839 subdirectories (recursively).
2840
2841 The result is the estimated size in I<kilobytes>
2842 (ie. units of 1024 bytes).");
2843
2844   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2845    [InitISOFS, Always, TestOutputList (
2846       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2847    "list files in an initrd",
2848    "\
2849 This command lists out files contained in an initrd.
2850
2851 The files are listed without any initial C</> character.  The
2852 files are listed in the order they appear (not necessarily
2853 alphabetical).  Directory names are listed as separate items.
2854
2855 Old Linux kernels (2.4 and earlier) used a compressed ext2
2856 filesystem as initrd.  We I<only> support the newer initramfs
2857 format (compressed cpio files).");
2858
2859   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2860    [],
2861    "mount a file using the loop device",
2862    "\
2863 This command lets you mount C<file> (a filesystem image
2864 in a file) on a mount point.  It is entirely equivalent to
2865 the command C<mount -o loop file mountpoint>.");
2866
2867   ("mkswap", (RErr, [Device "device"]), 130, [],
2868    [InitEmpty, Always, TestRun (
2869       [["part_disk"; "/dev/sda"; "mbr"];
2870        ["mkswap"; "/dev/sda1"]])],
2871    "create a swap partition",
2872    "\
2873 Create a swap partition on C<device>.");
2874
2875   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2876    [InitEmpty, Always, TestRun (
2877       [["part_disk"; "/dev/sda"; "mbr"];
2878        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2879    "create a swap partition with a label",
2880    "\
2881 Create a swap partition on C<device> with label C<label>.
2882
2883 Note that you cannot attach a swap label to a block device
2884 (eg. C</dev/sda>), just to a partition.  This appears to be
2885 a limitation of the kernel or swap tools.");
2886
2887   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2888    (let uuid = uuidgen () in
2889     [InitEmpty, Always, TestRun (
2890        [["part_disk"; "/dev/sda"; "mbr"];
2891         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2892    "create a swap partition with an explicit UUID",
2893    "\
2894 Create a swap partition on C<device> with UUID C<uuid>.");
2895
2896   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2897    [InitBasicFS, Always, TestOutputStruct (
2898       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2899        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2900        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2901     InitBasicFS, Always, TestOutputStruct (
2902       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2903        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2904    "make block, character or FIFO devices",
2905    "\
2906 This call creates block or character special devices, or
2907 named pipes (FIFOs).
2908
2909 The C<mode> parameter should be the mode, using the standard
2910 constants.  C<devmajor> and C<devminor> are the
2911 device major and minor numbers, only used when creating block
2912 and character special devices.");
2913
2914   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2915    [InitBasicFS, Always, TestOutputStruct (
2916       [["mkfifo"; "0o777"; "/node"];
2917        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2918    "make FIFO (named pipe)",
2919    "\
2920 This call creates a FIFO (named pipe) called C<path> with
2921 mode C<mode>.  It is just a convenient wrapper around
2922 C<guestfs_mknod>.");
2923
2924   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2925    [InitBasicFS, Always, TestOutputStruct (
2926       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2927        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2928    "make block device node",
2929    "\
2930 This call creates a block device node called C<path> with
2931 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2932 It is just a convenient wrapper around C<guestfs_mknod>.");
2933
2934   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2935    [InitBasicFS, Always, TestOutputStruct (
2936       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2937        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2938    "make char device node",
2939    "\
2940 This call creates a char device node called C<path> with
2941 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2942 It is just a convenient wrapper around C<guestfs_mknod>.");
2943
2944   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2945    [], (* XXX umask is one of those stateful things that we should
2946         * reset between each test.
2947         *)
2948    "set file mode creation mask (umask)",
2949    "\
2950 This function sets the mask used for creating new files and
2951 device nodes to C<mask & 0777>.
2952
2953 Typical umask values would be C<022> which creates new files
2954 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2955 C<002> which creates new files with permissions like
2956 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2957
2958 The default umask is C<022>.  This is important because it
2959 means that directories and device nodes will be created with
2960 C<0644> or C<0755> mode even if you specify C<0777>.
2961
2962 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2963
2964 This call returns the previous umask.");
2965
2966   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2967    [],
2968    "read directories entries",
2969    "\
2970 This returns the list of directory entries in directory C<dir>.
2971
2972 All entries in the directory are returned, including C<.> and
2973 C<..>.  The entries are I<not> sorted, but returned in the same
2974 order as the underlying filesystem.
2975
2976 Also this call returns basic file type information about each
2977 file.  The C<ftyp> field will contain one of the following characters:
2978
2979 =over 4
2980
2981 =item 'b'
2982
2983 Block special
2984
2985 =item 'c'
2986
2987 Char special
2988
2989 =item 'd'
2990
2991 Directory
2992
2993 =item 'f'
2994
2995 FIFO (named pipe)
2996
2997 =item 'l'
2998
2999 Symbolic link
3000
3001 =item 'r'
3002
3003 Regular file
3004
3005 =item 's'
3006
3007 Socket
3008
3009 =item 'u'
3010
3011 Unknown file type
3012
3013 =item '?'
3014
3015 The L<readdir(3)> returned a C<d_type> field with an
3016 unexpected value
3017
3018 =back
3019
3020 This function is primarily intended for use by programs.  To
3021 get a simple list of names, use C<guestfs_ls>.  To get a printable
3022 directory for human consumption, use C<guestfs_ll>.");
3023
3024   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3025    [],
3026    "create partitions on a block device",
3027    "\
3028 This is a simplified interface to the C<guestfs_sfdisk>
3029 command, where partition sizes are specified in megabytes
3030 only (rounded to the nearest cylinder) and you don't need
3031 to specify the cyls, heads and sectors parameters which
3032 were rarely if ever used anyway.
3033
3034 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3035 and C<guestfs_part_disk>");
3036
3037   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3038    [],
3039    "determine file type inside a compressed file",
3040    "\
3041 This command runs C<file> after first decompressing C<path>
3042 using C<method>.
3043
3044 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3045
3046 Since 1.0.63, use C<guestfs_file> instead which can now
3047 process compressed files.");
3048
3049   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3050    [],
3051    "list extended attributes of a file or directory",
3052    "\
3053 This call lists the extended attributes of the file or directory
3054 C<path>.
3055
3056 At the system call level, this is a combination of the
3057 L<listxattr(2)> and L<getxattr(2)> calls.
3058
3059 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3060
3061   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3062    [],
3063    "list extended attributes of a file or directory",
3064    "\
3065 This is the same as C<guestfs_getxattrs>, but if C<path>
3066 is a symbolic link, then it returns the extended attributes
3067 of the link itself.");
3068
3069   ("setxattr", (RErr, [String "xattr";
3070                        String "val"; Int "vallen"; (* will be BufferIn *)
3071                        Pathname "path"]), 143, [],
3072    [],
3073    "set extended attribute of a file or directory",
3074    "\
3075 This call sets the extended attribute named C<xattr>
3076 of the file C<path> to the value C<val> (of length C<vallen>).
3077 The value is arbitrary 8 bit data.
3078
3079 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3080
3081   ("lsetxattr", (RErr, [String "xattr";
3082                         String "val"; Int "vallen"; (* will be BufferIn *)
3083                         Pathname "path"]), 144, [],
3084    [],
3085    "set extended attribute of a file or directory",
3086    "\
3087 This is the same as C<guestfs_setxattr>, but if C<path>
3088 is a symbolic link, then it sets an extended attribute
3089 of the link itself.");
3090
3091   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3092    [],
3093    "remove extended attribute of a file or directory",
3094    "\
3095 This call removes the extended attribute named C<xattr>
3096 of the file C<path>.
3097
3098 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3099
3100   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3101    [],
3102    "remove extended attribute of a file or directory",
3103    "\
3104 This is the same as C<guestfs_removexattr>, but if C<path>
3105 is a symbolic link, then it removes an extended attribute
3106 of the link itself.");
3107
3108   ("mountpoints", (RHashtable "mps", []), 147, [],
3109    [],
3110    "show mountpoints",
3111    "\
3112 This call is similar to C<guestfs_mounts>.  That call returns
3113 a list of devices.  This one returns a hash table (map) of
3114 device name to directory where the device is mounted.");
3115
3116   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3117   (* This is a special case: while you would expect a parameter
3118    * of type "Pathname", that doesn't work, because it implies
3119    * NEED_ROOT in the generated calling code in stubs.c, and
3120    * this function cannot use NEED_ROOT.
3121    *)
3122    [],
3123    "create a mountpoint",
3124    "\
3125 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3126 specialized calls that can be used to create extra mountpoints
3127 before mounting the first filesystem.
3128
3129 These calls are I<only> necessary in some very limited circumstances,
3130 mainly the case where you want to mount a mix of unrelated and/or
3131 read-only filesystems together.
3132
3133 For example, live CDs often contain a \"Russian doll\" nest of
3134 filesystems, an ISO outer layer, with a squashfs image inside, with
3135 an ext2/3 image inside that.  You can unpack this as follows
3136 in guestfish:
3137
3138  add-ro Fedora-11-i686-Live.iso
3139  run
3140  mkmountpoint /cd
3141  mkmountpoint /squash
3142  mkmountpoint /ext3
3143  mount /dev/sda /cd
3144  mount-loop /cd/LiveOS/squashfs.img /squash
3145  mount-loop /squash/LiveOS/ext3fs.img /ext3
3146
3147 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3148
3149   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3150    [],
3151    "remove a mountpoint",
3152    "\
3153 This calls removes a mountpoint that was previously created
3154 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3155 for full details.");
3156
3157   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3158    [InitISOFS, Always, TestOutputBuffer (
3159       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3160    "read a file",
3161    "\
3162 This calls returns the contents of the file C<path> as a
3163 buffer.
3164
3165 Unlike C<guestfs_cat>, this function can correctly
3166 handle files that contain embedded ASCII NUL characters.
3167 However unlike C<guestfs_download>, this function is limited
3168 in the total size of file that can be handled.");
3169
3170   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3171    [InitISOFS, Always, TestOutputList (
3172       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3173     InitISOFS, Always, TestOutputList (
3174       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3175    "return lines matching a pattern",
3176    "\
3177 This calls the external C<grep> program and returns the
3178 matching lines.");
3179
3180   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3181    [InitISOFS, Always, TestOutputList (
3182       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3183    "return lines matching a pattern",
3184    "\
3185 This calls the external C<egrep> program and returns the
3186 matching lines.");
3187
3188   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3189    [InitISOFS, Always, TestOutputList (
3190       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3191    "return lines matching a pattern",
3192    "\
3193 This calls the external C<fgrep> program and returns the
3194 matching lines.");
3195
3196   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3197    [InitISOFS, Always, TestOutputList (
3198       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3199    "return lines matching a pattern",
3200    "\
3201 This calls the external C<grep -i> program and returns the
3202 matching lines.");
3203
3204   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3205    [InitISOFS, Always, TestOutputList (
3206       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3207    "return lines matching a pattern",
3208    "\
3209 This calls the external C<egrep -i> program and returns the
3210 matching lines.");
3211
3212   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3213    [InitISOFS, Always, TestOutputList (
3214       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3215    "return lines matching a pattern",
3216    "\
3217 This calls the external C<fgrep -i> program and returns the
3218 matching lines.");
3219
3220   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputList (
3222       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3223    "return lines matching a pattern",
3224    "\
3225 This calls the external C<zgrep> program and returns the
3226 matching lines.");
3227
3228   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3229    [InitISOFS, Always, TestOutputList (
3230       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3231    "return lines matching a pattern",
3232    "\
3233 This calls the external C<zegrep> program and returns the
3234 matching lines.");
3235
3236   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3239    "return lines matching a pattern",
3240    "\
3241 This calls the external C<zfgrep> program and returns the
3242 matching lines.");
3243
3244   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3245    [InitISOFS, Always, TestOutputList (
3246       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3247    "return lines matching a pattern",
3248    "\
3249 This calls the external C<zgrep -i> program and returns the
3250 matching lines.");
3251
3252   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3253    [InitISOFS, Always, TestOutputList (
3254       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3255    "return lines matching a pattern",
3256    "\
3257 This calls the external C<zegrep -i> program and returns the
3258 matching lines.");
3259
3260   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3261    [InitISOFS, Always, TestOutputList (
3262       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3263    "return lines matching a pattern",
3264    "\
3265 This calls the external C<zfgrep -i> program and returns the
3266 matching lines.");
3267
3268   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3269    [InitISOFS, Always, TestOutput (
3270       [["realpath"; "/../directory"]], "/directory")],
3271    "canonicalized absolute pathname",
3272    "\
3273 Return the canonicalized absolute pathname of C<path>.  The
3274 returned path has no C<.>, C<..> or symbolic link path elements.");
3275
3276   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3277    [InitBasicFS, Always, TestOutputStruct (
3278       [["touch"; "/a"];
3279        ["ln"; "/a"; "/b"];
3280        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3281    "create a hard link",
3282    "\
3283 This command creates a hard link using the C<ln> command.");
3284
3285   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3286    [InitBasicFS, Always, TestOutputStruct (
3287       [["touch"; "/a"];
3288        ["touch"; "/b"];
3289        ["ln_f"; "/a"; "/b"];
3290        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3291    "create a hard link",
3292    "\
3293 This command creates a hard link using the C<ln -f> command.
3294 The C<-f> option removes the link (C<linkname>) if it exists already.");
3295
3296   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3297    [InitBasicFS, Always, TestOutputStruct (
3298       [["touch"; "/a"];
3299        ["ln_s"; "a"; "/b"];
3300        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3301    "create a symbolic link",
3302    "\
3303 This command creates a symbolic link using the C<ln -s> command.");
3304
3305   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3306    [InitBasicFS, Always, TestOutput (
3307       [["mkdir_p"; "/a/b"];
3308        ["touch"; "/a/b/c"];
3309        ["ln_sf"; "../d"; "/a/b/c"];
3310        ["readlink"; "/a/b/c"]], "../d")],
3311    "create a symbolic link",
3312    "\
3313 This command creates a symbolic link using the C<ln -sf> command,
3314 The C<-f> option removes the link (C<linkname>) if it exists already.");
3315
3316   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3317    [] (* XXX tested above *),
3318    "read the target of a symbolic link",
3319    "\
3320 This command reads the target of a symbolic link.");
3321
3322   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3323    [InitBasicFS, Always, TestOutputStruct (
3324       [["fallocate"; "/a"; "1000000"];
3325        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3326    "preallocate a file in the guest filesystem",
3327    "\
3328 This command preallocates a file (containing zero bytes) named
3329 C<path> of size C<len> bytes.  If the file exists already, it
3330 is overwritten.
3331
3332 Do not confuse this with the guestfish-specific
3333 C<alloc> command which allocates a file in the host and
3334 attaches it as a device.");
3335
3336   ("swapon_device", (RErr, [Device "device"]), 170, [],
3337    [InitPartition, Always, TestRun (
3338       [["mkswap"; "/dev/sda1"];
3339        ["swapon_device"; "/dev/sda1"];
3340        ["swapoff_device"; "/dev/sda1"]])],
3341    "enable swap on device",
3342    "\
3343 This command enables the libguestfs appliance to use the
3344 swap device or partition named C<device>.  The increased
3345 memory is made available for all commands, for example
3346 those run using C<guestfs_command> or C<guestfs_sh>.
3347
3348 Note that you should not swap to existing guest swap
3349 partitions unless you know what you are doing.  They may
3350 contain hibernation information, or other information that
3351 the guest doesn't want you to trash.  You also risk leaking
3352 information about the host to the guest this way.  Instead,
3353 attach a new host device to the guest and swap on that.");
3354
3355   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3356    [], (* XXX tested by swapon_device *)
3357    "disable swap on device",
3358    "\
3359 This command disables the libguestfs appliance swap
3360 device or partition named C<device>.
3361 See C<guestfs_swapon_device>.");
3362
3363   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3364    [InitBasicFS, Always, TestRun (
3365       [["fallocate"; "/swap"; "8388608"];
3366        ["mkswap_file"; "/swap"];
3367        ["swapon_file"; "/swap"];
3368        ["swapoff_file"; "/swap"]])],
3369    "enable swap on file",
3370    "\
3371 This command enables swap to a file.
3372 See C<guestfs_swapon_device> for other notes.");
3373
3374   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3375    [], (* XXX tested by swapon_file *)
3376    "disable swap on file",
3377    "\
3378 This command disables the libguestfs appliance swap on file.");
3379
3380   ("swapon_label", (RErr, [String "label"]), 174, [],
3381    [InitEmpty, Always, TestRun (
3382       [["part_disk"; "/dev/sdb"; "mbr"];
3383        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3384        ["swapon_label"; "swapit"];
3385        ["swapoff_label"; "swapit"];
3386        ["zero"; "/dev/sdb"];
3387        ["blockdev_rereadpt"; "/dev/sdb"]])],
3388    "enable swap on labeled swap partition",
3389    "\
3390 This command enables swap to a labeled swap partition.
3391 See C<guestfs_swapon_device> for other notes.");
3392
3393   ("swapoff_label", (RErr, [String "label"]), 175, [],
3394    [], (* XXX tested by swapon_label *)
3395    "disable swap on labeled swap partition",
3396    "\
3397 This command disables the libguestfs appliance swap on
3398 labeled swap partition.");
3399
3400   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3401    (let uuid = uuidgen () in
3402     [InitEmpty, Always, TestRun (
3403        [["mkswap_U"; uuid; "/dev/sdb"];
3404         ["swapon_uuid"; uuid];
3405         ["swapoff_uuid"; uuid]])]),
3406    "enable swap on swap partition by UUID",
3407    "\
3408 This command enables swap to a swap partition with the given UUID.
3409 See C<guestfs_swapon_device> for other notes.");
3410
3411   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3412    [], (* XXX tested by swapon_uuid *)
3413    "disable swap on swap partition by UUID",
3414    "\
3415 This command disables the libguestfs appliance swap partition
3416 with the given UUID.");
3417
3418   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3419    [InitBasicFS, Always, TestRun (
3420       [["fallocate"; "/swap"; "8388608"];
3421        ["mkswap_file"; "/swap"]])],
3422    "create a swap file",
3423    "\
3424 Create a swap file.
3425
3426 This command just writes a swap file signature to an existing
3427 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3428
3429   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3430    [InitISOFS, Always, TestRun (
3431       [["inotify_init"; "0"]])],
3432    "create an inotify handle",
3433    "\
3434 This command creates a new inotify handle.
3435 The inotify subsystem can be used to notify events which happen to
3436 objects in the guest filesystem.
3437
3438 C<maxevents> is the maximum number of events which will be
3439 queued up between calls to C<guestfs_inotify_read> or
3440 C<guestfs_inotify_files>.
3441 If this is passed as C<0>, then the kernel (or previously set)
3442 default is used.  For Linux 2.6.29 the default was 16384 events.
3443 Beyond this limit, the kernel throws away events, but records
3444 the fact that it threw them away by setting a flag
3445 C<IN_Q_OVERFLOW> in the returned structure list (see
3446 C<guestfs_inotify_read>).
3447
3448 Before any events are generated, you have to add some
3449 watches to the internal watch list.  See:
3450 C<guestfs_inotify_add_watch>,
3451 C<guestfs_inotify_rm_watch> and
3452 C<guestfs_inotify_watch_all>.
3453
3454 Queued up events should be read periodically by calling
3455 C<guestfs_inotify_read>
3456 (or C<guestfs_inotify_files> which is just a helpful
3457 wrapper around C<guestfs_inotify_read>).  If you don't
3458 read the events out often enough then you risk the internal
3459 queue overflowing.
3460
3461 The handle should be closed after use by calling
3462 C<guestfs_inotify_close>.  This also removes any
3463 watches automatically.
3464
3465 See also L<inotify(7)> for an overview of the inotify interface
3466 as exposed by the Linux kernel, which is roughly what we expose
3467 via libguestfs.  Note that there is one global inotify handle
3468 per libguestfs instance.");
3469
3470   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3471    [InitBasicFS, Always, TestOutputList (
3472       [["inotify_init"; "0"];
3473        ["inotify_add_watch"; "/"; "1073741823"];
3474        ["touch"; "/a"];
3475        ["touch"; "/b"];
3476        ["inotify_files"]], ["a"; "b"])],
3477    "add an inotify watch",
3478    "\
3479 Watch C<path> for the events listed in C<mask>.
3480
3481 Note that if C<path> is a directory then events within that
3482 directory are watched, but this does I<not> happen recursively
3483 (in subdirectories).
3484
3485 Note for non-C or non-Linux callers: the inotify events are
3486 defined by the Linux kernel ABI and are listed in
3487 C</usr/include/sys/inotify.h>.");
3488
3489   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3490    [],
3491    "remove an inotify watch",
3492    "\
3493 Remove a previously defined inotify watch.
3494 See C<guestfs_inotify_add_watch>.");
3495
3496   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3497    [],
3498    "return list of inotify events",
3499    "\
3500 Return the complete queue of events that have happened
3501 since the previous read call.
3502
3503 If no events have happened, this returns an empty list.
3504
3505 I<Note>: In order to make sure that all events have been
3506 read, you must call this function repeatedly until it
3507 returns an empty list.  The reason is that the call will
3508 read events up to the maximum appliance-to-host message
3509 size and leave remaining events in the queue.");
3510
3511   ("inotify_files", (RStringList "paths", []), 183, [],
3512    [],
3513    "return list of watched files that had events",
3514    "\
3515 This function is a helpful wrapper around C<guestfs_inotify_read>
3516 which just returns a list of pathnames of objects that were
3517 touched.  The returned pathnames are sorted and deduplicated.");
3518
3519   ("inotify_close", (RErr, []), 184, [],
3520    [],
3521    "close the inotify handle",
3522    "\
3523 This closes the inotify handle which was previously
3524 opened by inotify_init.  It removes all watches, throws
3525 away any pending events, and deallocates all resources.");
3526
3527   ("setcon", (RErr, [String "context"]), 185, [],
3528    [],
3529    "set SELinux security context",
3530    "\
3531 This sets the SELinux security context of the daemon
3532 to the string C<context>.
3533
3534 See the documentation about SELINUX in L<guestfs(3)>.");
3535
3536   ("getcon", (RString "context", []), 186, [],
3537    [],
3538    "get SELinux security context",
3539    "\
3540 This gets the SELinux security context of the daemon.
3541
3542 See the documentation about SELINUX in L<guestfs(3)>,
3543 and C<guestfs_setcon>");
3544
3545   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3546    [InitEmpty, Always, TestOutput (
3547       [["part_disk"; "/dev/sda"; "mbr"];
3548        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3549        ["mount"; "/dev/sda1"; "/"];
3550        ["write_file"; "/new"; "new file contents"; "0"];
3551        ["cat"; "/new"]], "new file contents")],
3552    "make a filesystem with block size",
3553    "\
3554 This call is similar to C<guestfs_mkfs>, but it allows you to
3555 control the block size of the resulting filesystem.  Supported
3556 block sizes depend on the filesystem type, but typically they
3557 are C<1024>, C<2048> or C<4096> only.");
3558
3559   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3560    [InitEmpty, Always, TestOutput (
3561       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3562        ["mke2journal"; "4096"; "/dev/sda1"];
3563        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3564        ["mount"; "/dev/sda2"; "/"];
3565        ["write_file"; "/new"; "new file contents"; "0"];
3566        ["cat"; "/new"]], "new file contents")],
3567    "make ext2/3/4 external journal",
3568    "\
3569 This creates an ext2 external journal on C<device>.  It is equivalent
3570 to the command:
3571
3572  mke2fs -O journal_dev -b blocksize device");
3573
3574   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3575    [InitEmpty, Always, TestOutput (
3576       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3577        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3578        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3579        ["mount"; "/dev/sda2"; "/"];
3580        ["write_file"; "/new"; "new file contents"; "0"];
3581        ["cat"; "/new"]], "new file contents")],
3582    "make ext2/3/4 external journal with label",
3583    "\
3584 This creates an ext2 external journal on C<device> with label C<label>.");
3585
3586   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3587    (let uuid = uuidgen () in
3588     [InitEmpty, Always, TestOutput (
3589        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3590         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3591         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3592         ["mount"; "/dev/sda2"; "/"];
3593         ["write_file"; "/new"; "new file contents"; "0"];
3594         ["cat"; "/new"]], "new file contents")]),
3595    "make ext2/3/4 external journal with UUID",
3596    "\
3597 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3598
3599   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3600    [],
3601    "make ext2/3/4 filesystem with external journal",
3602    "\
3603 This creates an ext2/3/4 filesystem on C<device> with
3604 an external journal on C<journal>.  It is equivalent
3605 to the command:
3606
3607  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3608
3609 See also C<guestfs_mke2journal>.");
3610
3611   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3612    [],
3613    "make ext2/3/4 filesystem with external journal",
3614    "\
3615 This creates an ext2/3/4 filesystem on C<device> with
3616 an external journal on the journal labeled C<label>.
3617
3618 See also C<guestfs_mke2journal_L>.");
3619
3620   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3621    [],
3622    "make ext2/3/4 filesystem with external journal",
3623    "\
3624 This creates an ext2/3/4 filesystem on C<device> with
3625 an external journal on the journal with UUID C<uuid>.
3626
3627 See also C<guestfs_mke2journal_U>.");
3628
3629   ("modprobe", (RErr, [String "modulename"]), 194, [],
3630    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3631    "load a kernel module",
3632    "\
3633 This loads a kernel module in the appliance.
3634
3635 The kernel module must have been whitelisted when libguestfs
3636 was built (see C<appliance/kmod.whitelist.in> in the source).");
3637
3638   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3639    [InitNone, Always, TestOutput (
3640      [["echo_daemon"; "This is a test"]], "This is a test"
3641    )],
3642    "echo arguments back to the client",
3643    "\
3644 This command concatenate the list of C<words> passed with single spaces between
3645 them and returns the resulting string.
3646
3647 You can use this command to test the connection through to the daemon.
3648
3649 See also C<guestfs_ping_daemon>.");
3650
3651   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3652    [], (* There is a regression test for this. *)
3653    "find all files and directories, returning NUL-separated list",
3654    "\
3655 This command lists out all files and directories, recursively,
3656 starting at C<directory>, placing the resulting list in the
3657 external file called C<files>.
3658
3659 This command works the same way as C<guestfs_find> with the
3660 following exceptions:
3661
3662 =over 4
3663
3664 =item *
3665
3666 The resulting list is written to an external file.
3667
3668 =item *
3669
3670 Items (filenames) in the result are separated
3671 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3672
3673 =item *
3674
3675 This command is not limited in the number of names that it
3676 can return.
3677
3678 =item *
3679
3680 The result list is not sorted.
3681
3682 =back");
3683
3684   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3685    [InitISOFS, Always, TestOutput (
3686       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3687     InitISOFS, Always, TestOutput (
3688       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3689     InitISOFS, Always, TestOutput (
3690       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3691     InitISOFS, Always, TestLastFail (
3692       [["case_sensitive_path"; "/Known-1/"]]);
3693     InitBasicFS, Always, TestOutput (
3694       [["mkdir"; "/a"];
3695        ["mkdir"; "/a/bbb"];
3696        ["touch"; "/a/bbb/c"];
3697        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3698     InitBasicFS, Always, TestOutput (
3699       [["mkdir"; "/a"];
3700        ["mkdir"; "/a/bbb"];
3701        ["touch"; "/a/bbb/c"];
3702        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3703     InitBasicFS, Always, TestLastFail (
3704       [["mkdir"; "/a"];
3705        ["mkdir"; "/a/bbb"];
3706        ["touch"; "/a/bbb/c"];
3707        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3708    "return true path on case-insensitive filesystem",
3709    "\
3710 This can be used to resolve case insensitive paths on
3711 a filesystem which is case sensitive.  The use case is
3712 to resolve paths which you have read from Windows configuration
3713 files or the Windows Registry, to the true path.
3714
3715 The command handles a peculiarity of the Linux ntfs-3g
3716 filesystem driver (and probably others), which is that although
3717 the underlying filesystem is case-insensitive, the driver
3718 exports the filesystem to Linux as case-sensitive.
3719
3720 One consequence of this is that special directories such
3721 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3722 (or other things) depending on the precise details of how
3723 they were created.  In Windows itself this would not be
3724 a problem.
3725
3726 Bug or feature?  You decide:
3727 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3728
3729 This function resolves the true case of each element in the
3730 path and returns the case-sensitive path.
3731
3732 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3733 might return C<\"/WINDOWS/system32\"> (the exact return value
3734 would depend on details of how the directories were originally
3735 created under Windows).
3736
3737 I<Note>:
3738 This function does not handle drive names, backslashes etc.
3739
3740 See also C<guestfs_realpath>.");
3741
3742   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3743    [InitBasicFS, Always, TestOutput (
3744       [["vfs_type"; "/dev/sda1"]], "ext2")],
3745    "get the Linux VFS type corresponding to a mounted device",
3746    "\
3747 This command gets the block device type corresponding to
3748 a mounted device called C<device>.
3749
3750 Usually the result is the name of the Linux VFS module that
3751 is used to mount this device (probably determined automatically
3752 if you used the C<guestfs_mount> call).");
3753
3754   ("truncate", (RErr, [Pathname "path"]), 199, [],
3755    [InitBasicFS, Always, TestOutputStruct (
3756       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3757        ["truncate"; "/test"];
3758        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3759    "truncate a file to zero size",
3760    "\
3761 This command truncates C<path> to a zero-length file.  The
3762 file must exist already.");
3763
3764   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3765    [InitBasicFS, Always, TestOutputStruct (
3766       [["touch"; "/test"];
3767        ["truncate_size"; "/test"; "1000"];
3768        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3769    "truncate a file to a particular size",
3770    "\
3771 This command truncates C<path> to size C<size> bytes.  The file
3772 must exist already.  If the file is smaller than C<size> then
3773 the file is extended to the required size with null bytes.");
3774
3775   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3776    [InitBasicFS, Always, TestOutputStruct (
3777       [["touch"; "/test"];
3778        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3779        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3780    "set timestamp of a file with nanosecond precision",
3781    "\
3782 This command sets the timestamps of a file with nanosecond
3783 precision.
3784
3785 C<atsecs, atnsecs> are the last access time (atime) in secs and
3786 nanoseconds from the epoch.
3787
3788 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3789 secs and nanoseconds from the epoch.
3790
3791 If the C<*nsecs> field contains the special value C<-1> then
3792 the corresponding timestamp is set to the current time.  (The
3793 C<*secs> field is ignored in this case).
3794
3795 If the C<*nsecs> field contains the special value C<-2> then
3796 the corresponding timestamp is left unchanged.  (The
3797 C<*secs> field is ignored in this case).");
3798
3799   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3800    [InitBasicFS, Always, TestOutputStruct (
3801       [["mkdir_mode"; "/test"; "0o111"];
3802        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3803    "create a directory with a particular mode",
3804    "\
3805 This command creates a directory, setting the initial permissions
3806 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3807
3808   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3809    [], (* XXX *)
3810    "change file owner and group",
3811    "\
3812 Change the file owner to C<owner> and group to C<group>.
3813 This is like C<guestfs_chown> but if C<path> is a symlink then
3814 the link itself is changed, not the target.
3815
3816 Only numeric uid and gid are supported.  If you want to use
3817 names, you will need to locate and parse the password file
3818 yourself (Augeas support makes this relatively easy).");
3819
3820   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3821    [], (* XXX *)
3822    "lstat on multiple files",
3823    "\
3824 This call allows you to perform the C<guestfs_lstat> operation
3825 on multiple files, where all files are in the directory C<path>.
3826 C<names> is the list of files from this directory.
3827
3828 On return you get a list of stat structs, with a one-to-one
3829 correspondence to the C<names> list.  If any name did not exist
3830 or could not be lstat'd, then the C<ino> field of that structure
3831 is set to C<-1>.
3832
3833 This call is intended for programs that want to efficiently
3834 list a directory contents without making many round-trips.
3835 See also C<guestfs_lxattrlist> for a similarly efficient call
3836 for getting extended attributes.  Very long directory listings
3837 might cause the protocol message size to be exceeded, causing
3838 this call to fail.  The caller must split up such requests
3839 into smaller groups of names.");
3840
3841   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
3842    [], (* XXX *)
3843    "lgetxattr on multiple files",
3844    "\
3845 This call allows you to get the extended attributes
3846 of multiple files, where all files are in the directory C<path>.
3847 C<names> is the list of files from this directory.
3848
3849 On return you get a flat list of xattr structs which must be
3850 interpreted sequentially.  The first xattr struct always has a zero-length
3851 C<attrname>.  C<attrval> in this struct is zero-length
3852 to indicate there was an error doing C<lgetxattr> for this
3853 file, I<or> is a C string which is a decimal number
3854 (the number of following attributes for this file, which could
3855 be C<\"0\">).  Then after the first xattr struct are the
3856 zero or more attributes for the first named file.
3857 This repeats for the second and subsequent files.
3858
3859 This call is intended for programs that want to efficiently
3860 list a directory contents without making many round-trips.
3861 See also C<guestfs_lstatlist> for a similarly efficient call
3862 for getting standard stats.  Very long directory listings
3863 might cause the protocol message size to be exceeded, causing
3864 this call to fail.  The caller must split up such requests
3865 into smaller groups of names.");
3866
3867   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3868    [], (* XXX *)
3869    "readlink on multiple files",
3870    "\
3871 This call allows you to do a C<readlink> operation
3872 on multiple files, where all files are in the directory C<path>.
3873 C<names> is the list of files from this directory.
3874
3875 On return you get a list of strings, with a one-to-one
3876 correspondence to the C<names> list.  Each string is the
3877 value of the symbol link.
3878
3879 If the C<readlink(2)> operation fails on any name, then
3880 the corresponding result string is the empty string C<\"\">.
3881 However the whole operation is completed even if there
3882 were C<readlink(2)> errors, and so you can call this
3883 function with names where you don't know if they are
3884 symbolic links already (albeit slightly less efficient).
3885
3886 This call is intended for programs that want to efficiently
3887 list a directory contents without making many round-trips.
3888 Very long directory listings might cause the protocol
3889 message size to be exceeded, causing
3890 this call to fail.  The caller must split up such requests
3891 into smaller groups of names.");
3892
3893   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3894    [InitISOFS, Always, TestOutputBuffer (
3895       [["pread"; "/known-4"; "1"; "3"]], "\n");
3896     InitISOFS, Always, TestOutputBuffer (
3897       [["pread"; "/empty"; "0"; "100"]], "")],
3898    "read part of a file",
3899    "\
3900 This command lets you read part of a file.  It reads C<count>
3901 bytes of the file, starting at C<offset>, from file C<path>.
3902
3903 This may read fewer bytes than requested.  For further details
3904 see the L<pread(2)> system call.");
3905
3906   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3907    [InitEmpty, Always, TestRun (
3908       [["part_init"; "/dev/sda"; "gpt"]])],
3909    "create an empty partition table",
3910    "\
3911 This creates an empty partition table on C<device> of one of the
3912 partition types listed below.  Usually C<parttype> should be
3913 either C<msdos> or C<gpt> (for large disks).
3914
3915 Initially there are no partitions.  Following this, you should
3916 call C<guestfs_part_add> for each partition required.
3917
3918 Possible values for C<parttype> are:
3919
3920 =over 4
3921
3922 =item B<efi> | B<gpt>
3923
3924 Intel EFI / GPT partition table.
3925
3926 This is recommended for >= 2 TB partitions that will be accessed
3927 from Linux and Intel-based Mac OS X.  It also has limited backwards
3928 compatibility with the C<mbr> format.
3929
3930 =item B<mbr> | B<msdos>
3931
3932 The standard PC \"Master Boot Record\" (MBR) format used
3933 by MS-DOS and Windows.  This partition type will B<only> work
3934 for device sizes up to 2 TB.  For large disks we recommend
3935 using C<gpt>.
3936
3937 =back
3938
3939 Other partition table types that may work but are not
3940 supported include:
3941
3942 =over 4
3943
3944 =item B<aix>
3945
3946 AIX disk labels.
3947
3948 =item B<amiga> | B<rdb>
3949
3950 Amiga \"Rigid Disk Block\" format.
3951
3952 =item B<bsd>
3953
3954 BSD disk labels.
3955
3956 =item B<dasd>
3957
3958 DASD, used on IBM mainframes.
3959
3960 =item B<dvh>
3961
3962 MIPS/SGI volumes.
3963
3964 =item B<mac>
3965
3966 Old Mac partition format.  Modern Macs use C<gpt>.
3967
3968 =item B<pc98>
3969
3970 NEC PC-98 format, common in Japan apparently.
3971
3972 =item B<sun>
3973
3974 Sun disk labels.
3975
3976 =back");
3977
3978   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3979    [InitEmpty, Always, TestRun (
3980       [["part_init"; "/dev/sda"; "mbr"];
3981        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3982     InitEmpty, Always, TestRun (
3983       [["part_init"; "/dev/sda"; "gpt"];
3984        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3985        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3986     InitEmpty, Always, TestRun (
3987       [["part_init"; "/dev/sda"; "mbr"];
3988        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3989        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3990        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3991        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3992    "add a partition to the device",
3993    "\
3994 This command adds a partition to C<device>.  If there is no partition
3995 table on the device, call C<guestfs_part_init> first.
3996
3997 The C<prlogex> parameter is the type of partition.  Normally you
3998 should pass C<p> or C<primary> here, but MBR partition tables also
3999 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4000 types.
4001
4002 C<startsect> and C<endsect> are the start and end of the partition
4003 in I<sectors>.  C<endsect> may be negative, which means it counts
4004 backwards from the end of the disk (C<-1> is the last sector).
4005
4006 Creating a partition which covers the whole disk is not so easy.
4007 Use C<guestfs_part_disk> to do that.");
4008
4009   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4010    [InitEmpty, Always, TestRun (
4011       [["part_disk"; "/dev/sda"; "mbr"]]);
4012     InitEmpty, Always, TestRun (
4013       [["part_disk"; "/dev/sda"; "gpt"]])],
4014    "partition whole disk with a single primary partition",
4015    "\
4016 This command is simply a combination of C<guestfs_part_init>
4017 followed by C<guestfs_part_add> to create a single primary partition
4018 covering the whole disk.
4019
4020 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4021 but other possible values are described in C<guestfs_part_init>.");
4022
4023   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4024    [InitEmpty, Always, TestRun (
4025       [["part_disk"; "/dev/sda"; "mbr"];
4026        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4027    "make a partition bootable",
4028    "\
4029 This sets the bootable flag on partition numbered C<partnum> on
4030 device C<device>.  Note that partitions are numbered from 1.
4031
4032 The bootable flag is used by some PC BIOSes to determine which
4033 partition to boot from.  It is by no means universally recognized,
4034 and in any case if your operating system installed a boot
4035 sector on the device itself, then that takes precedence.");
4036
4037   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4038    [InitEmpty, Always, TestRun (
4039       [["part_disk"; "/dev/sda"; "gpt"];
4040        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4041    "set partition name",
4042    "\
4043 This sets the partition name on partition numbered C<partnum> on
4044 device C<device>.  Note that partitions are numbered from 1.
4045
4046 The partition name can only be set on certain types of partition
4047 table.  This works on C<gpt> but not on C<mbr> partitions.");
4048
4049   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4050    [], (* XXX Add a regression test for this. *)
4051    "list partitions on a device",
4052    "\
4053 This command parses the partition table on C<device> and
4054 returns the list of partitions found.
4055
4056 The fields in the returned structure are:
4057
4058 =over 4
4059
4060 =item B<part_num>
4061
4062 Partition number, counting from 1.
4063
4064 =item B<part_start>
4065
4066 Start of the partition I<in bytes>.  To get sectors you have to
4067 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4068
4069 =item B<part_end>
4070
4071 End of the partition in bytes.
4072
4073 =item B<part_size>
4074
4075 Size of the partition in bytes.
4076
4077 =back");
4078
4079   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4080    [InitEmpty, Always, TestOutput (
4081       [["part_disk"; "/dev/sda"; "gpt"];
4082        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4083    "get the partition table type",
4084    "\
4085 This command examines the partition table on C<device> and
4086 returns the partition table type (format) being used.
4087
4088 Common return values include: C<msdos> (a DOS/Windows style MBR
4089 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4090 values are possible, although unusual.  See C<guestfs_part_init>
4091 for a full list.");
4092
4093   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4094    [InitBasicFS, Always, TestOutputBuffer (
4095       [["fill"; "0x63"; "10"; "/test"];
4096        ["read_file"; "/test"]], "cccccccccc")],
4097    "fill a file with octets",
4098    "\
4099 This command creates a new file called C<path>.  The initial
4100 content of the file is C<len> octets of C<c>, where C<c>
4101 must be a number in the range C<[0..255]>.
4102
4103 To fill a file with zero bytes (sparsely), it is
4104 much more efficient to use C<guestfs_truncate_size>.");
4105
4106   ("available", (RErr, [StringList "groups"]), 216, [],
4107    [],
4108    "test availability of some parts of the API",
4109    "\
4110 This command is used to check the availability of some
4111 groups of libguestfs functions which not all builds of
4112 libguestfs will be able to provide.
4113
4114 The precise libguestfs function groups that may be checked by this
4115 command are listed in L<guestfs(3)/AVAILABILITY>.
4116
4117 The argument C<groups> is a list of API group names, eg:
4118 C<[\"inotify\", \"part\"]> would check for the availability of
4119 the C<guestfs_inotify_*> functions and C<guestfs_part_*>
4120 (partition editing) functions.
4121
4122 The command returns no error if I<all> requested groups are available.
4123
4124 It returns an error if one or more of the requested
4125 groups is unavailable.
4126
4127 If an unknown group name is included in the
4128 list of C<groups> then an error is always returned.
4129
4130 I<Notes:>
4131
4132 =over 4
4133
4134 =item *
4135
4136 You must call C<guestfs_launch> before calling this function.
4137 The reason is because we don't know what function groups are
4138 supported by the appliance/daemon until it is running and can
4139 be queried.
4140
4141 =item *
4142
4143 If a group of functions is available, this does not necessarily
4144 mean that they will work.  You still have to check for errors
4145 when calling individual API functions even if they are
4146 available.
4147
4148 =item *
4149
4150 It is usually the job of distro packagers to build
4151 complete functionality into the libguestfs appliance.
4152 Upstream libguestfs, if built from source with all
4153 requirements satisfied, will support everything.
4154
4155 =item *
4156
4157 This call was added in version C<1.0.80>.  In previous
4158 versions of libguestfs all you could do would be to speculatively
4159 execute a command to find out if the daemon implemented it.
4160 See also C<guestfs_version>.
4161
4162 =back");
4163
4164 ]
4165
4166 let all_functions = non_daemon_functions @ daemon_functions
4167
4168 (* In some places we want the functions to be displayed sorted
4169  * alphabetically, so this is useful:
4170  *)
4171 let all_functions_sorted =
4172   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4173                compare n1 n2) all_functions
4174
4175 (* Field types for structures. *)
4176 type field =
4177   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4178   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4179   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4180   | FUInt32
4181   | FInt32
4182   | FUInt64
4183   | FInt64
4184   | FBytes                      (* Any int measure that counts bytes. *)
4185   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4186   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4187
4188 (* Because we generate extra parsing code for LVM command line tools,
4189  * we have to pull out the LVM columns separately here.
4190  *)
4191 let lvm_pv_cols = [
4192   "pv_name", FString;
4193   "pv_uuid", FUUID;
4194   "pv_fmt", FString;
4195   "pv_size", FBytes;
4196   "dev_size", FBytes;
4197   "pv_free", FBytes;
4198   "pv_used", FBytes;
4199   "pv_attr", FString (* XXX *);
4200   "pv_pe_count", FInt64;
4201   "pv_pe_alloc_count", FInt64;
4202   "pv_tags", FString;
4203   "pe_start", FBytes;
4204   "pv_mda_count", FInt64;
4205   "pv_mda_free", FBytes;
4206   (* Not in Fedora 10:
4207      "pv_mda_size", FBytes;
4208   *)
4209 ]
4210 let lvm_vg_cols = [
4211   "vg_name", FString;
4212   "vg_uuid", FUUID;
4213   "vg_fmt", FString;
4214   "vg_attr", FString (* XXX *);
4215   "vg_size", FBytes;
4216   "vg_free", FBytes;
4217   "vg_sysid", FString;
4218   "vg_extent_size", FBytes;
4219   "vg_extent_count", FInt64;
4220   "vg_free_count", FInt64;
4221   "max_lv", FInt64;
4222   "max_pv", FInt64;
4223   "pv_count", FInt64;
4224   "lv_count", FInt64;
4225   "snap_count", FInt64;
4226   "vg_seqno", FInt64;
4227   "vg_tags", FString;
4228   "vg_mda_count", FInt64;
4229   "vg_mda_free", FBytes;
4230   (* Not in Fedora 10:
4231      "vg_mda_size", FBytes;
4232   *)
4233 ]
4234 let lvm_lv_cols = [
4235   "lv_name", FString;
4236   "lv_uuid", FUUID;
4237   "lv_attr", FString (* XXX *);
4238   "lv_major", FInt64;
4239   "lv_minor", FInt64;
4240   "lv_kernel_major", FInt64;
4241   "lv_kernel_minor", FInt64;
4242   "lv_size", FBytes;
4243   "seg_count", FInt64;
4244   "origin", FString;
4245   "snap_percent", FOptPercent;
4246   "copy_percent", FOptPercent;
4247   "move_pv", FString;
4248   "lv_tags", FString;
4249   "mirror_log", FString;
4250   "modules", FString;
4251 ]
4252
4253 (* Names and fields in all structures (in RStruct and RStructList)
4254  * that we support.
4255  *)
4256 let structs = [
4257   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4258    * not use this struct in any new code.
4259    *)
4260   "int_bool", [
4261     "i", FInt32;                (* for historical compatibility *)
4262     "b", FInt32;                (* for historical compatibility *)
4263   ];
4264
4265   (* LVM PVs, VGs, LVs. *)
4266   "lvm_pv", lvm_pv_cols;
4267   "lvm_vg", lvm_vg_cols;
4268   "lvm_lv", lvm_lv_cols;
4269
4270   (* Column names and types from stat structures.
4271    * NB. Can't use things like 'st_atime' because glibc header files
4272    * define some of these as macros.  Ugh.
4273    *)
4274   "stat", [
4275     "dev", FInt64;
4276     "ino", FInt64;
4277     "mode", FInt64;
4278     "nlink", FInt64;
4279     "uid", FInt64;
4280     "gid", FInt64;
4281     "rdev", FInt64;
4282     "size", FInt64;
4283     "blksize", FInt64;
4284     "blocks", FInt64;
4285     "atime", FInt64;
4286     "mtime", FInt64;
4287     "ctime", FInt64;
4288   ];
4289   "statvfs", [
4290     "bsize", FInt64;
4291     "frsize", FInt64;
4292     "blocks", FInt64;
4293     "bfree", FInt64;
4294     "bavail", FInt64;
4295     "files", FInt64;
4296     "ffree", FInt64;
4297     "favail", FInt64;
4298     "fsid", FInt64;
4299     "flag", FInt64;
4300     "namemax", FInt64;
4301   ];
4302
4303   (* Column names in dirent structure. *)
4304   "dirent", [
4305     "ino", FInt64;
4306     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4307     "ftyp", FChar;
4308     "name", FString;
4309   ];
4310
4311   (* Version numbers. *)
4312   "version", [
4313     "major", FInt64;
4314     "minor", FInt64;
4315     "release", FInt64;
4316     "extra", FString;
4317   ];
4318
4319   (* Extended attribute. *)
4320   "xattr", [
4321     "attrname", FString;
4322     "attrval", FBuffer;
4323   ];
4324
4325   (* Inotify events. *)
4326   "inotify_event", [
4327     "in_wd", FInt64;
4328     "in_mask", FUInt32;
4329     "in_cookie", FUInt32;
4330     "in_name", FString;
4331   ];
4332
4333   (* Partition table entry. *)
4334   "partition", [
4335     "part_num", FInt32;
4336     "part_start", FBytes;
4337     "part_end", FBytes;
4338     "part_size", FBytes;
4339   ];
4340 ] (* end of structs *)
4341
4342 (* Ugh, Java has to be different ..
4343  * These names are also used by the Haskell bindings.
4344  *)
4345 let java_structs = [
4346   "int_bool", "IntBool";
4347   "lvm_pv", "PV";
4348   "lvm_vg", "VG";
4349   "lvm_lv", "LV";
4350   "stat", "Stat";
4351   "statvfs", "StatVFS";
4352   "dirent", "Dirent";
4353   "version", "Version";
4354   "xattr", "XAttr";
4355   "inotify_event", "INotifyEvent";
4356   "partition", "Partition";
4357 ]
4358
4359 (* What structs are actually returned. *)
4360 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4361
4362 (* Returns a list of RStruct/RStructList structs that are returned
4363  * by any function.  Each element of returned list is a pair:
4364  *
4365  * (structname, RStructOnly)
4366  *    == there exists function which returns RStruct (_, structname)
4367  * (structname, RStructListOnly)
4368  *    == there exists function which returns RStructList (_, structname)
4369  * (structname, RStructAndList)
4370  *    == there are functions returning both RStruct (_, structname)
4371  *                                      and RStructList (_, structname)
4372  *)
4373 let rstructs_used_by functions =
4374   (* ||| is a "logical OR" for rstructs_used_t *)
4375   let (|||) a b =
4376     match a, b with
4377     | RStructAndList, _
4378     | _, RStructAndList -> RStructAndList
4379     | RStructOnly, RStructListOnly
4380     | RStructListOnly, RStructOnly -> RStructAndList
4381     | RStructOnly, RStructOnly -> RStructOnly
4382     | RStructListOnly, RStructListOnly -> RStructListOnly
4383   in
4384
4385   let h = Hashtbl.create 13 in
4386
4387   (* if elem->oldv exists, update entry using ||| operator,
4388    * else just add elem->newv to the hash
4389    *)
4390   let update elem newv =
4391     try  let oldv = Hashtbl.find h elem in
4392          Hashtbl.replace h elem (newv ||| oldv)
4393     with Not_found -> Hashtbl.add h elem newv
4394   in
4395
4396   List.iter (
4397     fun (_, style, _, _, _, _, _) ->
4398       match fst style with
4399       | RStruct (_, structname) -> update structname RStructOnly
4400       | RStructList (_, structname) -> update structname RStructListOnly
4401       | _ -> ()
4402   ) functions;
4403
4404   (* return key->values as a list of (key,value) *)
4405   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4406
4407 (* Used for testing language bindings. *)
4408 type callt =
4409   | CallString of string
4410   | CallOptString of string option
4411   | CallStringList of string list
4412   | CallInt of int
4413   | CallInt64 of int64
4414   | CallBool of bool
4415
4416 (* Used to memoize the result of pod2text. *)
4417 let pod2text_memo_filename = "src/.pod2text.data"
4418 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4419   try
4420     let chan = open_in pod2text_memo_filename in
4421     let v = input_value chan in
4422     close_in chan;
4423     v
4424   with
4425     _ -> Hashtbl.create 13
4426 let pod2text_memo_updated () =
4427   let chan = open_out pod2text_memo_filename in
4428   output_value chan pod2text_memo;
4429   close_out chan
4430
4431 (* Useful functions.
4432  * Note we don't want to use any external OCaml libraries which
4433  * makes this a bit harder than it should be.
4434  *)
4435 let failwithf fs = ksprintf failwith fs
4436
4437 let replace_char s c1 c2 =
4438   let s2 = String.copy s in
4439   let r = ref false in
4440   for i = 0 to String.length s2 - 1 do
4441     if String.unsafe_get s2 i = c1 then (
4442       String.unsafe_set s2 i c2;
4443       r := true
4444     )
4445   done;
4446   if not !r then s else s2
4447
4448 let isspace c =
4449   c = ' '
4450   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4451
4452 let triml ?(test = isspace) str =
4453   let i = ref 0 in
4454   let n = ref (String.length str) in
4455   while !n > 0 && test str.[!i]; do
4456     decr n;
4457     incr i
4458   done;
4459   if !i = 0 then str
4460   else String.sub str !i !n
4461
4462 let trimr ?(test = isspace) str =
4463   let n = ref (String.length str) in
4464   while !n > 0 && test str.[!n-1]; do
4465     decr n
4466   done;
4467   if !n = String.length str then str
4468   else String.sub str 0 !n
4469
4470 let trim ?(test = isspace) str =
4471   trimr ~test (triml ~test str)
4472
4473 let rec find s sub =
4474   let len = String.length s in
4475   let sublen = String.length sub in
4476   let rec loop i =
4477     if i <= len-sublen then (
4478       let rec loop2 j =
4479         if j < sublen then (
4480           if s.[i+j] = sub.[j] then loop2 (j+1)
4481           else -1
4482         ) else
4483           i (* found *)
4484       in
4485       let r = loop2 0 in
4486       if r = -1 then loop (i+1) else r
4487     ) else
4488       -1 (* not found *)
4489   in
4490   loop 0
4491
4492 let rec replace_str s s1 s2 =
4493   let len = String.length s in
4494   let sublen = String.length s1 in
4495   let i = find s s1 in
4496   if i = -1 then s
4497   else (
4498     let s' = String.sub s 0 i in
4499     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4500     s' ^ s2 ^ replace_str s'' s1 s2
4501   )
4502
4503 let rec string_split sep str =
4504   let len = String.length str in
4505   let seplen = String.length sep in
4506   let i = find str sep in
4507   if i = -1 then [str]
4508   else (
4509     let s' = String.sub str 0 i in
4510     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4511     s' :: string_split sep s''
4512   )
4513
4514 let files_equal n1 n2 =
4515   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4516   match Sys.command cmd with
4517   | 0 -> true
4518   | 1 -> false
4519   | i -> failwithf "%s: failed with error code %d" cmd i
4520
4521 let rec filter_map f = function
4522   | [] -> []
4523   | x :: xs ->
4524       match f x with
4525       | Some y -> y :: filter_map f xs
4526       | None -> filter_map f xs
4527
4528 let rec find_map f = function
4529   | [] -> raise Not_found
4530   | x :: xs ->
4531       match f x with
4532       | Some y -> y
4533       | None -> find_map f xs
4534
4535 let iteri f xs =
4536   let rec loop i = function
4537     | [] -> ()
4538     | x :: xs -> f i x; loop (i+1) xs
4539   in
4540   loop 0 xs
4541
4542 let mapi f xs =
4543   let rec loop i = function
4544     | [] -> []
4545     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4546   in
4547   loop 0 xs
4548
4549 let name_of_argt = function
4550   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4551   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4552   | FileIn n | FileOut n -> n
4553
4554 let java_name_of_struct typ =
4555   try List.assoc typ java_structs
4556   with Not_found ->
4557     failwithf
4558       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4559
4560 let cols_of_struct typ =
4561   try List.assoc typ structs
4562   with Not_found ->
4563     failwithf "cols_of_struct: unknown struct %s" typ
4564
4565 let seq_of_test = function
4566   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4567   | TestOutputListOfDevices (s, _)
4568   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4569   | TestOutputTrue s | TestOutputFalse s
4570   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4571   | TestOutputStruct (s, _)
4572   | TestLastFail s -> s
4573
4574 (* Handling for function flags. *)
4575 let protocol_limit_warning =
4576   "Because of the message protocol, there is a transfer limit
4577 of somewhere between 2MB and 4MB.  To transfer large files you should use
4578 FTP."
4579
4580 let danger_will_robinson =
4581   "B<This command is dangerous.  Without careful use you
4582 can easily destroy all your data>."
4583
4584 let deprecation_notice flags =
4585   try
4586     let alt =
4587       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4588     let txt =
4589       sprintf "This function is deprecated.
4590 In new code, use the C<%s> call instead.
4591
4592 Deprecated functions will not be removed from the API, but the
4593 fact that they are deprecated indicates that there are problems
4594 with correct use of these functions." alt in
4595     Some txt
4596   with
4597     Not_found -> None
4598
4599 (* Check function names etc. for consistency. *)
4600 let check_functions () =
4601   let contains_uppercase str =
4602     let len = String.length str in
4603     let rec loop i =
4604       if i >= len then false
4605       else (
4606         let c = str.[i] in
4607         if c >= 'A' && c <= 'Z' then true
4608         else loop (i+1)
4609       )
4610     in
4611     loop 0
4612   in
4613
4614   (* Check function names. *)
4615   List.iter (
4616     fun (name, _, _, _, _, _, _) ->
4617       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4618         failwithf "function name %s does not need 'guestfs' prefix" name;
4619       if name = "" then
4620         failwithf "function name is empty";
4621       if name.[0] < 'a' || name.[0] > 'z' then
4622         failwithf "function name %s must start with lowercase a-z" name;
4623       if String.contains name '-' then
4624         failwithf "function name %s should not contain '-', use '_' instead."
4625           name
4626   ) all_functions;
4627
4628   (* Check function parameter/return names. *)
4629   List.iter (
4630     fun (name, style, _, _, _, _, _) ->
4631       let check_arg_ret_name n =
4632         if contains_uppercase n then
4633           failwithf "%s param/ret %s should not contain uppercase chars"
4634             name n;
4635         if String.contains n '-' || String.contains n '_' then
4636           failwithf "%s param/ret %s should not contain '-' or '_'"
4637             name n;
4638         if n = "value" then
4639           failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
4640         if n = "int" || n = "char" || n = "short" || n = "long" then
4641           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4642         if n = "i" || n = "n" then
4643           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4644         if n = "argv" || n = "args" then
4645           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4646
4647         (* List Haskell, OCaml and C keywords here.
4648          * http://www.haskell.org/haskellwiki/Keywords
4649          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4650          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4651          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4652          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4653          * Omitting _-containing words, since they're handled above.
4654          * Omitting the OCaml reserved word, "val", is ok,
4655          * and saves us from renaming several parameters.
4656          *)
4657         let reserved = [
4658           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4659           "char"; "class"; "const"; "constraint"; "continue"; "data";
4660           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4661           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4662           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4663           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4664           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4665           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4666           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4667           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4668           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4669           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4670           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4671           "volatile"; "when"; "where"; "while";
4672           ] in
4673         if List.mem n reserved then
4674           failwithf "%s has param/ret using reserved word %s" name n;
4675       in
4676
4677       (match fst style with
4678        | RErr -> ()
4679        | RInt n | RInt64 n | RBool n
4680        | RConstString n | RConstOptString n | RString n
4681        | RStringList n | RStruct (n, _) | RStructList (n, _)
4682        | RHashtable n | RBufferOut n ->
4683            check_arg_ret_name n
4684       );
4685       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4686   ) all_functions;
4687
4688   (* Check short descriptions. *)
4689   List.iter (
4690     fun (name, _, _, _, _, shortdesc, _) ->
4691       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4692         failwithf "short description of %s should begin with lowercase." name;
4693       let c = shortdesc.[String.length shortdesc-1] in
4694       if c = '\n' || c = '.' then
4695         failwithf "short description of %s should not end with . or \\n." name
4696   ) all_functions;
4697
4698   (* Check long dscriptions. *)
4699   List.iter (
4700     fun (name, _, _, _, _, _, longdesc) ->
4701       if longdesc.[String.length longdesc-1] = '\n' then
4702         failwithf "long description of %s should not end with \\n." name
4703   ) all_functions;
4704
4705   (* Check proc_nrs. *)
4706   List.iter (
4707     fun (name, _, proc_nr, _, _, _, _) ->
4708       if proc_nr <= 0 then
4709         failwithf "daemon function %s should have proc_nr > 0" name
4710   ) daemon_functions;
4711
4712   List.iter (
4713     fun (name, _, proc_nr, _, _, _, _) ->
4714       if proc_nr <> -1 then
4715         failwithf "non-daemon function %s should have proc_nr -1" name
4716   ) non_daemon_functions;
4717
4718   let proc_nrs =
4719     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4720       daemon_functions in
4721   let proc_nrs =
4722     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4723   let rec loop = function
4724     | [] -> ()
4725     | [_] -> ()
4726     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4727         loop rest
4728     | (name1,nr1) :: (name2,nr2) :: _ ->
4729         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4730           name1 name2 nr1 nr2
4731   in
4732   loop proc_nrs;
4733
4734   (* Check tests. *)
4735   List.iter (
4736     function
4737       (* Ignore functions that have no tests.  We generate a
4738        * warning when the user does 'make check' instead.
4739        *)
4740     | name, _, _, _, [], _, _ -> ()
4741     | name, _, _, _, tests, _, _ ->
4742         let funcs =
4743           List.map (
4744             fun (_, _, test) ->
4745               match seq_of_test test with
4746               | [] ->
4747                   failwithf "%s has a test containing an empty sequence" name
4748               | cmds -> List.map List.hd cmds
4749           ) tests in
4750         let funcs = List.flatten funcs in
4751
4752         let tested = List.mem name funcs in
4753
4754         if not tested then
4755           failwithf "function %s has tests but does not test itself" name
4756   ) all_functions
4757
4758 (* 'pr' prints to the current output file. *)
4759 let chan = ref Pervasives.stdout
4760 let pr fs = ksprintf (output_string !chan) fs
4761
4762 (* Generate a header block in a number of standard styles. *)
4763 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4764 type license = GPLv2 | LGPLv2
4765
4766 let generate_header comment license =
4767   let c = match comment with
4768     | CStyle ->     pr "/* "; " *"
4769     | HashStyle ->  pr "# ";  "#"
4770     | OCamlStyle -> pr "(* "; " *"
4771     | HaskellStyle -> pr "{- "; "  " in
4772   pr "libguestfs generated file\n";
4773   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4774   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4775   pr "%s\n" c;
4776   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4777   pr "%s\n" c;
4778   (match license with
4779    | GPLv2 ->
4780        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4781        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4782        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4783        pr "%s (at your option) any later version.\n" c;
4784        pr "%s\n" c;
4785        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4786        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4787        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4788        pr "%s GNU General Public License for more details.\n" c;
4789        pr "%s\n" c;
4790        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4791        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4792        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4793
4794    | LGPLv2 ->
4795        pr "%s This library is free software; you can redistribute it and/or\n" c;
4796        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4797        pr "%s License as published by the Free Software Foundation; either\n" c;
4798        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4799        pr "%s\n" c;
4800        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4801        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4802        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4803        pr "%s Lesser General Public License for more details.\n" c;
4804        pr "%s\n" c;
4805        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4806        pr "%s License along with this library; if not, write to the Free Software\n" c;
4807        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4808   );
4809   (match comment with
4810    | CStyle -> pr " */\n"
4811    | HashStyle -> ()
4812    | OCamlStyle -> pr " *)\n"
4813    | HaskellStyle -> pr "-}\n"
4814   );
4815   pr "\n"
4816
4817 (* Start of main code generation functions below this line. *)
4818
4819 (* Generate the pod documentation for the C API. *)
4820 let rec generate_actions_pod () =
4821   List.iter (
4822     fun (shortname, style, _, flags, _, _, longdesc) ->
4823       if not (List.mem NotInDocs flags) then (
4824         let name = "guestfs_" ^ shortname in
4825         pr "=head2 %s\n\n" name;
4826         pr " ";
4827         generate_prototype ~extern:false ~handle:"handle" name style;
4828         pr "\n\n";
4829         pr "%s\n\n" longdesc;
4830         (match fst style with
4831          | RErr ->
4832              pr "This function returns 0 on success or -1 on error.\n\n"
4833          | RInt _ ->
4834              pr "On error this function returns -1.\n\n"
4835          | RInt64 _ ->
4836              pr "On error this function returns -1.\n\n"
4837          | RBool _ ->
4838              pr "This function returns a C truth value on success or -1 on error.\n\n"
4839          | RConstString _ ->
4840              pr "This function returns a string, or NULL on error.
4841 The string is owned by the guest handle and must I<not> be freed.\n\n"
4842          | RConstOptString _ ->
4843              pr "This function returns a string which may be NULL.
4844 There is way to return an error from this function.
4845 The string is owned by the guest handle and must I<not> be freed.\n\n"
4846          | RString _ ->
4847              pr "This function returns a string, or NULL on error.
4848 I<The caller must free the returned string after use>.\n\n"
4849          | RStringList _ ->
4850              pr "This function returns a NULL-terminated array of strings
4851 (like L<environ(3)>), or NULL if there was an error.
4852 I<The caller must free the strings and the array after use>.\n\n"
4853          | RStruct (_, typ) ->
4854              pr "This function returns a C<struct guestfs_%s *>,
4855 or NULL if there was an error.
4856 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4857          | RStructList (_, typ) ->
4858              pr "This function returns a C<struct guestfs_%s_list *>
4859 (see E<lt>guestfs-structs.hE<gt>),
4860 or NULL if there was an error.
4861 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4862          | RHashtable _ ->
4863              pr "This function returns a NULL-terminated array of
4864 strings, or NULL if there was an error.
4865 The array of strings will always have length C<2n+1>, where
4866 C<n> keys and values alternate, followed by the trailing NULL entry.
4867 I<The caller must free the strings and the array after use>.\n\n"
4868          | RBufferOut _ ->
4869              pr "This function returns a buffer, or NULL on error.
4870 The size of the returned buffer is written to C<*size_r>.
4871 I<The caller must free the returned buffer after use>.\n\n"
4872         );
4873         if List.mem ProtocolLimitWarning flags then
4874           pr "%s\n\n" protocol_limit_warning;
4875         if List.mem DangerWillRobinson flags then
4876           pr "%s\n\n" danger_will_robinson;
4877         match deprecation_notice flags with
4878         | None -> ()
4879         | Some txt -> pr "%s\n\n" txt
4880       )
4881   ) all_functions_sorted
4882
4883 and generate_structs_pod () =
4884   (* Structs documentation. *)
4885   List.iter (
4886     fun (typ, cols) ->
4887       pr "=head2 guestfs_%s\n" typ;
4888       pr "\n";
4889       pr " struct guestfs_%s {\n" typ;
4890       List.iter (
4891         function
4892         | name, FChar -> pr "   char %s;\n" name
4893         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4894         | name, FInt32 -> pr "   int32_t %s;\n" name
4895         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4896         | name, FInt64 -> pr "   int64_t %s;\n" name
4897         | name, FString -> pr "   char *%s;\n" name
4898         | name, FBuffer ->
4899             pr "   /* The next two fields describe a byte array. */\n";
4900             pr "   uint32_t %s_len;\n" name;
4901             pr "   char *%s;\n" name
4902         | name, FUUID ->
4903             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4904             pr "   char %s[32];\n" name
4905         | name, FOptPercent ->
4906             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4907             pr "   float %s;\n" name
4908       ) cols;
4909       pr " };\n";
4910       pr " \n";
4911       pr " struct guestfs_%s_list {\n" typ;
4912       pr "   uint32_t len; /* Number of elements in list. */\n";
4913       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4914       pr " };\n";
4915       pr " \n";
4916       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4917       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4918         typ typ;
4919       pr "\n"
4920   ) structs
4921
4922 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4923  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4924  *
4925  * We have to use an underscore instead of a dash because otherwise
4926  * rpcgen generates incorrect code.
4927  *
4928  * This header is NOT exported to clients, but see also generate_structs_h.
4929  *)
4930 and generate_xdr () =
4931   generate_header CStyle LGPLv2;
4932
4933   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4934   pr "typedef string str<>;\n";
4935   pr "\n";
4936
4937   (* Internal structures. *)
4938   List.iter (
4939     function
4940     | typ, cols ->
4941         pr "struct guestfs_int_%s {\n" typ;
4942         List.iter (function
4943                    | name, FChar -> pr "  char %s;\n" name
4944                    | name, FString -> pr "  string %s<>;\n" name
4945                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4946                    | name, FUUID -> pr "  opaque %s[32];\n" name
4947                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4948                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4949                    | name, FOptPercent -> pr "  float %s;\n" name
4950                   ) cols;
4951         pr "};\n";
4952         pr "\n";
4953         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4954         pr "\n";
4955   ) structs;
4956
4957   List.iter (
4958     fun (shortname, style, _, _, _, _, _) ->
4959       let name = "guestfs_" ^ shortname in
4960
4961       (match snd style with
4962        | [] -> ()
4963        | args ->
4964            pr "struct %s_args {\n" name;
4965            List.iter (
4966              function
4967              | Pathname n | Device n | Dev_or_Path n | String n ->
4968                  pr "  string %s<>;\n" n
4969              | OptString n -> pr "  str *%s;\n" n
4970              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4971              | Bool n -> pr "  bool %s;\n" n
4972              | Int n -> pr "  int %s;\n" n
4973              | Int64 n -> pr "  hyper %s;\n" n
4974              | FileIn _ | FileOut _ -> ()
4975            ) args;
4976            pr "};\n\n"
4977       );
4978       (match fst style with
4979        | RErr -> ()
4980        | RInt n ->
4981            pr "struct %s_ret {\n" name;
4982            pr "  int %s;\n" n;
4983            pr "};\n\n"
4984        | RInt64 n ->
4985            pr "struct %s_ret {\n" name;
4986            pr "  hyper %s;\n" n;
4987            pr "};\n\n"
4988        | RBool n ->
4989            pr "struct %s_ret {\n" name;
4990            pr "  bool %s;\n" n;
4991            pr "};\n\n"
4992        | RConstString _ | RConstOptString _ ->
4993            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4994        | RString n ->
4995            pr "struct %s_ret {\n" name;
4996            pr "  string %s<>;\n" n;
4997            pr "};\n\n"
4998        | RStringList n ->
4999            pr "struct %s_ret {\n" name;
5000            pr "  str %s<>;\n" n;
5001            pr "};\n\n"
5002        | RStruct (n, typ) ->
5003            pr "struct %s_ret {\n" name;
5004            pr "  guestfs_int_%s %s;\n" typ n;
5005            pr "};\n\n"
5006        | RStructList (n, typ) ->
5007            pr "struct %s_ret {\n" name;
5008            pr "  guestfs_int_%s_list %s;\n" typ n;
5009            pr "};\n\n"
5010        | RHashtable n ->
5011            pr "struct %s_ret {\n" name;
5012            pr "  str %s<>;\n" n;
5013            pr "};\n\n"
5014        | RBufferOut n ->
5015            pr "struct %s_ret {\n" name;
5016            pr "  opaque %s<>;\n" n;
5017            pr "};\n\n"
5018       );
5019   ) daemon_functions;
5020
5021   (* Table of procedure numbers. *)
5022   pr "enum guestfs_procedure {\n";
5023   List.iter (
5024     fun (shortname, _, proc_nr, _, _, _, _) ->
5025       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5026   ) daemon_functions;
5027   pr "  GUESTFS_PROC_NR_PROCS\n";
5028   pr "};\n";
5029   pr "\n";
5030
5031   (* Having to choose a maximum message size is annoying for several
5032    * reasons (it limits what we can do in the API), but it (a) makes
5033    * the protocol a lot simpler, and (b) provides a bound on the size
5034    * of the daemon which operates in limited memory space.  For large
5035    * file transfers you should use FTP.
5036    *)
5037   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5038   pr "\n";
5039
5040   (* Message header, etc. *)
5041   pr "\
5042 /* The communication protocol is now documented in the guestfs(3)
5043  * manpage.
5044  */
5045
5046 const GUESTFS_PROGRAM = 0x2000F5F5;
5047 const GUESTFS_PROTOCOL_VERSION = 1;
5048
5049 /* These constants must be larger than any possible message length. */
5050 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5051 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5052
5053 enum guestfs_message_direction {
5054   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5055   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5056 };
5057
5058 enum guestfs_message_status {
5059   GUESTFS_STATUS_OK = 0,
5060   GUESTFS_STATUS_ERROR = 1
5061 };
5062
5063 const GUESTFS_ERROR_LEN = 256;
5064
5065 struct guestfs_message_error {
5066   string error_message<GUESTFS_ERROR_LEN>;
5067 };
5068
5069 struct guestfs_message_header {
5070   unsigned prog;                     /* GUESTFS_PROGRAM */
5071   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5072   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5073   guestfs_message_direction direction;
5074   unsigned serial;                   /* message serial number */
5075   guestfs_message_status status;
5076 };
5077
5078 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5079
5080 struct guestfs_chunk {
5081   int cancel;                        /* if non-zero, transfer is cancelled */
5082   /* data size is 0 bytes if the transfer has finished successfully */
5083   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5084 };
5085 "
5086
5087 (* Generate the guestfs-structs.h file. *)
5088 and generate_structs_h () =
5089   generate_header CStyle LGPLv2;
5090
5091   (* This is a public exported header file containing various
5092    * structures.  The structures are carefully written to have
5093    * exactly the same in-memory format as the XDR structures that
5094    * we use on the wire to the daemon.  The reason for creating
5095    * copies of these structures here is just so we don't have to
5096    * export the whole of guestfs_protocol.h (which includes much
5097    * unrelated and XDR-dependent stuff that we don't want to be
5098    * public, or required by clients).
5099    *
5100    * To reiterate, we will pass these structures to and from the
5101    * client with a simple assignment or memcpy, so the format
5102    * must be identical to what rpcgen / the RFC defines.
5103    *)
5104
5105   (* Public structures. *)
5106   List.iter (
5107     fun (typ, cols) ->
5108       pr "struct guestfs_%s {\n" typ;
5109       List.iter (
5110         function
5111         | name, FChar -> pr "  char %s;\n" name
5112         | name, FString -> pr "  char *%s;\n" name
5113         | name, FBuffer ->
5114             pr "  uint32_t %s_len;\n" name;
5115             pr "  char *%s;\n" name
5116         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5117         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5118         | name, FInt32 -> pr "  int32_t %s;\n" name
5119         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5120         | name, FInt64 -> pr "  int64_t %s;\n" name
5121         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5122       ) cols;
5123       pr "};\n";
5124       pr "\n";
5125       pr "struct guestfs_%s_list {\n" typ;
5126       pr "  uint32_t len;\n";
5127       pr "  struct guestfs_%s *val;\n" typ;
5128       pr "};\n";
5129       pr "\n";
5130       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5131       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5132       pr "\n"
5133   ) structs
5134
5135 (* Generate the guestfs-actions.h file. *)
5136 and generate_actions_h () =
5137   generate_header CStyle LGPLv2;
5138   List.iter (
5139     fun (shortname, style, _, _, _, _, _) ->
5140       let name = "guestfs_" ^ shortname in
5141       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5142         name style
5143   ) all_functions
5144
5145 (* Generate the guestfs-internal-actions.h file. *)
5146 and generate_internal_actions_h () =
5147   generate_header CStyle LGPLv2;
5148   List.iter (
5149     fun (shortname, style, _, _, _, _, _) ->
5150       let name = "guestfs__" ^ shortname in
5151       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5152         name style
5153   ) non_daemon_functions
5154
5155 (* Generate the client-side dispatch stubs. *)
5156 and generate_client_actions () =
5157   generate_header CStyle LGPLv2;
5158
5159   pr "\
5160 #include <stdio.h>
5161 #include <stdlib.h>
5162 #include <stdint.h>
5163 #include <inttypes.h>
5164
5165 #include \"guestfs.h\"
5166 #include \"guestfs-internal.h\"
5167 #include \"guestfs-internal-actions.h\"
5168 #include \"guestfs_protocol.h\"
5169
5170 #define error guestfs_error
5171 //#define perrorf guestfs_perrorf
5172 #define safe_malloc guestfs_safe_malloc
5173 #define safe_realloc guestfs_safe_realloc
5174 //#define safe_strdup guestfs_safe_strdup
5175 #define safe_memdup guestfs_safe_memdup
5176
5177 /* Check the return message from a call for validity. */
5178 static int
5179 check_reply_header (guestfs_h *g,
5180                     const struct guestfs_message_header *hdr,
5181                     unsigned int proc_nr, unsigned int serial)
5182 {
5183   if (hdr->prog != GUESTFS_PROGRAM) {
5184     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5185     return -1;
5186   }
5187   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5188     error (g, \"wrong protocol version (%%d/%%d)\",
5189            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5190     return -1;
5191   }
5192   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5193     error (g, \"unexpected message direction (%%d/%%d)\",
5194            hdr->direction, GUESTFS_DIRECTION_REPLY);
5195     return -1;
5196   }
5197   if (hdr->proc != proc_nr) {
5198     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5199     return -1;
5200   }
5201   if (hdr->serial != serial) {
5202     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5203     return -1;
5204   }
5205
5206   return 0;
5207 }
5208
5209 /* Check we are in the right state to run a high-level action. */
5210 static int
5211 check_state (guestfs_h *g, const char *caller)
5212 {
5213   if (!guestfs__is_ready (g)) {
5214     if (guestfs__is_config (g) || guestfs__is_launching (g))
5215       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5216         caller);
5217     else
5218       error (g, \"%%s called from the wrong state, %%d != READY\",
5219         caller, guestfs__get_state (g));
5220     return -1;
5221   }
5222   return 0;
5223 }
5224
5225 ";
5226
5227   (* Generate code to generate guestfish call traces. *)
5228   let trace_call shortname style =
5229     pr "  if (guestfs__get_trace (g)) {\n";
5230
5231     let needs_i =
5232       List.exists (function
5233                    | StringList _ | DeviceList _ -> true
5234                    | _ -> false) (snd style) in
5235     if needs_i then (
5236       pr "    int i;\n";
5237       pr "\n"
5238     );
5239
5240     pr "    printf (\"%s\");\n" shortname;
5241     List.iter (
5242       function
5243       | String n                        (* strings *)
5244       | Device n
5245       | Pathname n
5246       | Dev_or_Path n
5247       | FileIn n
5248       | FileOut n ->
5249           (* guestfish doesn't support string escaping, so neither do we *)
5250           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5251       | OptString n ->                  (* string option *)
5252           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5253           pr "    else printf (\" null\");\n"
5254       | StringList n
5255       | DeviceList n ->                 (* string list *)
5256           pr "    putchar (' ');\n";
5257           pr "    putchar ('\"');\n";
5258           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5259           pr "      if (i > 0) putchar (' ');\n";
5260           pr "      fputs (%s[i], stdout);\n" n;
5261           pr "    }\n";
5262           pr "    putchar ('\"');\n";
5263       | Bool n ->                       (* boolean *)
5264           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5265       | Int n ->                        (* int *)
5266           pr "    printf (\" %%d\", %s);\n" n
5267       | Int64 n ->
5268           pr "    printf (\" %%\" PRIi64, %s);\n" n
5269     ) (snd style);
5270     pr "    putchar ('\\n');\n";
5271     pr "  }\n";
5272     pr "\n";
5273   in
5274
5275   (* For non-daemon functions, generate a wrapper around each function. *)
5276   List.iter (
5277     fun (shortname, style, _, _, _, _, _) ->
5278       let name = "guestfs_" ^ shortname in
5279
5280       generate_prototype ~extern:false ~semicolon:false ~newline:true
5281         ~handle:"g" name style;
5282       pr "{\n";
5283       trace_call shortname style;
5284       pr "  return guestfs__%s " shortname;
5285       generate_c_call_args ~handle:"g" style;
5286       pr ";\n";
5287       pr "}\n";
5288       pr "\n"
5289   ) non_daemon_functions;
5290
5291   (* Client-side stubs for each function. *)
5292   List.iter (
5293     fun (shortname, style, _, _, _, _, _) ->
5294       let name = "guestfs_" ^ shortname in
5295
5296       (* Generate the action stub. *)
5297       generate_prototype ~extern:false ~semicolon:false ~newline:true
5298         ~handle:"g" name style;
5299
5300       let error_code =
5301         match fst style with
5302         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5303         | RConstString _ | RConstOptString _ ->
5304             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5305         | RString _ | RStringList _
5306         | RStruct _ | RStructList _
5307         | RHashtable _ | RBufferOut _ ->
5308             "NULL" in
5309
5310       pr "{\n";
5311
5312       (match snd style with
5313        | [] -> ()
5314        | _ -> pr "  struct %s_args args;\n" name
5315       );
5316
5317       pr "  guestfs_message_header hdr;\n";
5318       pr "  guestfs_message_error err;\n";
5319       let has_ret =
5320         match fst style with
5321         | RErr -> false
5322         | RConstString _ | RConstOptString _ ->
5323             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5324         | RInt _ | RInt64 _
5325         | RBool _ | RString _ | RStringList _
5326         | RStruct _ | RStructList _
5327         | RHashtable _ | RBufferOut _ ->
5328             pr "  struct %s_ret ret;\n" name;
5329             true in
5330
5331       pr "  int serial;\n";
5332       pr "  int r;\n";
5333       pr "\n";
5334       trace_call shortname style;
5335       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5336       pr "  guestfs___set_busy (g);\n";
5337       pr "\n";
5338
5339       (* Send the main header and arguments. *)
5340       (match snd style with
5341        | [] ->
5342            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5343              (String.uppercase shortname)
5344        | args ->
5345            List.iter (
5346              function
5347              | Pathname n | Device n | Dev_or_Path n | String n ->
5348                  pr "  args.%s = (char *) %s;\n" n n
5349              | OptString n ->
5350                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5351              | StringList n | DeviceList n ->
5352                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5353                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5354              | Bool n ->
5355                  pr "  args.%s = %s;\n" n n
5356              | Int n ->
5357                  pr "  args.%s = %s;\n" n n
5358              | Int64 n ->
5359                  pr "  args.%s = %s;\n" n n
5360              | FileIn _ | FileOut _ -> ()
5361            ) args;
5362            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5363              (String.uppercase shortname);
5364            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5365              name;
5366       );
5367       pr "  if (serial == -1) {\n";
5368       pr "    guestfs___end_busy (g);\n";
5369       pr "    return %s;\n" error_code;
5370       pr "  }\n";
5371       pr "\n";
5372
5373       (* Send any additional files (FileIn) requested. *)
5374       let need_read_reply_label = ref false in
5375       List.iter (
5376         function
5377         | FileIn n ->
5378             pr "  r = guestfs___send_file (g, %s);\n" n;
5379             pr "  if (r == -1) {\n";
5380             pr "    guestfs___end_busy (g);\n";
5381             pr "    return %s;\n" error_code;
5382             pr "  }\n";
5383             pr "  if (r == -2) /* daemon cancelled */\n";
5384             pr "    goto read_reply;\n";
5385             need_read_reply_label := true;
5386             pr "\n";
5387         | _ -> ()
5388       ) (snd style);
5389
5390       (* Wait for the reply from the remote end. *)
5391       if !need_read_reply_label then pr " read_reply:\n";
5392       pr "  memset (&hdr, 0, sizeof hdr);\n";
5393       pr "  memset (&err, 0, sizeof err);\n";
5394       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5395       pr "\n";
5396       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5397       if not has_ret then
5398         pr "NULL, NULL"
5399       else
5400         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5401       pr ");\n";
5402
5403       pr "  if (r == -1) {\n";
5404       pr "    guestfs___end_busy (g);\n";
5405       pr "    return %s;\n" error_code;
5406       pr "  }\n";
5407       pr "\n";
5408
5409       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5410         (String.uppercase shortname);
5411       pr "    guestfs___end_busy (g);\n";
5412       pr "    return %s;\n" error_code;
5413       pr "  }\n";
5414       pr "\n";
5415
5416       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5417       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5418       pr "    free (err.error_message);\n";
5419       pr "    guestfs___end_busy (g);\n";
5420       pr "    return %s;\n" error_code;
5421       pr "  }\n";
5422       pr "\n";
5423
5424       (* Expecting to receive further files (FileOut)? *)
5425       List.iter (
5426         function
5427         | FileOut n ->
5428             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5429             pr "    guestfs___end_busy (g);\n";
5430             pr "    return %s;\n" error_code;
5431             pr "  }\n";
5432             pr "\n";
5433         | _ -> ()
5434       ) (snd style);
5435
5436       pr "  guestfs___end_busy (g);\n";
5437
5438       (match fst style with
5439        | RErr -> pr "  return 0;\n"
5440        | RInt n | RInt64 n | RBool n ->
5441            pr "  return ret.%s;\n" n
5442        | RConstString _ | RConstOptString _ ->
5443            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5444        | RString n ->
5445            pr "  return ret.%s; /* caller will free */\n" n
5446        | RStringList n | RHashtable n ->
5447            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5448            pr "  ret.%s.%s_val =\n" n n;
5449            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5450            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5451              n n;
5452            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5453            pr "  return ret.%s.%s_val;\n" n n
5454        | RStruct (n, _) ->
5455            pr "  /* caller will free this */\n";
5456            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5457        | RStructList (n, _) ->
5458            pr "  /* caller will free this */\n";
5459            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5460        | RBufferOut n ->
5461            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5462            pr "   * _val might be NULL here.  To make the API saner for\n";
5463            pr "   * callers, we turn this case into a unique pointer (using\n";
5464            pr "   * malloc(1)).\n";
5465            pr "   */\n";
5466            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5467            pr "    *size_r = ret.%s.%s_len;\n" n n;
5468            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5469            pr "  } else {\n";
5470            pr "    free (ret.%s.%s_val);\n" n n;
5471            pr "    char *p = safe_malloc (g, 1);\n";
5472            pr "    *size_r = ret.%s.%s_len;\n" n n;
5473            pr "    return p;\n";
5474            pr "  }\n";
5475       );
5476
5477       pr "}\n\n"
5478   ) daemon_functions;
5479
5480   (* Functions to free structures. *)
5481   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5482   pr " * structure format is identical to the XDR format.  See note in\n";
5483   pr " * generator.ml.\n";
5484   pr " */\n";
5485   pr "\n";
5486
5487   List.iter (
5488     fun (typ, _) ->
5489       pr "void\n";
5490       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5491       pr "{\n";
5492       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5493       pr "  free (x);\n";
5494       pr "}\n";
5495       pr "\n";
5496
5497       pr "void\n";
5498       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5499       pr "{\n";
5500       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5501       pr "  free (x);\n";
5502       pr "}\n";
5503       pr "\n";
5504
5505   ) structs;
5506
5507 (* Generate daemon/actions.h. *)
5508 and generate_daemon_actions_h () =
5509   generate_header CStyle GPLv2;
5510
5511   pr "#include \"../src/guestfs_protocol.h\"\n";
5512   pr "\n";
5513
5514   List.iter (
5515     fun (name, style, _, _, _, _, _) ->
5516       generate_prototype
5517         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5518         name style;
5519   ) daemon_functions
5520
5521 (* Generate the server-side stubs. *)
5522 and generate_daemon_actions () =
5523   generate_header CStyle GPLv2;
5524
5525   pr "#include <config.h>\n";
5526   pr "\n";
5527   pr "#include <stdio.h>\n";
5528   pr "#include <stdlib.h>\n";
5529   pr "#include <string.h>\n";
5530   pr "#include <inttypes.h>\n";
5531   pr "#include <rpc/types.h>\n";
5532   pr "#include <rpc/xdr.h>\n";
5533   pr "\n";
5534   pr "#include \"daemon.h\"\n";
5535   pr "#include \"c-ctype.h\"\n";
5536   pr "#include \"../src/guestfs_protocol.h\"\n";
5537   pr "#include \"actions.h\"\n";
5538   pr "\n";
5539
5540   List.iter (
5541     fun (name, style, _, _, _, _, _) ->
5542       (* Generate server-side stubs. *)
5543       pr "static void %s_stub (XDR *xdr_in)\n" name;
5544       pr "{\n";
5545       let error_code =
5546         match fst style with
5547         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5548         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5549         | RBool _ -> pr "  int r;\n"; "-1"
5550         | RConstString _ | RConstOptString _ ->
5551             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5552         | RString _ -> pr "  char *r;\n"; "NULL"
5553         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5554         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5555         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5556         | RBufferOut _ ->
5557             pr "  size_t size = 1;\n";
5558             pr "  char *r;\n";
5559             "NULL" in
5560
5561       (match snd style with
5562        | [] -> ()
5563        | args ->
5564            pr "  struct guestfs_%s_args args;\n" name;
5565            List.iter (
5566              function
5567              | Device n | Dev_or_Path n
5568              | Pathname n
5569              | String n -> ()
5570              | OptString n -> pr "  char *%s;\n" n
5571              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5572              | Bool n -> pr "  int %s;\n" n
5573              | Int n -> pr "  int %s;\n" n
5574              | Int64 n -> pr "  int64_t %s;\n" n
5575              | FileIn _ | FileOut _ -> ()
5576            ) args
5577       );
5578       pr "\n";
5579
5580       (match snd style with
5581        | [] -> ()
5582        | args ->
5583            pr "  memset (&args, 0, sizeof args);\n";
5584            pr "\n";
5585            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5586            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5587            pr "    return;\n";
5588            pr "  }\n";
5589            let pr_args n =
5590              pr "  char *%s = args.%s;\n" n n
5591            in
5592            let pr_list_handling_code n =
5593              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5594              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5595              pr "  if (%s == NULL) {\n" n;
5596              pr "    reply_with_perror (\"realloc\");\n";
5597              pr "    goto done;\n";
5598              pr "  }\n";
5599              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5600              pr "  args.%s.%s_val = %s;\n" n n n;
5601            in
5602            List.iter (
5603              function
5604              | Pathname n ->
5605                  pr_args n;
5606                  pr "  ABS_PATH (%s, goto done);\n" n;
5607              | Device n ->
5608                  pr_args n;
5609                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5610              | Dev_or_Path n ->
5611                  pr_args n;
5612                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5613              | String n -> pr_args n
5614              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5615              | StringList n ->
5616                  pr_list_handling_code n;
5617              | DeviceList n ->
5618                  pr_list_handling_code n;
5619                  pr "  /* Ensure that each is a device,\n";
5620                  pr "   * and perform device name translation. */\n";
5621                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5622                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5623                  pr "  }\n";
5624              | Bool n -> pr "  %s = args.%s;\n" n n
5625              | Int n -> pr "  %s = args.%s;\n" n n
5626              | Int64 n -> pr "  %s = args.%s;\n" n n
5627              | FileIn _ | FileOut _ -> ()
5628            ) args;
5629            pr "\n"
5630       );
5631
5632
5633       (* this is used at least for do_equal *)
5634       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5635         (* Emit NEED_ROOT just once, even when there are two or
5636            more Pathname args *)
5637         pr "  NEED_ROOT (goto done);\n";
5638       );
5639
5640       (* Don't want to call the impl with any FileIn or FileOut
5641        * parameters, since these go "outside" the RPC protocol.
5642        *)
5643       let args' =
5644         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5645           (snd style) in
5646       pr "  r = do_%s " name;
5647       generate_c_call_args (fst style, args');
5648       pr ";\n";
5649
5650       (match fst style with
5651        | RErr | RInt _ | RInt64 _ | RBool _
5652        | RConstString _ | RConstOptString _
5653        | RString _ | RStringList _ | RHashtable _
5654        | RStruct (_, _) | RStructList (_, _) ->
5655            pr "  if (r == %s)\n" error_code;
5656            pr "    /* do_%s has already called reply_with_error */\n" name;
5657            pr "    goto done;\n";
5658            pr "\n"
5659        | RBufferOut _ ->
5660            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5661            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5662            pr "   */\n";
5663            pr "  if (size == 1 && r == %s)\n" error_code;
5664            pr "    /* do_%s has already called reply_with_error */\n" name;
5665            pr "    goto done;\n";
5666            pr "\n"
5667       );
5668
5669       (* If there are any FileOut parameters, then the impl must
5670        * send its own reply.
5671        *)
5672       let no_reply =
5673         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5674       if no_reply then
5675         pr "  /* do_%s has already sent a reply */\n" name
5676       else (
5677         match fst style with
5678         | RErr -> pr "  reply (NULL, NULL);\n"
5679         | RInt n | RInt64 n | RBool n ->
5680             pr "  struct guestfs_%s_ret ret;\n" name;
5681             pr "  ret.%s = r;\n" n;
5682             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5683               name
5684         | RConstString _ | RConstOptString _ ->
5685             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5686         | RString n ->
5687             pr "  struct guestfs_%s_ret ret;\n" name;
5688             pr "  ret.%s = r;\n" n;
5689             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5690               name;
5691             pr "  free (r);\n"
5692         | RStringList n | RHashtable n ->
5693             pr "  struct guestfs_%s_ret ret;\n" name;
5694             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5695             pr "  ret.%s.%s_val = r;\n" n n;
5696             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5697               name;
5698             pr "  free_strings (r);\n"
5699         | RStruct (n, _) ->
5700             pr "  struct guestfs_%s_ret ret;\n" name;
5701             pr "  ret.%s = *r;\n" n;
5702             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5703               name;
5704             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5705               name
5706         | RStructList (n, _) ->
5707             pr "  struct guestfs_%s_ret ret;\n" name;
5708             pr "  ret.%s = *r;\n" n;
5709             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5710               name;
5711             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5712               name
5713         | RBufferOut n ->
5714             pr "  struct guestfs_%s_ret ret;\n" name;
5715             pr "  ret.%s.%s_val = r;\n" n n;
5716             pr "  ret.%s.%s_len = size;\n" n n;
5717             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5718               name;
5719             pr "  free (r);\n"
5720       );
5721
5722       (* Free the args. *)
5723       (match snd style with
5724        | [] ->
5725            pr "done: ;\n";
5726        | _ ->
5727            pr "done:\n";
5728            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5729              name
5730       );
5731
5732       pr "}\n\n";
5733   ) daemon_functions;
5734
5735   (* Dispatch function. *)
5736   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5737   pr "{\n";
5738   pr "  switch (proc_nr) {\n";
5739
5740   List.iter (
5741     fun (name, style, _, _, _, _, _) ->
5742       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5743       pr "      %s_stub (xdr_in);\n" name;
5744       pr "      break;\n"
5745   ) daemon_functions;
5746
5747   pr "    default:\n";
5748   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory\", proc_nr);\n";
5749   pr "  }\n";
5750   pr "}\n";
5751   pr "\n";
5752
5753   (* LVM columns and tokenization functions. *)
5754   (* XXX This generates crap code.  We should rethink how we
5755    * do this parsing.
5756    *)
5757   List.iter (
5758     function
5759     | typ, cols ->
5760         pr "static const char *lvm_%s_cols = \"%s\";\n"
5761           typ (String.concat "," (List.map fst cols));
5762         pr "\n";
5763
5764         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5765         pr "{\n";
5766         pr "  char *tok, *p, *next;\n";
5767         pr "  int i, j;\n";
5768         pr "\n";
5769         (*
5770           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5771           pr "\n";
5772         *)
5773         pr "  if (!str) {\n";
5774         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5775         pr "    return -1;\n";
5776         pr "  }\n";
5777         pr "  if (!*str || c_isspace (*str)) {\n";
5778         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5779         pr "    return -1;\n";
5780         pr "  }\n";
5781         pr "  tok = str;\n";
5782         List.iter (
5783           fun (name, coltype) ->
5784             pr "  if (!tok) {\n";
5785             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5786             pr "    return -1;\n";
5787             pr "  }\n";
5788             pr "  p = strchrnul (tok, ',');\n";
5789             pr "  if (*p) next = p+1; else next = NULL;\n";
5790             pr "  *p = '\\0';\n";
5791             (match coltype with
5792              | FString ->
5793                  pr "  r->%s = strdup (tok);\n" name;
5794                  pr "  if (r->%s == NULL) {\n" name;
5795                  pr "    perror (\"strdup\");\n";
5796                  pr "    return -1;\n";
5797                  pr "  }\n"
5798              | FUUID ->
5799                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5800                  pr "    if (tok[j] == '\\0') {\n";
5801                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5802                  pr "      return -1;\n";
5803                  pr "    } else if (tok[j] != '-')\n";
5804                  pr "      r->%s[i++] = tok[j];\n" name;
5805                  pr "  }\n";
5806              | FBytes ->
5807                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5808                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5809                  pr "    return -1;\n";
5810                  pr "  }\n";
5811              | FInt64 ->
5812                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5813                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5814                  pr "    return -1;\n";
5815                  pr "  }\n";
5816              | FOptPercent ->
5817                  pr "  if (tok[0] == '\\0')\n";
5818                  pr "    r->%s = -1;\n" name;
5819                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5820                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5821                  pr "    return -1;\n";
5822                  pr "  }\n";
5823              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5824                  assert false (* can never be an LVM column *)
5825             );
5826             pr "  tok = next;\n";
5827         ) cols;
5828
5829         pr "  if (tok != NULL) {\n";
5830         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5831         pr "    return -1;\n";
5832         pr "  }\n";
5833         pr "  return 0;\n";
5834         pr "}\n";
5835         pr "\n";
5836
5837         pr "guestfs_int_lvm_%s_list *\n" typ;
5838         pr "parse_command_line_%ss (void)\n" typ;
5839         pr "{\n";
5840         pr "  char *out, *err;\n";
5841         pr "  char *p, *pend;\n";
5842         pr "  int r, i;\n";
5843         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5844         pr "  void *newp;\n";
5845         pr "\n";
5846         pr "  ret = malloc (sizeof *ret);\n";
5847         pr "  if (!ret) {\n";
5848         pr "    reply_with_perror (\"malloc\");\n";
5849         pr "    return NULL;\n";
5850         pr "  }\n";
5851         pr "\n";
5852         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5853         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5854         pr "\n";
5855         pr "  r = command (&out, &err,\n";
5856         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5857         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5858         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5859         pr "  if (r == -1) {\n";
5860         pr "    reply_with_error (\"%%s\", err);\n";
5861         pr "    free (out);\n";
5862         pr "    free (err);\n";
5863         pr "    free (ret);\n";
5864         pr "    return NULL;\n";
5865         pr "  }\n";
5866         pr "\n";
5867         pr "  free (err);\n";
5868         pr "\n";
5869         pr "  /* Tokenize each line of the output. */\n";
5870         pr "  p = out;\n";
5871         pr "  i = 0;\n";
5872         pr "  while (p) {\n";
5873         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5874         pr "    if (pend) {\n";
5875         pr "      *pend = '\\0';\n";
5876         pr "      pend++;\n";
5877         pr "    }\n";
5878         pr "\n";
5879         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5880         pr "      p++;\n";
5881         pr "\n";
5882         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5883         pr "      p = pend;\n";
5884         pr "      continue;\n";
5885         pr "    }\n";
5886         pr "\n";
5887         pr "    /* Allocate some space to store this next entry. */\n";
5888         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5889         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5890         pr "    if (newp == NULL) {\n";
5891         pr "      reply_with_perror (\"realloc\");\n";
5892         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5893         pr "      free (ret);\n";
5894         pr "      free (out);\n";
5895         pr "      return NULL;\n";
5896         pr "    }\n";
5897         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5898         pr "\n";
5899         pr "    /* Tokenize the next entry. */\n";
5900         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5901         pr "    if (r == -1) {\n";
5902         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5903         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5904         pr "      free (ret);\n";
5905         pr "      free (out);\n";
5906         pr "      return NULL;\n";
5907         pr "    }\n";
5908         pr "\n";
5909         pr "    ++i;\n";
5910         pr "    p = pend;\n";
5911         pr "  }\n";
5912         pr "\n";
5913         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5914         pr "\n";
5915         pr "  free (out);\n";
5916         pr "  return ret;\n";
5917         pr "}\n"
5918
5919   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5920
5921 (* Generate a list of function names, for debugging in the daemon.. *)
5922 and generate_daemon_names () =
5923   generate_header CStyle GPLv2;
5924
5925   pr "#include <config.h>\n";
5926   pr "\n";
5927   pr "#include \"daemon.h\"\n";
5928   pr "\n";
5929
5930   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5931   pr "const char *function_names[] = {\n";
5932   List.iter (
5933     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5934   ) daemon_functions;
5935   pr "};\n";
5936
5937 (* Generate the tests. *)
5938 and generate_tests () =
5939   generate_header CStyle GPLv2;
5940
5941   pr "\
5942 #include <stdio.h>
5943 #include <stdlib.h>
5944 #include <string.h>
5945 #include <unistd.h>
5946 #include <sys/types.h>
5947 #include <fcntl.h>
5948
5949 #include \"guestfs.h\"
5950 #include \"guestfs-internal.h\"
5951
5952 static guestfs_h *g;
5953 static int suppress_error = 0;
5954
5955 static void print_error (guestfs_h *g, void *data, const char *msg)
5956 {
5957   if (!suppress_error)
5958     fprintf (stderr, \"%%s\\n\", msg);
5959 }
5960
5961 /* FIXME: nearly identical code appears in fish.c */
5962 static void print_strings (char *const *argv)
5963 {
5964   int argc;
5965
5966   for (argc = 0; argv[argc] != NULL; ++argc)
5967     printf (\"\\t%%s\\n\", argv[argc]);
5968 }
5969
5970 /*
5971 static void print_table (char const *const *argv)
5972 {
5973   int i;
5974
5975   for (i = 0; argv[i] != NULL; i += 2)
5976     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5977 }
5978 */
5979
5980 ";
5981
5982   (* Generate a list of commands which are not tested anywhere. *)
5983   pr "static void no_test_warnings (void)\n";
5984   pr "{\n";
5985
5986   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5987   List.iter (
5988     fun (_, _, _, _, tests, _, _) ->
5989       let tests = filter_map (
5990         function
5991         | (_, (Always|If _|Unless _), test) -> Some test
5992         | (_, Disabled, _) -> None
5993       ) tests in
5994       let seq = List.concat (List.map seq_of_test tests) in
5995       let cmds_tested = List.map List.hd seq in
5996       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5997   ) all_functions;
5998
5999   List.iter (
6000     fun (name, _, _, _, _, _, _) ->
6001       if not (Hashtbl.mem hash name) then
6002         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6003   ) all_functions;
6004
6005   pr "}\n";
6006   pr "\n";
6007
6008   (* Generate the actual tests.  Note that we generate the tests
6009    * in reverse order, deliberately, so that (in general) the
6010    * newest tests run first.  This makes it quicker and easier to
6011    * debug them.
6012    *)
6013   let test_names =
6014     List.map (
6015       fun (name, _, _, _, tests, _, _) ->
6016         mapi (generate_one_test name) tests
6017     ) (List.rev all_functions) in
6018   let test_names = List.concat test_names in
6019   let nr_tests = List.length test_names in
6020
6021   pr "\
6022 int main (int argc, char *argv[])
6023 {
6024   char c = 0;
6025   unsigned long int n_failed = 0;
6026   const char *filename;
6027   int fd;
6028   int nr_tests, test_num = 0;
6029
6030   setbuf (stdout, NULL);
6031
6032   no_test_warnings ();
6033
6034   g = guestfs_create ();
6035   if (g == NULL) {
6036     printf (\"guestfs_create FAILED\\n\");
6037     exit (EXIT_FAILURE);
6038   }
6039
6040   guestfs_set_error_handler (g, print_error, NULL);
6041
6042   guestfs_set_path (g, \"../appliance\");
6043
6044   filename = \"test1.img\";
6045   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6046   if (fd == -1) {
6047     perror (filename);
6048     exit (EXIT_FAILURE);
6049   }
6050   if (lseek (fd, %d, SEEK_SET) == -1) {
6051     perror (\"lseek\");
6052     close (fd);
6053     unlink (filename);
6054     exit (EXIT_FAILURE);
6055   }
6056   if (write (fd, &c, 1) == -1) {
6057     perror (\"write\");
6058     close (fd);
6059     unlink (filename);
6060     exit (EXIT_FAILURE);
6061   }
6062   if (close (fd) == -1) {
6063     perror (filename);
6064     unlink (filename);
6065     exit (EXIT_FAILURE);
6066   }
6067   if (guestfs_add_drive (g, filename) == -1) {
6068     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6069     exit (EXIT_FAILURE);
6070   }
6071
6072   filename = \"test2.img\";
6073   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6074   if (fd == -1) {
6075     perror (filename);
6076     exit (EXIT_FAILURE);
6077   }
6078   if (lseek (fd, %d, SEEK_SET) == -1) {
6079     perror (\"lseek\");
6080     close (fd);
6081     unlink (filename);
6082     exit (EXIT_FAILURE);
6083   }
6084   if (write (fd, &c, 1) == -1) {
6085     perror (\"write\");
6086     close (fd);
6087     unlink (filename);
6088     exit (EXIT_FAILURE);
6089   }
6090   if (close (fd) == -1) {
6091     perror (filename);
6092     unlink (filename);
6093     exit (EXIT_FAILURE);
6094   }
6095   if (guestfs_add_drive (g, filename) == -1) {
6096     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6097     exit (EXIT_FAILURE);
6098   }
6099
6100   filename = \"test3.img\";
6101   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6102   if (fd == -1) {
6103     perror (filename);
6104     exit (EXIT_FAILURE);
6105   }
6106   if (lseek (fd, %d, SEEK_SET) == -1) {
6107     perror (\"lseek\");
6108     close (fd);
6109     unlink (filename);
6110     exit (EXIT_FAILURE);
6111   }
6112   if (write (fd, &c, 1) == -1) {
6113     perror (\"write\");
6114     close (fd);
6115     unlink (filename);
6116     exit (EXIT_FAILURE);
6117   }
6118   if (close (fd) == -1) {
6119     perror (filename);
6120     unlink (filename);
6121     exit (EXIT_FAILURE);
6122   }
6123   if (guestfs_add_drive (g, filename) == -1) {
6124     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6125     exit (EXIT_FAILURE);
6126   }
6127
6128   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6129     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6130     exit (EXIT_FAILURE);
6131   }
6132
6133   if (guestfs_launch (g) == -1) {
6134     printf (\"guestfs_launch FAILED\\n\");
6135     exit (EXIT_FAILURE);
6136   }
6137
6138   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6139   alarm (600);
6140
6141   /* Cancel previous alarm. */
6142   alarm (0);
6143
6144   nr_tests = %d;
6145
6146 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6147
6148   iteri (
6149     fun i test_name ->
6150       pr "  test_num++;\n";
6151       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6152       pr "  if (%s () == -1) {\n" test_name;
6153       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6154       pr "    n_failed++;\n";
6155       pr "  }\n";
6156   ) test_names;
6157   pr "\n";
6158
6159   pr "  guestfs_close (g);\n";
6160   pr "  unlink (\"test1.img\");\n";
6161   pr "  unlink (\"test2.img\");\n";
6162   pr "  unlink (\"test3.img\");\n";
6163   pr "\n";
6164
6165   pr "  if (n_failed > 0) {\n";
6166   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6167   pr "    exit (EXIT_FAILURE);\n";
6168   pr "  }\n";
6169   pr "\n";
6170
6171   pr "  exit (EXIT_SUCCESS);\n";
6172   pr "}\n"
6173
6174 and generate_one_test name i (init, prereq, test) =
6175   let test_name = sprintf "test_%s_%d" name i in
6176
6177   pr "\
6178 static int %s_skip (void)
6179 {
6180   const char *str;
6181
6182   str = getenv (\"TEST_ONLY\");
6183   if (str)
6184     return strstr (str, \"%s\") == NULL;
6185   str = getenv (\"SKIP_%s\");
6186   if (str && STREQ (str, \"1\")) return 1;
6187   str = getenv (\"SKIP_TEST_%s\");
6188   if (str && STREQ (str, \"1\")) return 1;
6189   return 0;
6190 }
6191
6192 " test_name name (String.uppercase test_name) (String.uppercase name);
6193
6194   (match prereq with
6195    | Disabled | Always -> ()
6196    | If code | Unless code ->
6197        pr "static int %s_prereq (void)\n" test_name;
6198        pr "{\n";
6199        pr "  %s\n" code;
6200        pr "}\n";
6201        pr "\n";
6202   );
6203
6204   pr "\
6205 static int %s (void)
6206 {
6207   if (%s_skip ()) {
6208     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6209     return 0;
6210   }
6211
6212 " test_name test_name test_name;
6213
6214   (match prereq with
6215    | Disabled ->
6216        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6217    | If _ ->
6218        pr "  if (! %s_prereq ()) {\n" test_name;
6219        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6220        pr "    return 0;\n";
6221        pr "  }\n";
6222        pr "\n";
6223        generate_one_test_body name i test_name init test;
6224    | Unless _ ->
6225        pr "  if (%s_prereq ()) {\n" test_name;
6226        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6227        pr "    return 0;\n";
6228        pr "  }\n";
6229        pr "\n";
6230        generate_one_test_body name i test_name init test;
6231    | Always ->
6232        generate_one_test_body name i test_name init test
6233   );
6234
6235   pr "  return 0;\n";
6236   pr "}\n";
6237   pr "\n";
6238   test_name
6239
6240 and generate_one_test_body name i test_name init test =
6241   (match init with
6242    | InitNone (* XXX at some point, InitNone and InitEmpty became
6243                * folded together as the same thing.  Really we should
6244                * make InitNone do nothing at all, but the tests may
6245                * need to be checked to make sure this is OK.
6246                *)
6247    | InitEmpty ->
6248        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6249        List.iter (generate_test_command_call test_name)
6250          [["blockdev_setrw"; "/dev/sda"];
6251           ["umount_all"];
6252           ["lvm_remove_all"]]
6253    | InitPartition ->
6254        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6255        List.iter (generate_test_command_call test_name)
6256          [["blockdev_setrw"; "/dev/sda"];
6257           ["umount_all"];
6258           ["lvm_remove_all"];
6259           ["part_disk"; "/dev/sda"; "mbr"]]
6260    | InitBasicFS ->
6261        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6262        List.iter (generate_test_command_call test_name)
6263          [["blockdev_setrw"; "/dev/sda"];
6264           ["umount_all"];
6265           ["lvm_remove_all"];
6266           ["part_disk"; "/dev/sda"; "mbr"];
6267           ["mkfs"; "ext2"; "/dev/sda1"];
6268           ["mount"; "/dev/sda1"; "/"]]
6269    | InitBasicFSonLVM ->
6270        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6271          test_name;
6272        List.iter (generate_test_command_call test_name)
6273          [["blockdev_setrw"; "/dev/sda"];
6274           ["umount_all"];
6275           ["lvm_remove_all"];
6276           ["part_disk"; "/dev/sda"; "mbr"];
6277           ["pvcreate"; "/dev/sda1"];
6278           ["vgcreate"; "VG"; "/dev/sda1"];
6279           ["lvcreate"; "LV"; "VG"; "8"];
6280           ["mkfs"; "ext2"; "/dev/VG/LV"];
6281           ["mount"; "/dev/VG/LV"; "/"]]
6282    | InitISOFS ->
6283        pr "  /* InitISOFS for %s */\n" test_name;
6284        List.iter (generate_test_command_call test_name)
6285          [["blockdev_setrw"; "/dev/sda"];
6286           ["umount_all"];
6287           ["lvm_remove_all"];
6288           ["mount_ro"; "/dev/sdd"; "/"]]
6289   );
6290
6291   let get_seq_last = function
6292     | [] ->
6293         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6294           test_name
6295     | seq ->
6296         let seq = List.rev seq in
6297         List.rev (List.tl seq), List.hd seq
6298   in
6299
6300   match test with
6301   | TestRun seq ->
6302       pr "  /* TestRun for %s (%d) */\n" name i;
6303       List.iter (generate_test_command_call test_name) seq
6304   | TestOutput (seq, expected) ->
6305       pr "  /* TestOutput for %s (%d) */\n" name i;
6306       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6307       let seq, last = get_seq_last seq in
6308       let test () =
6309         pr "    if (STRNEQ (r, expected)) {\n";
6310         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6311         pr "      return -1;\n";
6312         pr "    }\n"
6313       in
6314       List.iter (generate_test_command_call test_name) seq;
6315       generate_test_command_call ~test test_name last
6316   | TestOutputList (seq, expected) ->
6317       pr "  /* TestOutputList for %s (%d) */\n" name i;
6318       let seq, last = get_seq_last seq in
6319       let test () =
6320         iteri (
6321           fun i str ->
6322             pr "    if (!r[%d]) {\n" i;
6323             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6324             pr "      print_strings (r);\n";
6325             pr "      return -1;\n";
6326             pr "    }\n";
6327             pr "    {\n";
6328             pr "      const char *expected = \"%s\";\n" (c_quote str);
6329             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6330             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6331             pr "        return -1;\n";
6332             pr "      }\n";
6333             pr "    }\n"
6334         ) expected;
6335         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6336         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6337           test_name;
6338         pr "      print_strings (r);\n";
6339         pr "      return -1;\n";
6340         pr "    }\n"
6341       in
6342       List.iter (generate_test_command_call test_name) seq;
6343       generate_test_command_call ~test test_name last
6344   | TestOutputListOfDevices (seq, expected) ->
6345       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6346       let seq, last = get_seq_last seq in
6347       let test () =
6348         iteri (
6349           fun i str ->
6350             pr "    if (!r[%d]) {\n" i;
6351             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6352             pr "      print_strings (r);\n";
6353             pr "      return -1;\n";
6354             pr "    }\n";
6355             pr "    {\n";
6356             pr "      const char *expected = \"%s\";\n" (c_quote str);
6357             pr "      r[%d][5] = 's';\n" i;
6358             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6359             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6360             pr "        return -1;\n";
6361             pr "      }\n";
6362             pr "    }\n"
6363         ) expected;
6364         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6365         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6366           test_name;
6367         pr "      print_strings (r);\n";
6368         pr "      return -1;\n";
6369         pr "    }\n"
6370       in
6371       List.iter (generate_test_command_call test_name) seq;
6372       generate_test_command_call ~test test_name last
6373   | TestOutputInt (seq, expected) ->
6374       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6375       let seq, last = get_seq_last seq in
6376       let test () =
6377         pr "    if (r != %d) {\n" expected;
6378         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6379           test_name expected;
6380         pr "               (int) r);\n";
6381         pr "      return -1;\n";
6382         pr "    }\n"
6383       in
6384       List.iter (generate_test_command_call test_name) seq;
6385       generate_test_command_call ~test test_name last
6386   | TestOutputIntOp (seq, op, expected) ->
6387       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6388       let seq, last = get_seq_last seq in
6389       let test () =
6390         pr "    if (! (r %s %d)) {\n" op expected;
6391         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6392           test_name op expected;
6393         pr "               (int) r);\n";
6394         pr "      return -1;\n";
6395         pr "    }\n"
6396       in
6397       List.iter (generate_test_command_call test_name) seq;
6398       generate_test_command_call ~test test_name last
6399   | TestOutputTrue seq ->
6400       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6401       let seq, last = get_seq_last seq in
6402       let test () =
6403         pr "    if (!r) {\n";
6404         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6405           test_name;
6406         pr "      return -1;\n";
6407         pr "    }\n"
6408       in
6409       List.iter (generate_test_command_call test_name) seq;
6410       generate_test_command_call ~test test_name last
6411   | TestOutputFalse seq ->
6412       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6413       let seq, last = get_seq_last seq in
6414       let test () =
6415         pr "    if (r) {\n";
6416         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6417           test_name;
6418         pr "      return -1;\n";
6419         pr "    }\n"
6420       in
6421       List.iter (generate_test_command_call test_name) seq;
6422       generate_test_command_call ~test test_name last
6423   | TestOutputLength (seq, expected) ->
6424       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6425       let seq, last = get_seq_last seq in
6426       let test () =
6427         pr "    int j;\n";
6428         pr "    for (j = 0; j < %d; ++j)\n" expected;
6429         pr "      if (r[j] == NULL) {\n";
6430         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6431           test_name;
6432         pr "        print_strings (r);\n";
6433         pr "        return -1;\n";
6434         pr "      }\n";
6435         pr "    if (r[j] != NULL) {\n";
6436         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6437           test_name;
6438         pr "      print_strings (r);\n";
6439         pr "      return -1;\n";
6440         pr "    }\n"
6441       in
6442       List.iter (generate_test_command_call test_name) seq;
6443       generate_test_command_call ~test test_name last
6444   | TestOutputBuffer (seq, expected) ->
6445       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6446       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6447       let seq, last = get_seq_last seq in
6448       let len = String.length expected in
6449       let test () =
6450         pr "    if (size != %d) {\n" len;
6451         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6452         pr "      return -1;\n";
6453         pr "    }\n";
6454         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6455         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6456         pr "      return -1;\n";
6457         pr "    }\n"
6458       in
6459       List.iter (generate_test_command_call test_name) seq;
6460       generate_test_command_call ~test test_name last
6461   | TestOutputStruct (seq, checks) ->
6462       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6463       let seq, last = get_seq_last seq in
6464       let test () =
6465         List.iter (
6466           function
6467           | CompareWithInt (field, expected) ->
6468               pr "    if (r->%s != %d) {\n" field expected;
6469               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6470                 test_name field expected;
6471               pr "               (int) r->%s);\n" field;
6472               pr "      return -1;\n";
6473               pr "    }\n"
6474           | CompareWithIntOp (field, op, expected) ->
6475               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6476               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6477                 test_name field op expected;
6478               pr "               (int) r->%s);\n" field;
6479               pr "      return -1;\n";
6480               pr "    }\n"
6481           | CompareWithString (field, expected) ->
6482               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6483               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6484                 test_name field expected;
6485               pr "               r->%s);\n" field;
6486               pr "      return -1;\n";
6487               pr "    }\n"
6488           | CompareFieldsIntEq (field1, field2) ->
6489               pr "    if (r->%s != r->%s) {\n" field1 field2;
6490               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6491                 test_name field1 field2;
6492               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6493               pr "      return -1;\n";
6494               pr "    }\n"
6495           | CompareFieldsStrEq (field1, field2) ->
6496               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6497               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6498                 test_name field1 field2;
6499               pr "               r->%s, r->%s);\n" field1 field2;
6500               pr "      return -1;\n";
6501               pr "    }\n"
6502         ) checks
6503       in
6504       List.iter (generate_test_command_call test_name) seq;
6505       generate_test_command_call ~test test_name last
6506   | TestLastFail seq ->
6507       pr "  /* TestLastFail for %s (%d) */\n" name i;
6508       let seq, last = get_seq_last seq in
6509       List.iter (generate_test_command_call test_name) seq;
6510       generate_test_command_call test_name ~expect_error:true last
6511
6512 (* Generate the code to run a command, leaving the result in 'r'.
6513  * If you expect to get an error then you should set expect_error:true.
6514  *)
6515 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6516   match cmd with
6517   | [] -> assert false
6518   | name :: args ->
6519       (* Look up the command to find out what args/ret it has. *)
6520       let style =
6521         try
6522           let _, style, _, _, _, _, _ =
6523             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6524           style
6525         with Not_found ->
6526           failwithf "%s: in test, command %s was not found" test_name name in
6527
6528       if List.length (snd style) <> List.length args then
6529         failwithf "%s: in test, wrong number of args given to %s"
6530           test_name name;
6531
6532       pr "  {\n";
6533
6534       List.iter (
6535         function
6536         | OptString n, "NULL" -> ()
6537         | Pathname n, arg
6538         | Device n, arg
6539         | Dev_or_Path n, arg
6540         | String n, arg
6541         | OptString n, arg ->
6542             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6543         | Int _, _
6544         | Int64 _, _
6545         | Bool _, _
6546         | FileIn _, _ | FileOut _, _ -> ()
6547         | StringList n, arg | DeviceList n, arg ->
6548             let strs = string_split " " arg in
6549             iteri (
6550               fun i str ->
6551                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6552             ) strs;
6553             pr "    const char *const %s[] = {\n" n;
6554             iteri (
6555               fun i _ -> pr "      %s_%d,\n" n i
6556             ) strs;
6557             pr "      NULL\n";
6558             pr "    };\n";
6559       ) (List.combine (snd style) args);
6560
6561       let error_code =
6562         match fst style with
6563         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6564         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6565         | RConstString _ | RConstOptString _ ->
6566             pr "    const char *r;\n"; "NULL"
6567         | RString _ -> pr "    char *r;\n"; "NULL"
6568         | RStringList _ | RHashtable _ ->
6569             pr "    char **r;\n";
6570             pr "    int i;\n";
6571             "NULL"
6572         | RStruct (_, typ) ->
6573             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6574         | RStructList (_, typ) ->
6575             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6576         | RBufferOut _ ->
6577             pr "    char *r;\n";
6578             pr "    size_t size;\n";
6579             "NULL" in
6580
6581       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6582       pr "    r = guestfs_%s (g" name;
6583
6584       (* Generate the parameters. *)
6585       List.iter (
6586         function
6587         | OptString _, "NULL" -> pr ", NULL"
6588         | Pathname n, _
6589         | Device n, _ | Dev_or_Path n, _
6590         | String n, _
6591         | OptString n, _ ->
6592             pr ", %s" n
6593         | FileIn _, arg | FileOut _, arg ->
6594             pr ", \"%s\"" (c_quote arg)
6595         | StringList n, _ | DeviceList n, _ ->
6596             pr ", (char **) %s" n
6597         | Int _, arg ->
6598             let i =
6599               try int_of_string arg
6600               with Failure "int_of_string" ->
6601                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6602             pr ", %d" i
6603         | Int64 _, arg ->
6604             let i =
6605               try Int64.of_string arg
6606               with Failure "int_of_string" ->
6607                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6608             pr ", %Ld" i
6609         | Bool _, arg ->
6610             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6611       ) (List.combine (snd style) args);
6612
6613       (match fst style with
6614        | RBufferOut _ -> pr ", &size"
6615        | _ -> ()
6616       );
6617
6618       pr ");\n";
6619
6620       if not expect_error then
6621         pr "    if (r == %s)\n" error_code
6622       else
6623         pr "    if (r != %s)\n" error_code;
6624       pr "      return -1;\n";
6625
6626       (* Insert the test code. *)
6627       (match test with
6628        | None -> ()
6629        | Some f -> f ()
6630       );
6631
6632       (match fst style with
6633        | RErr | RInt _ | RInt64 _ | RBool _
6634        | RConstString _ | RConstOptString _ -> ()
6635        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6636        | RStringList _ | RHashtable _ ->
6637            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6638            pr "      free (r[i]);\n";
6639            pr "    free (r);\n"
6640        | RStruct (_, typ) ->
6641            pr "    guestfs_free_%s (r);\n" typ
6642        | RStructList (_, typ) ->
6643            pr "    guestfs_free_%s_list (r);\n" typ
6644       );
6645
6646       pr "  }\n"
6647
6648 and c_quote str =
6649   let str = replace_str str "\r" "\\r" in
6650   let str = replace_str str "\n" "\\n" in
6651   let str = replace_str str "\t" "\\t" in
6652   let str = replace_str str "\000" "\\0" in
6653   str
6654
6655 (* Generate a lot of different functions for guestfish. *)
6656 and generate_fish_cmds () =
6657   generate_header CStyle GPLv2;
6658
6659   let all_functions =
6660     List.filter (
6661       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6662     ) all_functions in
6663   let all_functions_sorted =
6664     List.filter (
6665       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6666     ) all_functions_sorted in
6667
6668   pr "#include <stdio.h>\n";
6669   pr "#include <stdlib.h>\n";
6670   pr "#include <string.h>\n";
6671   pr "#include <inttypes.h>\n";
6672   pr "\n";
6673   pr "#include <guestfs.h>\n";
6674   pr "#include \"c-ctype.h\"\n";
6675   pr "#include \"fish.h\"\n";
6676   pr "\n";
6677
6678   (* list_commands function, which implements guestfish -h *)
6679   pr "void list_commands (void)\n";
6680   pr "{\n";
6681   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6682   pr "  list_builtin_commands ();\n";
6683   List.iter (
6684     fun (name, _, _, flags, _, shortdesc, _) ->
6685       let name = replace_char name '_' '-' in
6686       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6687         name shortdesc
6688   ) all_functions_sorted;
6689   pr "  printf (\"    %%s\\n\",";
6690   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6691   pr "}\n";
6692   pr "\n";
6693
6694   (* display_command function, which implements guestfish -h cmd *)
6695   pr "void display_command (const char *cmd)\n";
6696   pr "{\n";
6697   List.iter (
6698     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6699       let name2 = replace_char name '_' '-' in
6700       let alias =
6701         try find_map (function FishAlias n -> Some n | _ -> None) flags
6702         with Not_found -> name in
6703       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6704       let synopsis =
6705         match snd style with
6706         | [] -> name2
6707         | args ->
6708             sprintf "%s %s"
6709               name2 (String.concat " " (List.map name_of_argt args)) in
6710
6711       let warnings =
6712         if List.mem ProtocolLimitWarning flags then
6713           ("\n\n" ^ protocol_limit_warning)
6714         else "" in
6715
6716       (* For DangerWillRobinson commands, we should probably have
6717        * guestfish prompt before allowing you to use them (especially
6718        * in interactive mode). XXX
6719        *)
6720       let warnings =
6721         warnings ^
6722           if List.mem DangerWillRobinson flags then
6723             ("\n\n" ^ danger_will_robinson)
6724           else "" in
6725
6726       let warnings =
6727         warnings ^
6728           match deprecation_notice flags with
6729           | None -> ""
6730           | Some txt -> "\n\n" ^ txt in
6731
6732       let describe_alias =
6733         if name <> alias then
6734           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6735         else "" in
6736
6737       pr "  if (";
6738       pr "STRCASEEQ (cmd, \"%s\")" name;
6739       if name <> name2 then
6740         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6741       if name <> alias then
6742         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6743       pr ")\n";
6744       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6745         name2 shortdesc
6746         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6747          "=head1 DESCRIPTION\n\n" ^
6748          longdesc ^ warnings ^ describe_alias);
6749       pr "  else\n"
6750   ) all_functions;
6751   pr "    display_builtin_command (cmd);\n";
6752   pr "}\n";
6753   pr "\n";
6754
6755   let emit_print_list_function typ =
6756     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6757       typ typ typ;
6758     pr "{\n";
6759     pr "  unsigned int i;\n";
6760     pr "\n";
6761     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6762     pr "    printf (\"[%%d] = {\\n\", i);\n";
6763     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6764     pr "    printf (\"}\\n\");\n";
6765     pr "  }\n";
6766     pr "}\n";
6767     pr "\n";
6768   in
6769
6770   (* print_* functions *)
6771   List.iter (
6772     fun (typ, cols) ->
6773       let needs_i =
6774         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6775
6776       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6777       pr "{\n";
6778       if needs_i then (
6779         pr "  unsigned int i;\n";
6780         pr "\n"
6781       );
6782       List.iter (
6783         function
6784         | name, FString ->
6785             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6786         | name, FUUID ->
6787             pr "  printf (\"%%s%s: \", indent);\n" name;
6788             pr "  for (i = 0; i < 32; ++i)\n";
6789             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6790             pr "  printf (\"\\n\");\n"
6791         | name, FBuffer ->
6792             pr "  printf (\"%%s%s: \", indent);\n" name;
6793             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6794             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6795             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6796             pr "    else\n";
6797             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6798             pr "  printf (\"\\n\");\n"
6799         | name, (FUInt64|FBytes) ->
6800             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6801               name typ name
6802         | name, FInt64 ->
6803             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6804               name typ name
6805         | name, FUInt32 ->
6806             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6807               name typ name
6808         | name, FInt32 ->
6809             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6810               name typ name
6811         | name, FChar ->
6812             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6813               name typ name
6814         | name, FOptPercent ->
6815             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6816               typ name name typ name;
6817             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6818       ) cols;
6819       pr "}\n";
6820       pr "\n";
6821   ) structs;
6822
6823   (* Emit a print_TYPE_list function definition only if that function is used. *)
6824   List.iter (
6825     function
6826     | typ, (RStructListOnly | RStructAndList) ->
6827         (* generate the function for typ *)
6828         emit_print_list_function typ
6829     | typ, _ -> () (* empty *)
6830   ) (rstructs_used_by all_functions);
6831
6832   (* Emit a print_TYPE function definition only if that function is used. *)
6833   List.iter (
6834     function
6835     | typ, (RStructOnly | RStructAndList) ->
6836         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6837         pr "{\n";
6838         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6839         pr "}\n";
6840         pr "\n";
6841     | typ, _ -> () (* empty *)
6842   ) (rstructs_used_by all_functions);
6843
6844   (* run_<action> actions *)
6845   List.iter (
6846     fun (name, style, _, flags, _, _, _) ->
6847       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6848       pr "{\n";
6849       (match fst style with
6850        | RErr
6851        | RInt _
6852        | RBool _ -> pr "  int r;\n"
6853        | RInt64 _ -> pr "  int64_t r;\n"
6854        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6855        | RString _ -> pr "  char *r;\n"
6856        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6857        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6858        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6859        | RBufferOut _ ->
6860            pr "  char *r;\n";
6861            pr "  size_t size;\n";
6862       );
6863       List.iter (
6864         function
6865         | Device n
6866         | String n
6867         | OptString n
6868         | FileIn n
6869         | FileOut n -> pr "  const char *%s;\n" n
6870         | Pathname n
6871         | Dev_or_Path n -> pr "  char *%s;\n" n
6872         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6873         | Bool n -> pr "  int %s;\n" n
6874         | Int n -> pr "  int %s;\n" n
6875         | Int64 n -> pr "  int64_t %s;\n" n
6876       ) (snd style);
6877
6878       (* Check and convert parameters. *)
6879       let argc_expected = List.length (snd style) in
6880       pr "  if (argc != %d) {\n" argc_expected;
6881       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6882         argc_expected;
6883       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6884       pr "    return -1;\n";
6885       pr "  }\n";
6886       iteri (
6887         fun i ->
6888           function
6889           | Device name
6890           | String name ->
6891               pr "  %s = argv[%d];\n" name i
6892           | Pathname name
6893           | Dev_or_Path name ->
6894               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6895               pr "  if (%s == NULL) return -1;\n" name
6896           | OptString name ->
6897               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6898                 name i i
6899           | FileIn name ->
6900               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6901                 name i i
6902           | FileOut name ->
6903               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6904                 name i i
6905           | StringList name | DeviceList name ->
6906               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6907               pr "  if (%s == NULL) return -1;\n" name;
6908           | Bool name ->
6909               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6910           | Int name ->
6911               pr "  %s = atoi (argv[%d]);\n" name i
6912           | Int64 name ->
6913               pr "  %s = atoll (argv[%d]);\n" name i
6914       ) (snd style);
6915
6916       (* Call C API function. *)
6917       let fn =
6918         try find_map (function FishAction n -> Some n | _ -> None) flags
6919         with Not_found -> sprintf "guestfs_%s" name in
6920       pr "  r = %s " fn;
6921       generate_c_call_args ~handle:"g" style;
6922       pr ";\n";
6923
6924       List.iter (
6925         function
6926         | Device name | String name
6927         | OptString name | FileIn name | FileOut name | Bool name
6928         | Int name | Int64 name -> ()
6929         | Pathname name | Dev_or_Path name ->
6930             pr "  free (%s);\n" name
6931         | StringList name | DeviceList name ->
6932             pr "  free_strings (%s);\n" name
6933       ) (snd style);
6934
6935       (* Check return value for errors and display command results. *)
6936       (match fst style with
6937        | RErr -> pr "  return r;\n"
6938        | RInt _ ->
6939            pr "  if (r == -1) return -1;\n";
6940            pr "  printf (\"%%d\\n\", r);\n";
6941            pr "  return 0;\n"
6942        | RInt64 _ ->
6943            pr "  if (r == -1) return -1;\n";
6944            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6945            pr "  return 0;\n"
6946        | RBool _ ->
6947            pr "  if (r == -1) return -1;\n";
6948            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6949            pr "  return 0;\n"
6950        | RConstString _ ->
6951            pr "  if (r == NULL) return -1;\n";
6952            pr "  printf (\"%%s\\n\", r);\n";
6953            pr "  return 0;\n"
6954        | RConstOptString _ ->
6955            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6956            pr "  return 0;\n"
6957        | RString _ ->
6958            pr "  if (r == NULL) return -1;\n";
6959            pr "  printf (\"%%s\\n\", r);\n";
6960            pr "  free (r);\n";
6961            pr "  return 0;\n"
6962        | RStringList _ ->
6963            pr "  if (r == NULL) return -1;\n";
6964            pr "  print_strings (r);\n";
6965            pr "  free_strings (r);\n";
6966            pr "  return 0;\n"
6967        | RStruct (_, typ) ->
6968            pr "  if (r == NULL) return -1;\n";
6969            pr "  print_%s (r);\n" typ;
6970            pr "  guestfs_free_%s (r);\n" typ;
6971            pr "  return 0;\n"
6972        | RStructList (_, typ) ->
6973            pr "  if (r == NULL) return -1;\n";
6974            pr "  print_%s_list (r);\n" typ;
6975            pr "  guestfs_free_%s_list (r);\n" typ;
6976            pr "  return 0;\n"
6977        | RHashtable _ ->
6978            pr "  if (r == NULL) return -1;\n";
6979            pr "  print_table (r);\n";
6980            pr "  free_strings (r);\n";
6981            pr "  return 0;\n"
6982        | RBufferOut _ ->
6983            pr "  if (r == NULL) return -1;\n";
6984            pr "  fwrite (r, size, 1, stdout);\n";
6985            pr "  free (r);\n";
6986            pr "  return 0;\n"
6987       );
6988       pr "}\n";
6989       pr "\n"
6990   ) all_functions;
6991
6992   (* run_action function *)
6993   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6994   pr "{\n";
6995   List.iter (
6996     fun (name, _, _, flags, _, _, _) ->
6997       let name2 = replace_char name '_' '-' in
6998       let alias =
6999         try find_map (function FishAlias n -> Some n | _ -> None) flags
7000         with Not_found -> name in
7001       pr "  if (";
7002       pr "STRCASEEQ (cmd, \"%s\")" name;
7003       if name <> name2 then
7004         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7005       if name <> alias then
7006         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7007       pr ")\n";
7008       pr "    return run_%s (cmd, argc, argv);\n" name;
7009       pr "  else\n";
7010   ) all_functions;
7011   pr "    {\n";
7012   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7013   pr "      return -1;\n";
7014   pr "    }\n";
7015   pr "  return 0;\n";
7016   pr "}\n";
7017   pr "\n"
7018
7019 (* Readline completion for guestfish. *)
7020 and generate_fish_completion () =
7021   generate_header CStyle GPLv2;
7022
7023   let all_functions =
7024     List.filter (
7025       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7026     ) all_functions in
7027
7028   pr "\
7029 #include <config.h>
7030
7031 #include <stdio.h>
7032 #include <stdlib.h>
7033 #include <string.h>
7034
7035 #ifdef HAVE_LIBREADLINE
7036 #include <readline/readline.h>
7037 #endif
7038
7039 #include \"fish.h\"
7040
7041 #ifdef HAVE_LIBREADLINE
7042
7043 static const char *const commands[] = {
7044   BUILTIN_COMMANDS_FOR_COMPLETION,
7045 ";
7046
7047   (* Get the commands, including the aliases.  They don't need to be
7048    * sorted - the generator() function just does a dumb linear search.
7049    *)
7050   let commands =
7051     List.map (
7052       fun (name, _, _, flags, _, _, _) ->
7053         let name2 = replace_char name '_' '-' in
7054         let alias =
7055           try find_map (function FishAlias n -> Some n | _ -> None) flags
7056           with Not_found -> name in
7057
7058         if name <> alias then [name2; alias] else [name2]
7059     ) all_functions in
7060   let commands = List.flatten commands in
7061
7062   List.iter (pr "  \"%s\",\n") commands;
7063
7064   pr "  NULL
7065 };
7066
7067 static char *
7068 generator (const char *text, int state)
7069 {
7070   static int index, len;
7071   const char *name;
7072
7073   if (!state) {
7074     index = 0;
7075     len = strlen (text);
7076   }
7077
7078   rl_attempted_completion_over = 1;
7079
7080   while ((name = commands[index]) != NULL) {
7081     index++;
7082     if (STRCASEEQLEN (name, text, len))
7083       return strdup (name);
7084   }
7085
7086   return NULL;
7087 }
7088
7089 #endif /* HAVE_LIBREADLINE */
7090
7091 char **do_completion (const char *text, int start, int end)
7092 {
7093   char **matches = NULL;
7094
7095 #ifdef HAVE_LIBREADLINE
7096   rl_completion_append_character = ' ';
7097
7098   if (start == 0)
7099     matches = rl_completion_matches (text, generator);
7100   else if (complete_dest_paths)
7101     matches = rl_completion_matches (text, complete_dest_paths_generator);
7102 #endif
7103
7104   return matches;
7105 }
7106 ";
7107
7108 (* Generate the POD documentation for guestfish. *)
7109 and generate_fish_actions_pod () =
7110   let all_functions_sorted =
7111     List.filter (
7112       fun (_, _, _, flags, _, _, _) ->
7113         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7114     ) all_functions_sorted in
7115
7116   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7117
7118   List.iter (
7119     fun (name, style, _, flags, _, _, longdesc) ->
7120       let longdesc =
7121         Str.global_substitute rex (
7122           fun s ->
7123             let sub =
7124               try Str.matched_group 1 s
7125               with Not_found ->
7126                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7127             "C<" ^ replace_char sub '_' '-' ^ ">"
7128         ) longdesc in
7129       let name = replace_char name '_' '-' in
7130       let alias =
7131         try find_map (function FishAlias n -> Some n | _ -> None) flags
7132         with Not_found -> name in
7133
7134       pr "=head2 %s" name;
7135       if name <> alias then
7136         pr " | %s" alias;
7137       pr "\n";
7138       pr "\n";
7139       pr " %s" name;
7140       List.iter (
7141         function
7142         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7143         | OptString n -> pr " %s" n
7144         | StringList n | DeviceList n -> pr " '%s ...'" n
7145         | Bool _ -> pr " true|false"
7146         | Int n -> pr " %s" n
7147         | Int64 n -> pr " %s" n
7148         | FileIn n | FileOut n -> pr " (%s|-)" n
7149       ) (snd style);
7150       pr "\n";
7151       pr "\n";
7152       pr "%s\n\n" longdesc;
7153
7154       if List.exists (function FileIn _ | FileOut _ -> true
7155                       | _ -> false) (snd style) then
7156         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7157
7158       if List.mem ProtocolLimitWarning flags then
7159         pr "%s\n\n" protocol_limit_warning;
7160
7161       if List.mem DangerWillRobinson flags then
7162         pr "%s\n\n" danger_will_robinson;
7163
7164       match deprecation_notice flags with
7165       | None -> ()
7166       | Some txt -> pr "%s\n\n" txt
7167   ) all_functions_sorted
7168
7169 (* Generate a C function prototype. *)
7170 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7171     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7172     ?(prefix = "")
7173     ?handle name style =
7174   if extern then pr "extern ";
7175   if static then pr "static ";
7176   (match fst style with
7177    | RErr -> pr "int "
7178    | RInt _ -> pr "int "
7179    | RInt64 _ -> pr "int64_t "
7180    | RBool _ -> pr "int "
7181    | RConstString _ | RConstOptString _ -> pr "const char *"
7182    | RString _ | RBufferOut _ -> pr "char *"
7183    | RStringList _ | RHashtable _ -> pr "char **"
7184    | RStruct (_, typ) ->
7185        if not in_daemon then pr "struct guestfs_%s *" typ
7186        else pr "guestfs_int_%s *" typ
7187    | RStructList (_, typ) ->
7188        if not in_daemon then pr "struct guestfs_%s_list *" typ
7189        else pr "guestfs_int_%s_list *" typ
7190   );
7191   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7192   pr "%s%s (" prefix name;
7193   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7194     pr "void"
7195   else (
7196     let comma = ref false in
7197     (match handle with
7198      | None -> ()
7199      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7200     );
7201     let next () =
7202       if !comma then (
7203         if single_line then pr ", " else pr ",\n\t\t"
7204       );
7205       comma := true
7206     in
7207     List.iter (
7208       function
7209       | Pathname n
7210       | Device n | Dev_or_Path n
7211       | String n
7212       | OptString n ->
7213           next ();
7214           pr "const char *%s" n
7215       | StringList n | DeviceList n ->
7216           next ();
7217           pr "char *const *%s" n
7218       | Bool n -> next (); pr "int %s" n
7219       | Int n -> next (); pr "int %s" n
7220       | Int64 n -> next (); pr "int64_t %s" n
7221       | FileIn n
7222       | FileOut n ->
7223           if not in_daemon then (next (); pr "const char *%s" n)
7224     ) (snd style);
7225     if is_RBufferOut then (next (); pr "size_t *size_r");
7226   );
7227   pr ")";
7228   if semicolon then pr ";";
7229   if newline then pr "\n"
7230
7231 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7232 and generate_c_call_args ?handle ?(decl = false) style =
7233   pr "(";
7234   let comma = ref false in
7235   let next () =
7236     if !comma then pr ", ";
7237     comma := true
7238   in
7239   (match handle with
7240    | None -> ()
7241    | Some handle -> pr "%s" handle; comma := true
7242   );
7243   List.iter (
7244     fun arg ->
7245       next ();
7246       pr "%s" (name_of_argt arg)
7247   ) (snd style);
7248   (* For RBufferOut calls, add implicit &size parameter. *)
7249   if not decl then (
7250     match fst style with
7251     | RBufferOut _ ->
7252         next ();
7253         pr "&size"
7254     | _ -> ()
7255   );
7256   pr ")"
7257
7258 (* Generate the OCaml bindings interface. *)
7259 and generate_ocaml_mli () =
7260   generate_header OCamlStyle LGPLv2;
7261
7262   pr "\
7263 (** For API documentation you should refer to the C API
7264     in the guestfs(3) manual page.  The OCaml API uses almost
7265     exactly the same calls. *)
7266
7267 type t
7268 (** A [guestfs_h] handle. *)
7269
7270 exception Error of string
7271 (** This exception is raised when there is an error. *)
7272
7273 exception Handle_closed of string
7274 (** This exception is raised if you use a {!Guestfs.t} handle
7275     after calling {!close} on it.  The string is the name of
7276     the function. *)
7277
7278 val create : unit -> t
7279 (** Create a {!Guestfs.t} handle. *)
7280
7281 val close : t -> unit
7282 (** Close the {!Guestfs.t} handle and free up all resources used
7283     by it immediately.
7284
7285     Handles are closed by the garbage collector when they become
7286     unreferenced, but callers can call this in order to provide
7287     predictable cleanup. *)
7288
7289 ";
7290   generate_ocaml_structure_decls ();
7291
7292   (* The actions. *)
7293   List.iter (
7294     fun (name, style, _, _, _, shortdesc, _) ->
7295       generate_ocaml_prototype name style;
7296       pr "(** %s *)\n" shortdesc;
7297       pr "\n"
7298   ) all_functions_sorted
7299
7300 (* Generate the OCaml bindings implementation. *)
7301 and generate_ocaml_ml () =
7302   generate_header OCamlStyle LGPLv2;
7303
7304   pr "\
7305 type t
7306
7307 exception Error of string
7308 exception Handle_closed of string
7309
7310 external create : unit -> t = \"ocaml_guestfs_create\"
7311 external close : t -> unit = \"ocaml_guestfs_close\"
7312
7313 (* Give the exceptions names, so they can be raised from the C code. *)
7314 let () =
7315   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7316   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7317
7318 ";
7319
7320   generate_ocaml_structure_decls ();
7321
7322   (* The actions. *)
7323   List.iter (
7324     fun (name, style, _, _, _, shortdesc, _) ->
7325       generate_ocaml_prototype ~is_external:true name style;
7326   ) all_functions_sorted
7327
7328 (* Generate the OCaml bindings C implementation. *)
7329 and generate_ocaml_c () =
7330   generate_header CStyle LGPLv2;
7331
7332   pr "\
7333 #include <stdio.h>
7334 #include <stdlib.h>
7335 #include <string.h>
7336
7337 #include <caml/config.h>
7338 #include <caml/alloc.h>
7339 #include <caml/callback.h>
7340 #include <caml/fail.h>
7341 #include <caml/memory.h>
7342 #include <caml/mlvalues.h>
7343 #include <caml/signals.h>
7344
7345 #include <guestfs.h>
7346
7347 #include \"guestfs_c.h\"
7348
7349 /* Copy a hashtable of string pairs into an assoc-list.  We return
7350  * the list in reverse order, but hashtables aren't supposed to be
7351  * ordered anyway.
7352  */
7353 static CAMLprim value
7354 copy_table (char * const * argv)
7355 {
7356   CAMLparam0 ();
7357   CAMLlocal5 (rv, pairv, kv, vv, cons);
7358   int i;
7359
7360   rv = Val_int (0);
7361   for (i = 0; argv[i] != NULL; i += 2) {
7362     kv = caml_copy_string (argv[i]);
7363     vv = caml_copy_string (argv[i+1]);
7364     pairv = caml_alloc (2, 0);
7365     Store_field (pairv, 0, kv);
7366     Store_field (pairv, 1, vv);
7367     cons = caml_alloc (2, 0);
7368     Store_field (cons, 1, rv);
7369     rv = cons;
7370     Store_field (cons, 0, pairv);
7371   }
7372
7373   CAMLreturn (rv);
7374 }
7375
7376 ";
7377
7378   (* Struct copy functions. *)
7379
7380   let emit_ocaml_copy_list_function typ =
7381     pr "static CAMLprim value\n";
7382     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7383     pr "{\n";
7384     pr "  CAMLparam0 ();\n";
7385     pr "  CAMLlocal2 (rv, v);\n";
7386     pr "  unsigned int i;\n";
7387     pr "\n";
7388     pr "  if (%ss->len == 0)\n" typ;
7389     pr "    CAMLreturn (Atom (0));\n";
7390     pr "  else {\n";
7391     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7392     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7393     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7394     pr "      caml_modify (&Field (rv, i), v);\n";
7395     pr "    }\n";
7396     pr "    CAMLreturn (rv);\n";
7397     pr "  }\n";
7398     pr "}\n";
7399     pr "\n";
7400   in
7401
7402   List.iter (
7403     fun (typ, cols) ->
7404       let has_optpercent_col =
7405         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7406
7407       pr "static CAMLprim value\n";
7408       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7409       pr "{\n";
7410       pr "  CAMLparam0 ();\n";
7411       if has_optpercent_col then
7412         pr "  CAMLlocal3 (rv, v, v2);\n"
7413       else
7414         pr "  CAMLlocal2 (rv, v);\n";
7415       pr "\n";
7416       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7417       iteri (
7418         fun i col ->
7419           (match col with
7420            | name, FString ->
7421                pr "  v = caml_copy_string (%s->%s);\n" typ name
7422            | name, FBuffer ->
7423                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7424                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7425                  typ name typ name
7426            | name, FUUID ->
7427                pr "  v = caml_alloc_string (32);\n";
7428                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7429            | name, (FBytes|FInt64|FUInt64) ->
7430                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7431            | name, (FInt32|FUInt32) ->
7432                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7433            | name, FOptPercent ->
7434                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7435                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7436                pr "    v = caml_alloc (1, 0);\n";
7437                pr "    Store_field (v, 0, v2);\n";
7438                pr "  } else /* None */\n";
7439                pr "    v = Val_int (0);\n";
7440            | name, FChar ->
7441                pr "  v = Val_int (%s->%s);\n" typ name
7442           );
7443           pr "  Store_field (rv, %d, v);\n" i
7444       ) cols;
7445       pr "  CAMLreturn (rv);\n";
7446       pr "}\n";
7447       pr "\n";
7448   ) structs;
7449
7450   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7451   List.iter (
7452     function
7453     | typ, (RStructListOnly | RStructAndList) ->
7454         (* generate the function for typ *)
7455         emit_ocaml_copy_list_function typ
7456     | typ, _ -> () (* empty *)
7457   ) (rstructs_used_by all_functions);
7458
7459   (* The wrappers. *)
7460   List.iter (
7461     fun (name, style, _, _, _, _, _) ->
7462       pr "/* Automatically generated wrapper for function\n";
7463       pr " * ";
7464       generate_ocaml_prototype name style;
7465       pr " */\n";
7466       pr "\n";
7467
7468       let params =
7469         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7470
7471       let needs_extra_vs =
7472         match fst style with RConstOptString _ -> true | _ -> false in
7473
7474       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7475       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7476       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7477       pr "\n";
7478
7479       pr "CAMLprim value\n";
7480       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7481       List.iter (pr ", value %s") (List.tl params);
7482       pr ")\n";
7483       pr "{\n";
7484
7485       (match params with
7486        | [p1; p2; p3; p4; p5] ->
7487            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7488        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7489            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7490            pr "  CAMLxparam%d (%s);\n"
7491              (List.length rest) (String.concat ", " rest)
7492        | ps ->
7493            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7494       );
7495       if not needs_extra_vs then
7496         pr "  CAMLlocal1 (rv);\n"
7497       else
7498         pr "  CAMLlocal3 (rv, v, v2);\n";
7499       pr "\n";
7500
7501       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7502       pr "  if (g == NULL)\n";
7503       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7504       pr "\n";
7505
7506       List.iter (
7507         function
7508         | Pathname n
7509         | Device n | Dev_or_Path n
7510         | String n
7511         | FileIn n
7512         | FileOut n ->
7513             pr "  const char *%s = String_val (%sv);\n" n n
7514         | OptString n ->
7515             pr "  const char *%s =\n" n;
7516             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7517               n n
7518         | StringList n | DeviceList n ->
7519             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7520         | Bool n ->
7521             pr "  int %s = Bool_val (%sv);\n" n n
7522         | Int n ->
7523             pr "  int %s = Int_val (%sv);\n" n n
7524         | Int64 n ->
7525             pr "  int64_t %s = Int64_val (%sv);\n" n n
7526       ) (snd style);
7527       let error_code =
7528         match fst style with
7529         | RErr -> pr "  int r;\n"; "-1"
7530         | RInt _ -> pr "  int r;\n"; "-1"
7531         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7532         | RBool _ -> pr "  int r;\n"; "-1"
7533         | RConstString _ | RConstOptString _ ->
7534             pr "  const char *r;\n"; "NULL"
7535         | RString _ -> pr "  char *r;\n"; "NULL"
7536         | RStringList _ ->
7537             pr "  int i;\n";
7538             pr "  char **r;\n";
7539             "NULL"
7540         | RStruct (_, typ) ->
7541             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7542         | RStructList (_, typ) ->
7543             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7544         | RHashtable _ ->
7545             pr "  int i;\n";
7546             pr "  char **r;\n";
7547             "NULL"
7548         | RBufferOut _ ->
7549             pr "  char *r;\n";
7550             pr "  size_t size;\n";
7551             "NULL" in
7552       pr "\n";
7553
7554       pr "  caml_enter_blocking_section ();\n";
7555       pr "  r = guestfs_%s " name;
7556       generate_c_call_args ~handle:"g" style;
7557       pr ";\n";
7558       pr "  caml_leave_blocking_section ();\n";
7559
7560       List.iter (
7561         function
7562         | StringList n | DeviceList n ->
7563             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7564         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7565         | Bool _ | Int _ | Int64 _
7566         | FileIn _ | FileOut _ -> ()
7567       ) (snd style);
7568
7569       pr "  if (r == %s)\n" error_code;
7570       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7571       pr "\n";
7572
7573       (match fst style with
7574        | RErr -> pr "  rv = Val_unit;\n"
7575        | RInt _ -> pr "  rv = Val_int (r);\n"
7576        | RInt64 _ ->
7577            pr "  rv = caml_copy_int64 (r);\n"
7578        | RBool _ -> pr "  rv = Val_bool (r);\n"
7579        | RConstString _ ->
7580            pr "  rv = caml_copy_string (r);\n"
7581        | RConstOptString _ ->
7582            pr "  if (r) { /* Some string */\n";
7583            pr "    v = caml_alloc (1, 0);\n";
7584            pr "    v2 = caml_copy_string (r);\n";
7585            pr "    Store_field (v, 0, v2);\n";
7586            pr "  } else /* None */\n";
7587            pr "    v = Val_int (0);\n";
7588        | RString _ ->
7589            pr "  rv = caml_copy_string (r);\n";
7590            pr "  free (r);\n"
7591        | RStringList _ ->
7592            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7593            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7594            pr "  free (r);\n"
7595        | RStruct (_, typ) ->
7596            pr "  rv = copy_%s (r);\n" typ;
7597            pr "  guestfs_free_%s (r);\n" typ;
7598        | RStructList (_, typ) ->
7599            pr "  rv = copy_%s_list (r);\n" typ;
7600            pr "  guestfs_free_%s_list (r);\n" typ;
7601        | RHashtable _ ->
7602            pr "  rv = copy_table (r);\n";
7603            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7604            pr "  free (r);\n";
7605        | RBufferOut _ ->
7606            pr "  rv = caml_alloc_string (size);\n";
7607            pr "  memcpy (String_val (rv), r, size);\n";
7608       );
7609
7610       pr "  CAMLreturn (rv);\n";
7611       pr "}\n";
7612       pr "\n";
7613
7614       if List.length params > 5 then (
7615         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7616         pr "CAMLprim value ";
7617         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7618         pr "CAMLprim value\n";
7619         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7620         pr "{\n";
7621         pr "  return ocaml_guestfs_%s (argv[0]" name;
7622         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7623         pr ");\n";
7624         pr "}\n";
7625         pr "\n"
7626       )
7627   ) all_functions_sorted
7628
7629 and generate_ocaml_structure_decls () =
7630   List.iter (
7631     fun (typ, cols) ->
7632       pr "type %s = {\n" typ;
7633       List.iter (
7634         function
7635         | name, FString -> pr "  %s : string;\n" name
7636         | name, FBuffer -> pr "  %s : string;\n" name
7637         | name, FUUID -> pr "  %s : string;\n" name
7638         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7639         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7640         | name, FChar -> pr "  %s : char;\n" name
7641         | name, FOptPercent -> pr "  %s : float option;\n" name
7642       ) cols;
7643       pr "}\n";
7644       pr "\n"
7645   ) structs
7646
7647 and generate_ocaml_prototype ?(is_external = false) name style =
7648   if is_external then pr "external " else pr "val ";
7649   pr "%s : t -> " name;
7650   List.iter (
7651     function
7652     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7653     | OptString _ -> pr "string option -> "
7654     | StringList _ | DeviceList _ -> pr "string array -> "
7655     | Bool _ -> pr "bool -> "
7656     | Int _ -> pr "int -> "
7657     | Int64 _ -> pr "int64 -> "
7658   ) (snd style);
7659   (match fst style with
7660    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7661    | RInt _ -> pr "int"
7662    | RInt64 _ -> pr "int64"
7663    | RBool _ -> pr "bool"
7664    | RConstString _ -> pr "string"
7665    | RConstOptString _ -> pr "string option"
7666    | RString _ | RBufferOut _ -> pr "string"
7667    | RStringList _ -> pr "string array"
7668    | RStruct (_, typ) -> pr "%s" typ
7669    | RStructList (_, typ) -> pr "%s array" typ
7670    | RHashtable _ -> pr "(string * string) list"
7671   );
7672   if is_external then (
7673     pr " = ";
7674     if List.length (snd style) + 1 > 5 then
7675       pr "\"ocaml_guestfs_%s_byte\" " name;
7676     pr "\"ocaml_guestfs_%s\"" name
7677   );
7678   pr "\n"
7679
7680 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7681 and generate_perl_xs () =
7682   generate_header CStyle LGPLv2;
7683
7684   pr "\
7685 #include \"EXTERN.h\"
7686 #include \"perl.h\"
7687 #include \"XSUB.h\"
7688
7689 #include <guestfs.h>
7690
7691 #ifndef PRId64
7692 #define PRId64 \"lld\"
7693 #endif
7694
7695 static SV *
7696 my_newSVll(long long val) {
7697 #ifdef USE_64_BIT_ALL
7698   return newSViv(val);
7699 #else
7700   char buf[100];
7701   int len;
7702   len = snprintf(buf, 100, \"%%\" PRId64, val);
7703   return newSVpv(buf, len);
7704 #endif
7705 }
7706
7707 #ifndef PRIu64
7708 #define PRIu64 \"llu\"
7709 #endif
7710
7711 static SV *
7712 my_newSVull(unsigned long long val) {
7713 #ifdef USE_64_BIT_ALL
7714   return newSVuv(val);
7715 #else
7716   char buf[100];
7717   int len;
7718   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7719   return newSVpv(buf, len);
7720 #endif
7721 }
7722
7723 /* http://www.perlmonks.org/?node_id=680842 */
7724 static char **
7725 XS_unpack_charPtrPtr (SV *arg) {
7726   char **ret;
7727   AV *av;
7728   I32 i;
7729
7730   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7731     croak (\"array reference expected\");
7732
7733   av = (AV *)SvRV (arg);
7734   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7735   if (!ret)
7736     croak (\"malloc failed\");
7737
7738   for (i = 0; i <= av_len (av); i++) {
7739     SV **elem = av_fetch (av, i, 0);
7740
7741     if (!elem || !*elem)
7742       croak (\"missing element in list\");
7743
7744     ret[i] = SvPV_nolen (*elem);
7745   }
7746
7747   ret[i] = NULL;
7748
7749   return ret;
7750 }
7751
7752 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7753
7754 PROTOTYPES: ENABLE
7755
7756 guestfs_h *
7757 _create ()
7758    CODE:
7759       RETVAL = guestfs_create ();
7760       if (!RETVAL)
7761         croak (\"could not create guestfs handle\");
7762       guestfs_set_error_handler (RETVAL, NULL, NULL);
7763  OUTPUT:
7764       RETVAL
7765
7766 void
7767 DESTROY (g)
7768       guestfs_h *g;
7769  PPCODE:
7770       guestfs_close (g);
7771
7772 ";
7773
7774   List.iter (
7775     fun (name, style, _, _, _, _, _) ->
7776       (match fst style with
7777        | RErr -> pr "void\n"
7778        | RInt _ -> pr "SV *\n"
7779        | RInt64 _ -> pr "SV *\n"
7780        | RBool _ -> pr "SV *\n"
7781        | RConstString _ -> pr "SV *\n"
7782        | RConstOptString _ -> pr "SV *\n"
7783        | RString _ -> pr "SV *\n"
7784        | RBufferOut _ -> pr "SV *\n"
7785        | RStringList _
7786        | RStruct _ | RStructList _
7787        | RHashtable _ ->
7788            pr "void\n" (* all lists returned implictly on the stack *)
7789       );
7790       (* Call and arguments. *)
7791       pr "%s " name;
7792       generate_c_call_args ~handle:"g" ~decl:true style;
7793       pr "\n";
7794       pr "      guestfs_h *g;\n";
7795       iteri (
7796         fun i ->
7797           function
7798           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7799               pr "      char *%s;\n" n
7800           | OptString n ->
7801               (* http://www.perlmonks.org/?node_id=554277
7802                * Note that the implicit handle argument means we have
7803                * to add 1 to the ST(x) operator.
7804                *)
7805               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7806           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7807           | Bool n -> pr "      int %s;\n" n
7808           | Int n -> pr "      int %s;\n" n
7809           | Int64 n -> pr "      int64_t %s;\n" n
7810       ) (snd style);
7811
7812       let do_cleanups () =
7813         List.iter (
7814           function
7815           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7816           | Bool _ | Int _ | Int64 _
7817           | FileIn _ | FileOut _ -> ()
7818           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7819         ) (snd style)
7820       in
7821
7822       (* Code. *)
7823       (match fst style with
7824        | RErr ->
7825            pr "PREINIT:\n";
7826            pr "      int r;\n";
7827            pr " PPCODE:\n";
7828            pr "      r = guestfs_%s " name;
7829            generate_c_call_args ~handle:"g" style;
7830            pr ";\n";
7831            do_cleanups ();
7832            pr "      if (r == -1)\n";
7833            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7834        | RInt n
7835        | RBool n ->
7836            pr "PREINIT:\n";
7837            pr "      int %s;\n" n;
7838            pr "   CODE:\n";
7839            pr "      %s = guestfs_%s " n name;
7840            generate_c_call_args ~handle:"g" style;
7841            pr ";\n";
7842            do_cleanups ();
7843            pr "      if (%s == -1)\n" n;
7844            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7845            pr "      RETVAL = newSViv (%s);\n" n;
7846            pr " OUTPUT:\n";
7847            pr "      RETVAL\n"
7848        | RInt64 n ->
7849            pr "PREINIT:\n";
7850            pr "      int64_t %s;\n" n;
7851            pr "   CODE:\n";
7852            pr "      %s = guestfs_%s " n name;
7853            generate_c_call_args ~handle:"g" style;
7854            pr ";\n";
7855            do_cleanups ();
7856            pr "      if (%s == -1)\n" n;
7857            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7858            pr "      RETVAL = my_newSVll (%s);\n" n;
7859            pr " OUTPUT:\n";
7860            pr "      RETVAL\n"
7861        | RConstString n ->
7862            pr "PREINIT:\n";
7863            pr "      const char *%s;\n" n;
7864            pr "   CODE:\n";
7865            pr "      %s = guestfs_%s " n name;
7866            generate_c_call_args ~handle:"g" style;
7867            pr ";\n";
7868            do_cleanups ();
7869            pr "      if (%s == NULL)\n" n;
7870            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7871            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7872            pr " OUTPUT:\n";
7873            pr "      RETVAL\n"
7874        | RConstOptString n ->
7875            pr "PREINIT:\n";
7876            pr "      const char *%s;\n" n;
7877            pr "   CODE:\n";
7878            pr "      %s = guestfs_%s " n name;
7879            generate_c_call_args ~handle:"g" style;
7880            pr ";\n";
7881            do_cleanups ();
7882            pr "      if (%s == NULL)\n" n;
7883            pr "        RETVAL = &PL_sv_undef;\n";
7884            pr "      else\n";
7885            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7886            pr " OUTPUT:\n";
7887            pr "      RETVAL\n"
7888        | RString n ->
7889            pr "PREINIT:\n";
7890            pr "      char *%s;\n" n;
7891            pr "   CODE:\n";
7892            pr "      %s = guestfs_%s " n name;
7893            generate_c_call_args ~handle:"g" style;
7894            pr ";\n";
7895            do_cleanups ();
7896            pr "      if (%s == NULL)\n" n;
7897            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7898            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7899            pr "      free (%s);\n" n;
7900            pr " OUTPUT:\n";
7901            pr "      RETVAL\n"
7902        | RStringList n | RHashtable n ->
7903            pr "PREINIT:\n";
7904            pr "      char **%s;\n" n;
7905            pr "      int i, n;\n";
7906            pr " PPCODE:\n";
7907            pr "      %s = guestfs_%s " n name;
7908            generate_c_call_args ~handle:"g" style;
7909            pr ";\n";
7910            do_cleanups ();
7911            pr "      if (%s == NULL)\n" n;
7912            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7913            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7914            pr "      EXTEND (SP, n);\n";
7915            pr "      for (i = 0; i < n; ++i) {\n";
7916            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7917            pr "        free (%s[i]);\n" n;
7918            pr "      }\n";
7919            pr "      free (%s);\n" n;
7920        | RStruct (n, typ) ->
7921            let cols = cols_of_struct typ in
7922            generate_perl_struct_code typ cols name style n do_cleanups
7923        | RStructList (n, typ) ->
7924            let cols = cols_of_struct typ in
7925            generate_perl_struct_list_code typ cols name style n do_cleanups
7926        | RBufferOut n ->
7927            pr "PREINIT:\n";
7928            pr "      char *%s;\n" n;
7929            pr "      size_t size;\n";
7930            pr "   CODE:\n";
7931            pr "      %s = guestfs_%s " n name;
7932            generate_c_call_args ~handle:"g" style;
7933            pr ";\n";
7934            do_cleanups ();
7935            pr "      if (%s == NULL)\n" n;
7936            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7937            pr "      RETVAL = newSVpv (%s, size);\n" n;
7938            pr "      free (%s);\n" n;
7939            pr " OUTPUT:\n";
7940            pr "      RETVAL\n"
7941       );
7942
7943       pr "\n"
7944   ) all_functions
7945
7946 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7947   pr "PREINIT:\n";
7948   pr "      struct guestfs_%s_list *%s;\n" typ n;
7949   pr "      int i;\n";
7950   pr "      HV *hv;\n";
7951   pr " PPCODE:\n";
7952   pr "      %s = guestfs_%s " n name;
7953   generate_c_call_args ~handle:"g" style;
7954   pr ";\n";
7955   do_cleanups ();
7956   pr "      if (%s == NULL)\n" n;
7957   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7958   pr "      EXTEND (SP, %s->len);\n" n;
7959   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7960   pr "        hv = newHV ();\n";
7961   List.iter (
7962     function
7963     | name, FString ->
7964         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7965           name (String.length name) n name
7966     | name, FUUID ->
7967         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7968           name (String.length name) n name
7969     | name, FBuffer ->
7970         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7971           name (String.length name) n name n name
7972     | name, (FBytes|FUInt64) ->
7973         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7974           name (String.length name) n name
7975     | name, FInt64 ->
7976         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7977           name (String.length name) n name
7978     | name, (FInt32|FUInt32) ->
7979         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7980           name (String.length name) n name
7981     | name, FChar ->
7982         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7983           name (String.length name) n name
7984     | name, FOptPercent ->
7985         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7986           name (String.length name) n name
7987   ) cols;
7988   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7989   pr "      }\n";
7990   pr "      guestfs_free_%s_list (%s);\n" typ n
7991
7992 and generate_perl_struct_code typ cols name style n do_cleanups =
7993   pr "PREINIT:\n";
7994   pr "      struct guestfs_%s *%s;\n" typ n;
7995   pr " PPCODE:\n";
7996   pr "      %s = guestfs_%s " n name;
7997   generate_c_call_args ~handle:"g" style;
7998   pr ";\n";
7999   do_cleanups ();
8000   pr "      if (%s == NULL)\n" n;
8001   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8002   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8003   List.iter (
8004     fun ((name, _) as col) ->
8005       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8006
8007       match col with
8008       | name, FString ->
8009           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8010             n name
8011       | name, FBuffer ->
8012           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8013             n name n name
8014       | name, FUUID ->
8015           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8016             n name
8017       | name, (FBytes|FUInt64) ->
8018           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8019             n name
8020       | name, FInt64 ->
8021           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8022             n name
8023       | name, (FInt32|FUInt32) ->
8024           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8025             n name
8026       | name, FChar ->
8027           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8028             n name
8029       | name, FOptPercent ->
8030           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8031             n name
8032   ) cols;
8033   pr "      free (%s);\n" n
8034
8035 (* Generate Sys/Guestfs.pm. *)
8036 and generate_perl_pm () =
8037   generate_header HashStyle LGPLv2;
8038
8039   pr "\
8040 =pod
8041
8042 =head1 NAME
8043
8044 Sys::Guestfs - Perl bindings for libguestfs
8045
8046 =head1 SYNOPSIS
8047
8048  use Sys::Guestfs;
8049
8050  my $h = Sys::Guestfs->new ();
8051  $h->add_drive ('guest.img');
8052  $h->launch ();
8053  $h->mount ('/dev/sda1', '/');
8054  $h->touch ('/hello');
8055  $h->sync ();
8056
8057 =head1 DESCRIPTION
8058
8059 The C<Sys::Guestfs> module provides a Perl XS binding to the
8060 libguestfs API for examining and modifying virtual machine
8061 disk images.
8062
8063 Amongst the things this is good for: making batch configuration
8064 changes to guests, getting disk used/free statistics (see also:
8065 virt-df), migrating between virtualization systems (see also:
8066 virt-p2v), performing partial backups, performing partial guest
8067 clones, cloning guests and changing registry/UUID/hostname info, and
8068 much else besides.
8069
8070 Libguestfs uses Linux kernel and qemu code, and can access any type of
8071 guest filesystem that Linux and qemu can, including but not limited
8072 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8073 schemes, qcow, qcow2, vmdk.
8074
8075 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8076 LVs, what filesystem is in each LV, etc.).  It can also run commands
8077 in the context of the guest.  Also you can access filesystems over FTP.
8078
8079 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8080 functions for using libguestfs from Perl, including integration
8081 with libvirt.
8082
8083 =head1 ERRORS
8084
8085 All errors turn into calls to C<croak> (see L<Carp(3)>).
8086
8087 =head1 METHODS
8088
8089 =over 4
8090
8091 =cut
8092
8093 package Sys::Guestfs;
8094
8095 use strict;
8096 use warnings;
8097
8098 require XSLoader;
8099 XSLoader::load ('Sys::Guestfs');
8100
8101 =item $h = Sys::Guestfs->new ();
8102
8103 Create a new guestfs handle.
8104
8105 =cut
8106
8107 sub new {
8108   my $proto = shift;
8109   my $class = ref ($proto) || $proto;
8110
8111   my $self = Sys::Guestfs::_create ();
8112   bless $self, $class;
8113   return $self;
8114 }
8115
8116 ";
8117
8118   (* Actions.  We only need to print documentation for these as
8119    * they are pulled in from the XS code automatically.
8120    *)
8121   List.iter (
8122     fun (name, style, _, flags, _, _, longdesc) ->
8123       if not (List.mem NotInDocs flags) then (
8124         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8125         pr "=item ";
8126         generate_perl_prototype name style;
8127         pr "\n\n";
8128         pr "%s\n\n" longdesc;
8129         if List.mem ProtocolLimitWarning flags then
8130           pr "%s\n\n" protocol_limit_warning;
8131         if List.mem DangerWillRobinson flags then
8132           pr "%s\n\n" danger_will_robinson;
8133         match deprecation_notice flags with
8134         | None -> ()
8135         | Some txt -> pr "%s\n\n" txt
8136       )
8137   ) all_functions_sorted;
8138
8139   (* End of file. *)
8140   pr "\
8141 =cut
8142
8143 1;
8144
8145 =back
8146
8147 =head1 COPYRIGHT
8148
8149 Copyright (C) 2009 Red Hat Inc.
8150
8151 =head1 LICENSE
8152
8153 Please see the file COPYING.LIB for the full license.
8154
8155 =head1 SEE ALSO
8156
8157 L<guestfs(3)>,
8158 L<guestfish(1)>,
8159 L<http://libguestfs.org>,
8160 L<Sys::Guestfs::Lib(3)>.
8161
8162 =cut
8163 "
8164
8165 and generate_perl_prototype name style =
8166   (match fst style with
8167    | RErr -> ()
8168    | RBool n
8169    | RInt n
8170    | RInt64 n
8171    | RConstString n
8172    | RConstOptString n
8173    | RString n
8174    | RBufferOut n -> pr "$%s = " n
8175    | RStruct (n,_)
8176    | RHashtable n -> pr "%%%s = " n
8177    | RStringList n
8178    | RStructList (n,_) -> pr "@%s = " n
8179   );
8180   pr "$h->%s (" name;
8181   let comma = ref false in
8182   List.iter (
8183     fun arg ->
8184       if !comma then pr ", ";
8185       comma := true;
8186       match arg with
8187       | Pathname n | Device n | Dev_or_Path n | String n
8188       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8189           pr "$%s" n
8190       | StringList n | DeviceList n ->
8191           pr "\\@%s" n
8192   ) (snd style);
8193   pr ");"
8194
8195 (* Generate Python C module. *)
8196 and generate_python_c () =
8197   generate_header CStyle LGPLv2;
8198
8199   pr "\
8200 #include <Python.h>
8201
8202 #include <stdio.h>
8203 #include <stdlib.h>
8204 #include <assert.h>
8205
8206 #include \"guestfs.h\"
8207
8208 typedef struct {
8209   PyObject_HEAD
8210   guestfs_h *g;
8211 } Pyguestfs_Object;
8212
8213 static guestfs_h *
8214 get_handle (PyObject *obj)
8215 {
8216   assert (obj);
8217   assert (obj != Py_None);
8218   return ((Pyguestfs_Object *) obj)->g;
8219 }
8220
8221 static PyObject *
8222 put_handle (guestfs_h *g)
8223 {
8224   assert (g);
8225   return
8226     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8227 }
8228
8229 /* This list should be freed (but not the strings) after use. */
8230 static char **
8231 get_string_list (PyObject *obj)
8232 {
8233   int i, len;
8234   char **r;
8235
8236   assert (obj);
8237
8238   if (!PyList_Check (obj)) {
8239     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8240     return NULL;
8241   }
8242
8243   len = PyList_Size (obj);
8244   r = malloc (sizeof (char *) * (len+1));
8245   if (r == NULL) {
8246     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8247     return NULL;
8248   }
8249
8250   for (i = 0; i < len; ++i)
8251     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8252   r[len] = NULL;
8253
8254   return r;
8255 }
8256
8257 static PyObject *
8258 put_string_list (char * const * const argv)
8259 {
8260   PyObject *list;
8261   int argc, i;
8262
8263   for (argc = 0; argv[argc] != NULL; ++argc)
8264     ;
8265
8266   list = PyList_New (argc);
8267   for (i = 0; i < argc; ++i)
8268     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8269
8270   return list;
8271 }
8272
8273 static PyObject *
8274 put_table (char * const * const argv)
8275 {
8276   PyObject *list, *item;
8277   int argc, i;
8278
8279   for (argc = 0; argv[argc] != NULL; ++argc)
8280     ;
8281
8282   list = PyList_New (argc >> 1);
8283   for (i = 0; i < argc; i += 2) {
8284     item = PyTuple_New (2);
8285     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8286     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8287     PyList_SetItem (list, i >> 1, item);
8288   }
8289
8290   return list;
8291 }
8292
8293 static void
8294 free_strings (char **argv)
8295 {
8296   int argc;
8297
8298   for (argc = 0; argv[argc] != NULL; ++argc)
8299     free (argv[argc]);
8300   free (argv);
8301 }
8302
8303 static PyObject *
8304 py_guestfs_create (PyObject *self, PyObject *args)
8305 {
8306   guestfs_h *g;
8307
8308   g = guestfs_create ();
8309   if (g == NULL) {
8310     PyErr_SetString (PyExc_RuntimeError,
8311                      \"guestfs.create: failed to allocate handle\");
8312     return NULL;
8313   }
8314   guestfs_set_error_handler (g, NULL, NULL);
8315   return put_handle (g);
8316 }
8317
8318 static PyObject *
8319 py_guestfs_close (PyObject *self, PyObject *args)
8320 {
8321   PyObject *py_g;
8322   guestfs_h *g;
8323
8324   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8325     return NULL;
8326   g = get_handle (py_g);
8327
8328   guestfs_close (g);
8329
8330   Py_INCREF (Py_None);
8331   return Py_None;
8332 }
8333
8334 ";
8335
8336   let emit_put_list_function typ =
8337     pr "static PyObject *\n";
8338     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8339     pr "{\n";
8340     pr "  PyObject *list;\n";
8341     pr "  int i;\n";
8342     pr "\n";
8343     pr "  list = PyList_New (%ss->len);\n" typ;
8344     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8345     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8346     pr "  return list;\n";
8347     pr "};\n";
8348     pr "\n"
8349   in
8350
8351   (* Structures, turned into Python dictionaries. *)
8352   List.iter (
8353     fun (typ, cols) ->
8354       pr "static PyObject *\n";
8355       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8356       pr "{\n";
8357       pr "  PyObject *dict;\n";
8358       pr "\n";
8359       pr "  dict = PyDict_New ();\n";
8360       List.iter (
8361         function
8362         | name, FString ->
8363             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8364             pr "                        PyString_FromString (%s->%s));\n"
8365               typ name
8366         | name, FBuffer ->
8367             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8368             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8369               typ name typ name
8370         | name, FUUID ->
8371             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8372             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8373               typ name
8374         | name, (FBytes|FUInt64) ->
8375             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8376             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8377               typ name
8378         | name, FInt64 ->
8379             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8380             pr "                        PyLong_FromLongLong (%s->%s));\n"
8381               typ name
8382         | name, FUInt32 ->
8383             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8384             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8385               typ name
8386         | name, FInt32 ->
8387             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8388             pr "                        PyLong_FromLong (%s->%s));\n"
8389               typ name
8390         | name, FOptPercent ->
8391             pr "  if (%s->%s >= 0)\n" typ name;
8392             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8393             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8394               typ name;
8395             pr "  else {\n";
8396             pr "    Py_INCREF (Py_None);\n";
8397             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8398             pr "  }\n"
8399         | name, FChar ->
8400             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8401             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8402       ) cols;
8403       pr "  return dict;\n";
8404       pr "};\n";
8405       pr "\n";
8406
8407   ) structs;
8408
8409   (* Emit a put_TYPE_list function definition only if that function is used. *)
8410   List.iter (
8411     function
8412     | typ, (RStructListOnly | RStructAndList) ->
8413         (* generate the function for typ *)
8414         emit_put_list_function typ
8415     | typ, _ -> () (* empty *)
8416   ) (rstructs_used_by all_functions);
8417
8418   (* Python wrapper functions. *)
8419   List.iter (
8420     fun (name, style, _, _, _, _, _) ->
8421       pr "static PyObject *\n";
8422       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8423       pr "{\n";
8424
8425       pr "  PyObject *py_g;\n";
8426       pr "  guestfs_h *g;\n";
8427       pr "  PyObject *py_r;\n";
8428
8429       let error_code =
8430         match fst style with
8431         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8432         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8433         | RConstString _ | RConstOptString _ ->
8434             pr "  const char *r;\n"; "NULL"
8435         | RString _ -> pr "  char *r;\n"; "NULL"
8436         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8437         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8438         | RStructList (_, typ) ->
8439             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8440         | RBufferOut _ ->
8441             pr "  char *r;\n";
8442             pr "  size_t size;\n";
8443             "NULL" in
8444
8445       List.iter (
8446         function
8447         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8448             pr "  const char *%s;\n" n
8449         | OptString n -> pr "  const char *%s;\n" n
8450         | StringList n | DeviceList n ->
8451             pr "  PyObject *py_%s;\n" n;
8452             pr "  char **%s;\n" n
8453         | Bool n -> pr "  int %s;\n" n
8454         | Int n -> pr "  int %s;\n" n
8455         | Int64 n -> pr "  long long %s;\n" n
8456       ) (snd style);
8457
8458       pr "\n";
8459
8460       (* Convert the parameters. *)
8461       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8462       List.iter (
8463         function
8464         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8465         | OptString _ -> pr "z"
8466         | StringList _ | DeviceList _ -> pr "O"
8467         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8468         | Int _ -> pr "i"
8469         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8470                              * emulate C's int/long/long long in Python?
8471                              *)
8472       ) (snd style);
8473       pr ":guestfs_%s\",\n" name;
8474       pr "                         &py_g";
8475       List.iter (
8476         function
8477         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8478         | OptString n -> pr ", &%s" n
8479         | StringList n | DeviceList n -> pr ", &py_%s" n
8480         | Bool n -> pr ", &%s" n
8481         | Int n -> pr ", &%s" n
8482         | Int64 n -> pr ", &%s" n
8483       ) (snd style);
8484
8485       pr "))\n";
8486       pr "    return NULL;\n";
8487
8488       pr "  g = get_handle (py_g);\n";
8489       List.iter (
8490         function
8491         | Pathname _ | Device _ | Dev_or_Path _ | String _
8492         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8493         | StringList n | DeviceList n ->
8494             pr "  %s = get_string_list (py_%s);\n" n n;
8495             pr "  if (!%s) return NULL;\n" n
8496       ) (snd style);
8497
8498       pr "\n";
8499
8500       pr "  r = guestfs_%s " name;
8501       generate_c_call_args ~handle:"g" style;
8502       pr ";\n";
8503
8504       List.iter (
8505         function
8506         | Pathname _ | Device _ | Dev_or_Path _ | String _
8507         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8508         | StringList n | DeviceList n ->
8509             pr "  free (%s);\n" n
8510       ) (snd style);
8511
8512       pr "  if (r == %s) {\n" error_code;
8513       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8514       pr "    return NULL;\n";
8515       pr "  }\n";
8516       pr "\n";
8517
8518       (match fst style with
8519        | RErr ->
8520            pr "  Py_INCREF (Py_None);\n";
8521            pr "  py_r = Py_None;\n"
8522        | RInt _
8523        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8524        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8525        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8526        | RConstOptString _ ->
8527            pr "  if (r)\n";
8528            pr "    py_r = PyString_FromString (r);\n";
8529            pr "  else {\n";
8530            pr "    Py_INCREF (Py_None);\n";
8531            pr "    py_r = Py_None;\n";
8532            pr "  }\n"
8533        | RString _ ->
8534            pr "  py_r = PyString_FromString (r);\n";
8535            pr "  free (r);\n"
8536        | RStringList _ ->
8537            pr "  py_r = put_string_list (r);\n";
8538            pr "  free_strings (r);\n"
8539        | RStruct (_, typ) ->
8540            pr "  py_r = put_%s (r);\n" typ;
8541            pr "  guestfs_free_%s (r);\n" typ
8542        | RStructList (_, typ) ->
8543            pr "  py_r = put_%s_list (r);\n" typ;
8544            pr "  guestfs_free_%s_list (r);\n" typ
8545        | RHashtable n ->
8546            pr "  py_r = put_table (r);\n";
8547            pr "  free_strings (r);\n"
8548        | RBufferOut _ ->
8549            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8550            pr "  free (r);\n"
8551       );
8552
8553       pr "  return py_r;\n";
8554       pr "}\n";
8555       pr "\n"
8556   ) all_functions;
8557
8558   (* Table of functions. *)
8559   pr "static PyMethodDef methods[] = {\n";
8560   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8561   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8562   List.iter (
8563     fun (name, _, _, _, _, _, _) ->
8564       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8565         name name
8566   ) all_functions;
8567   pr "  { NULL, NULL, 0, NULL }\n";
8568   pr "};\n";
8569   pr "\n";
8570
8571   (* Init function. *)
8572   pr "\
8573 void
8574 initlibguestfsmod (void)
8575 {
8576   static int initialized = 0;
8577
8578   if (initialized) return;
8579   Py_InitModule ((char *) \"libguestfsmod\", methods);
8580   initialized = 1;
8581 }
8582 "
8583
8584 (* Generate Python module. *)
8585 and generate_python_py () =
8586   generate_header HashStyle LGPLv2;
8587
8588   pr "\
8589 u\"\"\"Python bindings for libguestfs
8590
8591 import guestfs
8592 g = guestfs.GuestFS ()
8593 g.add_drive (\"guest.img\")
8594 g.launch ()
8595 parts = g.list_partitions ()
8596
8597 The guestfs module provides a Python binding to the libguestfs API
8598 for examining and modifying virtual machine disk images.
8599
8600 Amongst the things this is good for: making batch configuration
8601 changes to guests, getting disk used/free statistics (see also:
8602 virt-df), migrating between virtualization systems (see also:
8603 virt-p2v), performing partial backups, performing partial guest
8604 clones, cloning guests and changing registry/UUID/hostname info, and
8605 much else besides.
8606
8607 Libguestfs uses Linux kernel and qemu code, and can access any type of
8608 guest filesystem that Linux and qemu can, including but not limited
8609 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8610 schemes, qcow, qcow2, vmdk.
8611
8612 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8613 LVs, what filesystem is in each LV, etc.).  It can also run commands
8614 in the context of the guest.  Also you can access filesystems over FTP.
8615
8616 Errors which happen while using the API are turned into Python
8617 RuntimeError exceptions.
8618
8619 To create a guestfs handle you usually have to perform the following
8620 sequence of calls:
8621
8622 # Create the handle, call add_drive at least once, and possibly
8623 # several times if the guest has multiple block devices:
8624 g = guestfs.GuestFS ()
8625 g.add_drive (\"guest.img\")
8626
8627 # Launch the qemu subprocess and wait for it to become ready:
8628 g.launch ()
8629
8630 # Now you can issue commands, for example:
8631 logvols = g.lvs ()
8632
8633 \"\"\"
8634
8635 import libguestfsmod
8636
8637 class GuestFS:
8638     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8639
8640     def __init__ (self):
8641         \"\"\"Create a new libguestfs handle.\"\"\"
8642         self._o = libguestfsmod.create ()
8643
8644     def __del__ (self):
8645         libguestfsmod.close (self._o)
8646
8647 ";
8648
8649   List.iter (
8650     fun (name, style, _, flags, _, _, longdesc) ->
8651       pr "    def %s " name;
8652       generate_py_call_args ~handle:"self" (snd style);
8653       pr ":\n";
8654
8655       if not (List.mem NotInDocs flags) then (
8656         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8657         let doc =
8658           match fst style with
8659           | RErr | RInt _ | RInt64 _ | RBool _
8660           | RConstOptString _ | RConstString _
8661           | RString _ | RBufferOut _ -> doc
8662           | RStringList _ ->
8663               doc ^ "\n\nThis function returns a list of strings."
8664           | RStruct (_, typ) ->
8665               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8666           | RStructList (_, typ) ->
8667               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8668           | RHashtable _ ->
8669               doc ^ "\n\nThis function returns a dictionary." in
8670         let doc =
8671           if List.mem ProtocolLimitWarning flags then
8672             doc ^ "\n\n" ^ protocol_limit_warning
8673           else doc in
8674         let doc =
8675           if List.mem DangerWillRobinson flags then
8676             doc ^ "\n\n" ^ danger_will_robinson
8677           else doc in
8678         let doc =
8679           match deprecation_notice flags with
8680           | None -> doc
8681           | Some txt -> doc ^ "\n\n" ^ txt in
8682         let doc = pod2text ~width:60 name doc in
8683         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8684         let doc = String.concat "\n        " doc in
8685         pr "        u\"\"\"%s\"\"\"\n" doc;
8686       );
8687       pr "        return libguestfsmod.%s " name;
8688       generate_py_call_args ~handle:"self._o" (snd style);
8689       pr "\n";
8690       pr "\n";
8691   ) all_functions
8692
8693 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8694 and generate_py_call_args ~handle args =
8695   pr "(%s" handle;
8696   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8697   pr ")"
8698
8699 (* Useful if you need the longdesc POD text as plain text.  Returns a
8700  * list of lines.
8701  *
8702  * Because this is very slow (the slowest part of autogeneration),
8703  * we memoize the results.
8704  *)
8705 and pod2text ~width name longdesc =
8706   let key = width, name, longdesc in
8707   try Hashtbl.find pod2text_memo key
8708   with Not_found ->
8709     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8710     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8711     close_out chan;
8712     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8713     let chan = open_process_in cmd in
8714     let lines = ref [] in
8715     let rec loop i =
8716       let line = input_line chan in
8717       if i = 1 then             (* discard the first line of output *)
8718         loop (i+1)
8719       else (
8720         let line = triml line in
8721         lines := line :: !lines;
8722         loop (i+1)
8723       ) in
8724     let lines = try loop 1 with End_of_file -> List.rev !lines in
8725     unlink filename;
8726     (match close_process_in chan with
8727      | WEXITED 0 -> ()
8728      | WEXITED i ->
8729          failwithf "pod2text: process exited with non-zero status (%d)" i
8730      | WSIGNALED i | WSTOPPED i ->
8731          failwithf "pod2text: process signalled or stopped by signal %d" i
8732     );
8733     Hashtbl.add pod2text_memo key lines;
8734     pod2text_memo_updated ();
8735     lines
8736
8737 (* Generate ruby bindings. *)
8738 and generate_ruby_c () =
8739   generate_header CStyle LGPLv2;
8740
8741   pr "\
8742 #include <stdio.h>
8743 #include <stdlib.h>
8744
8745 #include <ruby.h>
8746
8747 #include \"guestfs.h\"
8748
8749 #include \"extconf.h\"
8750
8751 /* For Ruby < 1.9 */
8752 #ifndef RARRAY_LEN
8753 #define RARRAY_LEN(r) (RARRAY((r))->len)
8754 #endif
8755
8756 static VALUE m_guestfs;                 /* guestfs module */
8757 static VALUE c_guestfs;                 /* guestfs_h handle */
8758 static VALUE e_Error;                   /* used for all errors */
8759
8760 static void ruby_guestfs_free (void *p)
8761 {
8762   if (!p) return;
8763   guestfs_close ((guestfs_h *) p);
8764 }
8765
8766 static VALUE ruby_guestfs_create (VALUE m)
8767 {
8768   guestfs_h *g;
8769
8770   g = guestfs_create ();
8771   if (!g)
8772     rb_raise (e_Error, \"failed to create guestfs handle\");
8773
8774   /* Don't print error messages to stderr by default. */
8775   guestfs_set_error_handler (g, NULL, NULL);
8776
8777   /* Wrap it, and make sure the close function is called when the
8778    * handle goes away.
8779    */
8780   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8781 }
8782
8783 static VALUE ruby_guestfs_close (VALUE gv)
8784 {
8785   guestfs_h *g;
8786   Data_Get_Struct (gv, guestfs_h, g);
8787
8788   ruby_guestfs_free (g);
8789   DATA_PTR (gv) = NULL;
8790
8791   return Qnil;
8792 }
8793
8794 ";
8795
8796   List.iter (
8797     fun (name, style, _, _, _, _, _) ->
8798       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8799       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8800       pr ")\n";
8801       pr "{\n";
8802       pr "  guestfs_h *g;\n";
8803       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8804       pr "  if (!g)\n";
8805       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8806         name;
8807       pr "\n";
8808
8809       List.iter (
8810         function
8811         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8812             pr "  Check_Type (%sv, T_STRING);\n" n;
8813             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8814             pr "  if (!%s)\n" n;
8815             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8816             pr "              \"%s\", \"%s\");\n" n name
8817         | OptString n ->
8818             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8819         | StringList n | DeviceList n ->
8820             pr "  char **%s;\n" n;
8821             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8822             pr "  {\n";
8823             pr "    int i, len;\n";
8824             pr "    len = RARRAY_LEN (%sv);\n" n;
8825             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8826               n;
8827             pr "    for (i = 0; i < len; ++i) {\n";
8828             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8829             pr "      %s[i] = StringValueCStr (v);\n" n;
8830             pr "    }\n";
8831             pr "    %s[len] = NULL;\n" n;
8832             pr "  }\n";
8833         | Bool n ->
8834             pr "  int %s = RTEST (%sv);\n" n n
8835         | Int n ->
8836             pr "  int %s = NUM2INT (%sv);\n" n n
8837         | Int64 n ->
8838             pr "  long long %s = NUM2LL (%sv);\n" n n
8839       ) (snd style);
8840       pr "\n";
8841
8842       let error_code =
8843         match fst style with
8844         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8845         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8846         | RConstString _ | RConstOptString _ ->
8847             pr "  const char *r;\n"; "NULL"
8848         | RString _ -> pr "  char *r;\n"; "NULL"
8849         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8850         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8851         | RStructList (_, typ) ->
8852             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8853         | RBufferOut _ ->
8854             pr "  char *r;\n";
8855             pr "  size_t size;\n";
8856             "NULL" in
8857       pr "\n";
8858
8859       pr "  r = guestfs_%s " name;
8860       generate_c_call_args ~handle:"g" style;
8861       pr ";\n";
8862
8863       List.iter (
8864         function
8865         | Pathname _ | Device _ | Dev_or_Path _ | String _
8866         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8867         | StringList n | DeviceList n ->
8868             pr "  free (%s);\n" n
8869       ) (snd style);
8870
8871       pr "  if (r == %s)\n" error_code;
8872       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8873       pr "\n";
8874
8875       (match fst style with
8876        | RErr ->
8877            pr "  return Qnil;\n"
8878        | RInt _ | RBool _ ->
8879            pr "  return INT2NUM (r);\n"
8880        | RInt64 _ ->
8881            pr "  return ULL2NUM (r);\n"
8882        | RConstString _ ->
8883            pr "  return rb_str_new2 (r);\n";
8884        | RConstOptString _ ->
8885            pr "  if (r)\n";
8886            pr "    return rb_str_new2 (r);\n";
8887            pr "  else\n";
8888            pr "    return Qnil;\n";
8889        | RString _ ->
8890            pr "  VALUE rv = rb_str_new2 (r);\n";
8891            pr "  free (r);\n";
8892            pr "  return rv;\n";
8893        | RStringList _ ->
8894            pr "  int i, len = 0;\n";
8895            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8896            pr "  VALUE rv = rb_ary_new2 (len);\n";
8897            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8898            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8899            pr "    free (r[i]);\n";
8900            pr "  }\n";
8901            pr "  free (r);\n";
8902            pr "  return rv;\n"
8903        | RStruct (_, typ) ->
8904            let cols = cols_of_struct typ in
8905            generate_ruby_struct_code typ cols
8906        | RStructList (_, typ) ->
8907            let cols = cols_of_struct typ in
8908            generate_ruby_struct_list_code typ cols
8909        | RHashtable _ ->
8910            pr "  VALUE rv = rb_hash_new ();\n";
8911            pr "  int i;\n";
8912            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8913            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8914            pr "    free (r[i]);\n";
8915            pr "    free (r[i+1]);\n";
8916            pr "  }\n";
8917            pr "  free (r);\n";
8918            pr "  return rv;\n"
8919        | RBufferOut _ ->
8920            pr "  VALUE rv = rb_str_new (r, size);\n";
8921            pr "  free (r);\n";
8922            pr "  return rv;\n";
8923       );
8924
8925       pr "}\n";
8926       pr "\n"
8927   ) all_functions;
8928
8929   pr "\
8930 /* Initialize the module. */
8931 void Init__guestfs ()
8932 {
8933   m_guestfs = rb_define_module (\"Guestfs\");
8934   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8935   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8936
8937   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8938   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8939
8940 ";
8941   (* Define the rest of the methods. *)
8942   List.iter (
8943     fun (name, style, _, _, _, _, _) ->
8944       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8945       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8946   ) all_functions;
8947
8948   pr "}\n"
8949
8950 (* Ruby code to return a struct. *)
8951 and generate_ruby_struct_code typ cols =
8952   pr "  VALUE rv = rb_hash_new ();\n";
8953   List.iter (
8954     function
8955     | name, FString ->
8956         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8957     | name, FBuffer ->
8958         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8959     | name, FUUID ->
8960         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8961     | name, (FBytes|FUInt64) ->
8962         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8963     | name, FInt64 ->
8964         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8965     | name, FUInt32 ->
8966         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8967     | name, FInt32 ->
8968         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8969     | name, FOptPercent ->
8970         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8971     | name, FChar -> (* XXX wrong? *)
8972         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8973   ) cols;
8974   pr "  guestfs_free_%s (r);\n" typ;
8975   pr "  return rv;\n"
8976
8977 (* Ruby code to return a struct list. *)
8978 and generate_ruby_struct_list_code typ cols =
8979   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8980   pr "  int i;\n";
8981   pr "  for (i = 0; i < r->len; ++i) {\n";
8982   pr "    VALUE hv = rb_hash_new ();\n";
8983   List.iter (
8984     function
8985     | name, FString ->
8986         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8987     | name, FBuffer ->
8988         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, r->val[i].%s_len));\n" name name name
8989     | name, FUUID ->
8990         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8991     | name, (FBytes|FUInt64) ->
8992         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8993     | name, FInt64 ->
8994         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8995     | name, FUInt32 ->
8996         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8997     | name, FInt32 ->
8998         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8999     | name, FOptPercent ->
9000         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9001     | name, FChar -> (* XXX wrong? *)
9002         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9003   ) cols;
9004   pr "    rb_ary_push (rv, hv);\n";
9005   pr "  }\n";
9006   pr "  guestfs_free_%s_list (r);\n" typ;
9007   pr "  return rv;\n"
9008
9009 (* Generate Java bindings GuestFS.java file. *)
9010 and generate_java_java () =
9011   generate_header CStyle LGPLv2;
9012
9013   pr "\
9014 package com.redhat.et.libguestfs;
9015
9016 import java.util.HashMap;
9017 import com.redhat.et.libguestfs.LibGuestFSException;
9018 import com.redhat.et.libguestfs.PV;
9019 import com.redhat.et.libguestfs.VG;
9020 import com.redhat.et.libguestfs.LV;
9021 import com.redhat.et.libguestfs.Stat;
9022 import com.redhat.et.libguestfs.StatVFS;
9023 import com.redhat.et.libguestfs.IntBool;
9024 import com.redhat.et.libguestfs.Dirent;
9025
9026 /**
9027  * The GuestFS object is a libguestfs handle.
9028  *
9029  * @author rjones
9030  */
9031 public class GuestFS {
9032   // Load the native code.
9033   static {
9034     System.loadLibrary (\"guestfs_jni\");
9035   }
9036
9037   /**
9038    * The native guestfs_h pointer.
9039    */
9040   long g;
9041
9042   /**
9043    * Create a libguestfs handle.
9044    *
9045    * @throws LibGuestFSException
9046    */
9047   public GuestFS () throws LibGuestFSException
9048   {
9049     g = _create ();
9050   }
9051   private native long _create () throws LibGuestFSException;
9052
9053   /**
9054    * Close a libguestfs handle.
9055    *
9056    * You can also leave handles to be collected by the garbage
9057    * collector, but this method ensures that the resources used
9058    * by the handle are freed up immediately.  If you call any
9059    * other methods after closing the handle, you will get an
9060    * exception.
9061    *
9062    * @throws LibGuestFSException
9063    */
9064   public void close () throws LibGuestFSException
9065   {
9066     if (g != 0)
9067       _close (g);
9068     g = 0;
9069   }
9070   private native void _close (long g) throws LibGuestFSException;
9071
9072   public void finalize () throws LibGuestFSException
9073   {
9074     close ();
9075   }
9076
9077 ";
9078
9079   List.iter (
9080     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9081       if not (List.mem NotInDocs flags); then (
9082         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9083         let doc =
9084           if List.mem ProtocolLimitWarning flags then
9085             doc ^ "\n\n" ^ protocol_limit_warning
9086           else doc in
9087         let doc =
9088           if List.mem DangerWillRobinson flags then
9089             doc ^ "\n\n" ^ danger_will_robinson
9090           else doc in
9091         let doc =
9092           match deprecation_notice flags with
9093           | None -> doc
9094           | Some txt -> doc ^ "\n\n" ^ txt in
9095         let doc = pod2text ~width:60 name doc in
9096         let doc = List.map (            (* RHBZ#501883 *)
9097           function
9098           | "" -> "<p>"
9099           | nonempty -> nonempty
9100         ) doc in
9101         let doc = String.concat "\n   * " doc in
9102
9103         pr "  /**\n";
9104         pr "   * %s\n" shortdesc;
9105         pr "   * <p>\n";
9106         pr "   * %s\n" doc;
9107         pr "   * @throws LibGuestFSException\n";
9108         pr "   */\n";
9109         pr "  ";
9110       );
9111       generate_java_prototype ~public:true ~semicolon:false name style;
9112       pr "\n";
9113       pr "  {\n";
9114       pr "    if (g == 0)\n";
9115       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9116         name;
9117       pr "    ";
9118       if fst style <> RErr then pr "return ";
9119       pr "_%s " name;
9120       generate_java_call_args ~handle:"g" (snd style);
9121       pr ";\n";
9122       pr "  }\n";
9123       pr "  ";
9124       generate_java_prototype ~privat:true ~native:true name style;
9125       pr "\n";
9126       pr "\n";
9127   ) all_functions;
9128
9129   pr "}\n"
9130
9131 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9132 and generate_java_call_args ~handle args =
9133   pr "(%s" handle;
9134   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9135   pr ")"
9136
9137 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9138     ?(semicolon=true) name style =
9139   if privat then pr "private ";
9140   if public then pr "public ";
9141   if native then pr "native ";
9142
9143   (* return type *)
9144   (match fst style with
9145    | RErr -> pr "void ";
9146    | RInt _ -> pr "int ";
9147    | RInt64 _ -> pr "long ";
9148    | RBool _ -> pr "boolean ";
9149    | RConstString _ | RConstOptString _ | RString _
9150    | RBufferOut _ -> pr "String ";
9151    | RStringList _ -> pr "String[] ";
9152    | RStruct (_, typ) ->
9153        let name = java_name_of_struct typ in
9154        pr "%s " name;
9155    | RStructList (_, typ) ->
9156        let name = java_name_of_struct typ in
9157        pr "%s[] " name;
9158    | RHashtable _ -> pr "HashMap<String,String> ";
9159   );
9160
9161   if native then pr "_%s " name else pr "%s " name;
9162   pr "(";
9163   let needs_comma = ref false in
9164   if native then (
9165     pr "long g";
9166     needs_comma := true
9167   );
9168
9169   (* args *)
9170   List.iter (
9171     fun arg ->
9172       if !needs_comma then pr ", ";
9173       needs_comma := true;
9174
9175       match arg with
9176       | Pathname n
9177       | Device n | Dev_or_Path n
9178       | String n
9179       | OptString n
9180       | FileIn n
9181       | FileOut n ->
9182           pr "String %s" n
9183       | StringList n | DeviceList n ->
9184           pr "String[] %s" n
9185       | Bool n ->
9186           pr "boolean %s" n
9187       | Int n ->
9188           pr "int %s" n
9189       | Int64 n ->
9190           pr "long %s" n
9191   ) (snd style);
9192
9193   pr ")\n";
9194   pr "    throws LibGuestFSException";
9195   if semicolon then pr ";"
9196
9197 and generate_java_struct jtyp cols =
9198   generate_header CStyle LGPLv2;
9199
9200   pr "\
9201 package com.redhat.et.libguestfs;
9202
9203 /**
9204  * Libguestfs %s structure.
9205  *
9206  * @author rjones
9207  * @see GuestFS
9208  */
9209 public class %s {
9210 " jtyp jtyp;
9211
9212   List.iter (
9213     function
9214     | name, FString
9215     | name, FUUID
9216     | name, FBuffer -> pr "  public String %s;\n" name
9217     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9218     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9219     | name, FChar -> pr "  public char %s;\n" name
9220     | name, FOptPercent ->
9221         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9222         pr "  public float %s;\n" name
9223   ) cols;
9224
9225   pr "}\n"
9226
9227 and generate_java_c () =
9228   generate_header CStyle LGPLv2;
9229
9230   pr "\
9231 #include <stdio.h>
9232 #include <stdlib.h>
9233 #include <string.h>
9234
9235 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9236 #include \"guestfs.h\"
9237
9238 /* Note that this function returns.  The exception is not thrown
9239  * until after the wrapper function returns.
9240  */
9241 static void
9242 throw_exception (JNIEnv *env, const char *msg)
9243 {
9244   jclass cl;
9245   cl = (*env)->FindClass (env,
9246                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9247   (*env)->ThrowNew (env, cl, msg);
9248 }
9249
9250 JNIEXPORT jlong JNICALL
9251 Java_com_redhat_et_libguestfs_GuestFS__1create
9252   (JNIEnv *env, jobject obj)
9253 {
9254   guestfs_h *g;
9255
9256   g = guestfs_create ();
9257   if (g == NULL) {
9258     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9259     return 0;
9260   }
9261   guestfs_set_error_handler (g, NULL, NULL);
9262   return (jlong) (long) g;
9263 }
9264
9265 JNIEXPORT void JNICALL
9266 Java_com_redhat_et_libguestfs_GuestFS__1close
9267   (JNIEnv *env, jobject obj, jlong jg)
9268 {
9269   guestfs_h *g = (guestfs_h *) (long) jg;
9270   guestfs_close (g);
9271 }
9272
9273 ";
9274
9275   List.iter (
9276     fun (name, style, _, _, _, _, _) ->
9277       pr "JNIEXPORT ";
9278       (match fst style with
9279        | RErr -> pr "void ";
9280        | RInt _ -> pr "jint ";
9281        | RInt64 _ -> pr "jlong ";
9282        | RBool _ -> pr "jboolean ";
9283        | RConstString _ | RConstOptString _ | RString _
9284        | RBufferOut _ -> pr "jstring ";
9285        | RStruct _ | RHashtable _ ->
9286            pr "jobject ";
9287        | RStringList _ | RStructList _ ->
9288            pr "jobjectArray ";
9289       );
9290       pr "JNICALL\n";
9291       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9292       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9293       pr "\n";
9294       pr "  (JNIEnv *env, jobject obj, jlong jg";
9295       List.iter (
9296         function
9297         | Pathname n
9298         | Device n | Dev_or_Path n
9299         | String n
9300         | OptString n
9301         | FileIn n
9302         | FileOut n ->
9303             pr ", jstring j%s" n
9304         | StringList n | DeviceList n ->
9305             pr ", jobjectArray j%s" n
9306         | Bool n ->
9307             pr ", jboolean j%s" n
9308         | Int n ->
9309             pr ", jint j%s" n
9310         | Int64 n ->
9311             pr ", jlong j%s" n
9312       ) (snd style);
9313       pr ")\n";
9314       pr "{\n";
9315       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9316       let error_code, no_ret =
9317         match fst style with
9318         | RErr -> pr "  int r;\n"; "-1", ""
9319         | RBool _
9320         | RInt _ -> pr "  int r;\n"; "-1", "0"
9321         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9322         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9323         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9324         | RString _ ->
9325             pr "  jstring jr;\n";
9326             pr "  char *r;\n"; "NULL", "NULL"
9327         | RStringList _ ->
9328             pr "  jobjectArray jr;\n";
9329             pr "  int r_len;\n";
9330             pr "  jclass cl;\n";
9331             pr "  jstring jstr;\n";
9332             pr "  char **r;\n"; "NULL", "NULL"
9333         | RStruct (_, typ) ->
9334             pr "  jobject jr;\n";
9335             pr "  jclass cl;\n";
9336             pr "  jfieldID fl;\n";
9337             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9338         | RStructList (_, typ) ->
9339             pr "  jobjectArray jr;\n";
9340             pr "  jclass cl;\n";
9341             pr "  jfieldID fl;\n";
9342             pr "  jobject jfl;\n";
9343             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9344         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9345         | RBufferOut _ ->
9346             pr "  jstring jr;\n";
9347             pr "  char *r;\n";
9348             pr "  size_t size;\n";
9349             "NULL", "NULL" in
9350       List.iter (
9351         function
9352         | Pathname n
9353         | Device n | Dev_or_Path n
9354         | String n
9355         | OptString n
9356         | FileIn n
9357         | FileOut n ->
9358             pr "  const char *%s;\n" n
9359         | StringList n | DeviceList n ->
9360             pr "  int %s_len;\n" n;
9361             pr "  const char **%s;\n" n
9362         | Bool n
9363         | Int n ->
9364             pr "  int %s;\n" n
9365         | Int64 n ->
9366             pr "  int64_t %s;\n" n
9367       ) (snd style);
9368
9369       let needs_i =
9370         (match fst style with
9371          | RStringList _ | RStructList _ -> true
9372          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9373          | RConstOptString _
9374          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9375           List.exists (function
9376                        | StringList _ -> true
9377                        | DeviceList _ -> true
9378                        | _ -> false) (snd style) in
9379       if needs_i then
9380         pr "  int i;\n";
9381
9382       pr "\n";
9383
9384       (* Get the parameters. *)
9385       List.iter (
9386         function
9387         | Pathname n
9388         | Device n | Dev_or_Path n
9389         | String n
9390         | FileIn n
9391         | FileOut n ->
9392             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9393         | OptString n ->
9394             (* This is completely undocumented, but Java null becomes
9395              * a NULL parameter.
9396              *)
9397             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9398         | StringList n | DeviceList n ->
9399             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9400             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9401             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9402             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9403               n;
9404             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9405             pr "  }\n";
9406             pr "  %s[%s_len] = NULL;\n" n n;
9407         | Bool n
9408         | Int n
9409         | Int64 n ->
9410             pr "  %s = j%s;\n" n n
9411       ) (snd style);
9412
9413       (* Make the call. *)
9414       pr "  r = guestfs_%s " name;
9415       generate_c_call_args ~handle:"g" style;
9416       pr ";\n";
9417
9418       (* Release the parameters. *)
9419       List.iter (
9420         function
9421         | Pathname n
9422         | Device n | Dev_or_Path n
9423         | String n
9424         | FileIn n
9425         | FileOut n ->
9426             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9427         | OptString n ->
9428             pr "  if (j%s)\n" n;
9429             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9430         | StringList n | DeviceList n ->
9431             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9432             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9433               n;
9434             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9435             pr "  }\n";
9436             pr "  free (%s);\n" n
9437         | Bool n
9438         | Int n
9439         | Int64 n -> ()
9440       ) (snd style);
9441
9442       (* Check for errors. *)
9443       pr "  if (r == %s) {\n" error_code;
9444       pr "    throw_exception (env, guestfs_last_error (g));\n";
9445       pr "    return %s;\n" no_ret;
9446       pr "  }\n";
9447
9448       (* Return value. *)
9449       (match fst style with
9450        | RErr -> ()
9451        | RInt _ -> pr "  return (jint) r;\n"
9452        | RBool _ -> pr "  return (jboolean) r;\n"
9453        | RInt64 _ -> pr "  return (jlong) r;\n"
9454        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9455        | RConstOptString _ ->
9456            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9457        | RString _ ->
9458            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9459            pr "  free (r);\n";
9460            pr "  return jr;\n"
9461        | RStringList _ ->
9462            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9463            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9464            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9465            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9466            pr "  for (i = 0; i < r_len; ++i) {\n";
9467            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9468            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9469            pr "    free (r[i]);\n";
9470            pr "  }\n";
9471            pr "  free (r);\n";
9472            pr "  return jr;\n"
9473        | RStruct (_, typ) ->
9474            let jtyp = java_name_of_struct typ in
9475            let cols = cols_of_struct typ in
9476            generate_java_struct_return typ jtyp cols
9477        | RStructList (_, typ) ->
9478            let jtyp = java_name_of_struct typ in
9479            let cols = cols_of_struct typ in
9480            generate_java_struct_list_return typ jtyp cols
9481        | RHashtable _ ->
9482            (* XXX *)
9483            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9484            pr "  return NULL;\n"
9485        | RBufferOut _ ->
9486            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9487            pr "  free (r);\n";
9488            pr "  return jr;\n"
9489       );
9490
9491       pr "}\n";
9492       pr "\n"
9493   ) all_functions
9494
9495 and generate_java_struct_return typ jtyp cols =
9496   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9497   pr "  jr = (*env)->AllocObject (env, cl);\n";
9498   List.iter (
9499     function
9500     | name, FString ->
9501         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9502         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9503     | name, FUUID ->
9504         pr "  {\n";
9505         pr "    char s[33];\n";
9506         pr "    memcpy (s, r->%s, 32);\n" name;
9507         pr "    s[32] = 0;\n";
9508         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9509         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9510         pr "  }\n";
9511     | name, FBuffer ->
9512         pr "  {\n";
9513         pr "    int len = r->%s_len;\n" name;
9514         pr "    char s[len+1];\n";
9515         pr "    memcpy (s, r->%s, len);\n" name;
9516         pr "    s[len] = 0;\n";
9517         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9518         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9519         pr "  }\n";
9520     | name, (FBytes|FUInt64|FInt64) ->
9521         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9522         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9523     | name, (FUInt32|FInt32) ->
9524         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9525         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9526     | name, FOptPercent ->
9527         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9528         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9529     | name, FChar ->
9530         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9531         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9532   ) cols;
9533   pr "  free (r);\n";
9534   pr "  return jr;\n"
9535
9536 and generate_java_struct_list_return typ jtyp cols =
9537   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9538   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9539   pr "  for (i = 0; i < r->len; ++i) {\n";
9540   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9541   List.iter (
9542     function
9543     | name, FString ->
9544         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9545         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9546     | name, FUUID ->
9547         pr "    {\n";
9548         pr "      char s[33];\n";
9549         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9550         pr "      s[32] = 0;\n";
9551         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9552         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9553         pr "    }\n";
9554     | name, FBuffer ->
9555         pr "    {\n";
9556         pr "      int len = r->val[i].%s_len;\n" name;
9557         pr "      char s[len+1];\n";
9558         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9559         pr "      s[len] = 0;\n";
9560         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9561         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9562         pr "    }\n";
9563     | name, (FBytes|FUInt64|FInt64) ->
9564         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9565         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9566     | name, (FUInt32|FInt32) ->
9567         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9568         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9569     | name, FOptPercent ->
9570         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9571         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9572     | name, FChar ->
9573         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9574         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9575   ) cols;
9576   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9577   pr "  }\n";
9578   pr "  guestfs_free_%s_list (r);\n" typ;
9579   pr "  return jr;\n"
9580
9581 and generate_java_makefile_inc () =
9582   generate_header HashStyle GPLv2;
9583
9584   pr "java_built_sources = \\\n";
9585   List.iter (
9586     fun (typ, jtyp) ->
9587         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9588   ) java_structs;
9589   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9590
9591 and generate_haskell_hs () =
9592   generate_header HaskellStyle LGPLv2;
9593
9594   (* XXX We only know how to generate partial FFI for Haskell
9595    * at the moment.  Please help out!
9596    *)
9597   let can_generate style =
9598     match style with
9599     | RErr, _
9600     | RInt _, _
9601     | RInt64 _, _ -> true
9602     | RBool _, _
9603     | RConstString _, _
9604     | RConstOptString _, _
9605     | RString _, _
9606     | RStringList _, _
9607     | RStruct _, _
9608     | RStructList _, _
9609     | RHashtable _, _
9610     | RBufferOut _, _ -> false in
9611
9612   pr "\
9613 {-# INCLUDE <guestfs.h> #-}
9614 {-# LANGUAGE ForeignFunctionInterface #-}
9615
9616 module Guestfs (
9617   create";
9618
9619   (* List out the names of the actions we want to export. *)
9620   List.iter (
9621     fun (name, style, _, _, _, _, _) ->
9622       if can_generate style then pr ",\n  %s" name
9623   ) all_functions;
9624
9625   pr "
9626   ) where
9627
9628 -- Unfortunately some symbols duplicate ones already present
9629 -- in Prelude.  We don't know which, so we hard-code a list
9630 -- here.
9631 import Prelude hiding (truncate)
9632
9633 import Foreign
9634 import Foreign.C
9635 import Foreign.C.Types
9636 import IO
9637 import Control.Exception
9638 import Data.Typeable
9639
9640 data GuestfsS = GuestfsS            -- represents the opaque C struct
9641 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9642 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9643
9644 -- XXX define properly later XXX
9645 data PV = PV
9646 data VG = VG
9647 data LV = LV
9648 data IntBool = IntBool
9649 data Stat = Stat
9650 data StatVFS = StatVFS
9651 data Hashtable = Hashtable
9652
9653 foreign import ccall unsafe \"guestfs_create\" c_create
9654   :: IO GuestfsP
9655 foreign import ccall unsafe \"&guestfs_close\" c_close
9656   :: FunPtr (GuestfsP -> IO ())
9657 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9658   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9659
9660 create :: IO GuestfsH
9661 create = do
9662   p <- c_create
9663   c_set_error_handler p nullPtr nullPtr
9664   h <- newForeignPtr c_close p
9665   return h
9666
9667 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9668   :: GuestfsP -> IO CString
9669
9670 -- last_error :: GuestfsH -> IO (Maybe String)
9671 -- last_error h = do
9672 --   str <- withForeignPtr h (\\p -> c_last_error p)
9673 --   maybePeek peekCString str
9674
9675 last_error :: GuestfsH -> IO (String)
9676 last_error h = do
9677   str <- withForeignPtr h (\\p -> c_last_error p)
9678   if (str == nullPtr)
9679     then return \"no error\"
9680     else peekCString str
9681
9682 ";
9683
9684   (* Generate wrappers for each foreign function. *)
9685   List.iter (
9686     fun (name, style, _, _, _, _, _) ->
9687       if can_generate style then (
9688         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9689         pr "  :: ";
9690         generate_haskell_prototype ~handle:"GuestfsP" style;
9691         pr "\n";
9692         pr "\n";
9693         pr "%s :: " name;
9694         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9695         pr "\n";
9696         pr "%s %s = do\n" name
9697           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9698         pr "  r <- ";
9699         (* Convert pointer arguments using with* functions. *)
9700         List.iter (
9701           function
9702           | FileIn n
9703           | FileOut n
9704           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9705           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9706           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9707           | Bool _ | Int _ | Int64 _ -> ()
9708         ) (snd style);
9709         (* Convert integer arguments. *)
9710         let args =
9711           List.map (
9712             function
9713             | Bool n -> sprintf "(fromBool %s)" n
9714             | Int n -> sprintf "(fromIntegral %s)" n
9715             | Int64 n -> sprintf "(fromIntegral %s)" n
9716             | FileIn n | FileOut n
9717             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9718           ) (snd style) in
9719         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9720           (String.concat " " ("p" :: args));
9721         (match fst style with
9722          | RErr | RInt _ | RInt64 _ | RBool _ ->
9723              pr "  if (r == -1)\n";
9724              pr "    then do\n";
9725              pr "      err <- last_error h\n";
9726              pr "      fail err\n";
9727          | RConstString _ | RConstOptString _ | RString _
9728          | RStringList _ | RStruct _
9729          | RStructList _ | RHashtable _ | RBufferOut _ ->
9730              pr "  if (r == nullPtr)\n";
9731              pr "    then do\n";
9732              pr "      err <- last_error h\n";
9733              pr "      fail err\n";
9734         );
9735         (match fst style with
9736          | RErr ->
9737              pr "    else return ()\n"
9738          | RInt _ ->
9739              pr "    else return (fromIntegral r)\n"
9740          | RInt64 _ ->
9741              pr "    else return (fromIntegral r)\n"
9742          | RBool _ ->
9743              pr "    else return (toBool r)\n"
9744          | RConstString _
9745          | RConstOptString _
9746          | RString _
9747          | RStringList _
9748          | RStruct _
9749          | RStructList _
9750          | RHashtable _
9751          | RBufferOut _ ->
9752              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9753         );
9754         pr "\n";
9755       )
9756   ) all_functions
9757
9758 and generate_haskell_prototype ~handle ?(hs = false) style =
9759   pr "%s -> " handle;
9760   let string = if hs then "String" else "CString" in
9761   let int = if hs then "Int" else "CInt" in
9762   let bool = if hs then "Bool" else "CInt" in
9763   let int64 = if hs then "Integer" else "Int64" in
9764   List.iter (
9765     fun arg ->
9766       (match arg with
9767        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9768        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9769        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9770        | Bool _ -> pr "%s" bool
9771        | Int _ -> pr "%s" int
9772        | Int64 _ -> pr "%s" int
9773        | FileIn _ -> pr "%s" string
9774        | FileOut _ -> pr "%s" string
9775       );
9776       pr " -> ";
9777   ) (snd style);
9778   pr "IO (";
9779   (match fst style with
9780    | RErr -> if not hs then pr "CInt"
9781    | RInt _ -> pr "%s" int
9782    | RInt64 _ -> pr "%s" int64
9783    | RBool _ -> pr "%s" bool
9784    | RConstString _ -> pr "%s" string
9785    | RConstOptString _ -> pr "Maybe %s" string
9786    | RString _ -> pr "%s" string
9787    | RStringList _ -> pr "[%s]" string
9788    | RStruct (_, typ) ->
9789        let name = java_name_of_struct typ in
9790        pr "%s" name
9791    | RStructList (_, typ) ->
9792        let name = java_name_of_struct typ in
9793        pr "[%s]" name
9794    | RHashtable _ -> pr "Hashtable"
9795    | RBufferOut _ -> pr "%s" string
9796   );
9797   pr ")"
9798
9799 and generate_bindtests () =
9800   generate_header CStyle LGPLv2;
9801
9802   pr "\
9803 #include <stdio.h>
9804 #include <stdlib.h>
9805 #include <inttypes.h>
9806 #include <string.h>
9807
9808 #include \"guestfs.h\"
9809 #include \"guestfs-internal.h\"
9810 #include \"guestfs-internal-actions.h\"
9811 #include \"guestfs_protocol.h\"
9812
9813 #define error guestfs_error
9814 #define safe_calloc guestfs_safe_calloc
9815 #define safe_malloc guestfs_safe_malloc
9816
9817 static void
9818 print_strings (char *const *argv)
9819 {
9820   int argc;
9821
9822   printf (\"[\");
9823   for (argc = 0; argv[argc] != NULL; ++argc) {
9824     if (argc > 0) printf (\", \");
9825     printf (\"\\\"%%s\\\"\", argv[argc]);
9826   }
9827   printf (\"]\\n\");
9828 }
9829
9830 /* The test0 function prints its parameters to stdout. */
9831 ";
9832
9833   let test0, tests =
9834     match test_functions with
9835     | [] -> assert false
9836     | test0 :: tests -> test0, tests in
9837
9838   let () =
9839     let (name, style, _, _, _, _, _) = test0 in
9840     generate_prototype ~extern:false ~semicolon:false ~newline:true
9841       ~handle:"g" ~prefix:"guestfs__" name style;
9842     pr "{\n";
9843     List.iter (
9844       function
9845       | Pathname n
9846       | Device n | Dev_or_Path n
9847       | String n
9848       | FileIn n
9849       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9850       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9851       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9852       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9853       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9854       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9855     ) (snd style);
9856     pr "  /* Java changes stdout line buffering so we need this: */\n";
9857     pr "  fflush (stdout);\n";
9858     pr "  return 0;\n";
9859     pr "}\n";
9860     pr "\n" in
9861
9862   List.iter (
9863     fun (name, style, _, _, _, _, _) ->
9864       if String.sub name (String.length name - 3) 3 <> "err" then (
9865         pr "/* Test normal return. */\n";
9866         generate_prototype ~extern:false ~semicolon:false ~newline:true
9867           ~handle:"g" ~prefix:"guestfs__" name style;
9868         pr "{\n";
9869         (match fst style with
9870          | RErr ->
9871              pr "  return 0;\n"
9872          | RInt _ ->
9873              pr "  int r;\n";
9874              pr "  sscanf (val, \"%%d\", &r);\n";
9875              pr "  return r;\n"
9876          | RInt64 _ ->
9877              pr "  int64_t r;\n";
9878              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9879              pr "  return r;\n"
9880          | RBool _ ->
9881              pr "  return STREQ (val, \"true\");\n"
9882          | RConstString _
9883          | RConstOptString _ ->
9884              (* Can't return the input string here.  Return a static
9885               * string so we ensure we get a segfault if the caller
9886               * tries to free it.
9887               *)
9888              pr "  return \"static string\";\n"
9889          | RString _ ->
9890              pr "  return strdup (val);\n"
9891          | RStringList _ ->
9892              pr "  char **strs;\n";
9893              pr "  int n, i;\n";
9894              pr "  sscanf (val, \"%%d\", &n);\n";
9895              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9896              pr "  for (i = 0; i < n; ++i) {\n";
9897              pr "    strs[i] = safe_malloc (g, 16);\n";
9898              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9899              pr "  }\n";
9900              pr "  strs[n] = NULL;\n";
9901              pr "  return strs;\n"
9902          | RStruct (_, typ) ->
9903              pr "  struct guestfs_%s *r;\n" typ;
9904              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9905              pr "  return r;\n"
9906          | RStructList (_, typ) ->
9907              pr "  struct guestfs_%s_list *r;\n" typ;
9908              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9909              pr "  sscanf (val, \"%%d\", &r->len);\n";
9910              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9911              pr "  return r;\n"
9912          | RHashtable _ ->
9913              pr "  char **strs;\n";
9914              pr "  int n, i;\n";
9915              pr "  sscanf (val, \"%%d\", &n);\n";
9916              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9917              pr "  for (i = 0; i < n; ++i) {\n";
9918              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9919              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9920              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9921              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9922              pr "  }\n";
9923              pr "  strs[n*2] = NULL;\n";
9924              pr "  return strs;\n"
9925          | RBufferOut _ ->
9926              pr "  return strdup (val);\n"
9927         );
9928         pr "}\n";
9929         pr "\n"
9930       ) else (
9931         pr "/* Test error return. */\n";
9932         generate_prototype ~extern:false ~semicolon:false ~newline:true
9933           ~handle:"g" ~prefix:"guestfs__" name style;
9934         pr "{\n";
9935         pr "  error (g, \"error\");\n";
9936         (match fst style with
9937          | RErr | RInt _ | RInt64 _ | RBool _ ->
9938              pr "  return -1;\n"
9939          | RConstString _ | RConstOptString _
9940          | RString _ | RStringList _ | RStruct _
9941          | RStructList _
9942          | RHashtable _
9943          | RBufferOut _ ->
9944              pr "  return NULL;\n"
9945         );
9946         pr "}\n";
9947         pr "\n"
9948       )
9949   ) tests
9950
9951 and generate_ocaml_bindtests () =
9952   generate_header OCamlStyle GPLv2;
9953
9954   pr "\
9955 let () =
9956   let g = Guestfs.create () in
9957 ";
9958
9959   let mkargs args =
9960     String.concat " " (
9961       List.map (
9962         function
9963         | CallString s -> "\"" ^ s ^ "\""
9964         | CallOptString None -> "None"
9965         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9966         | CallStringList xs ->
9967             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9968         | CallInt i when i >= 0 -> string_of_int i
9969         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9970         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9971         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9972         | CallBool b -> string_of_bool b
9973       ) args
9974     )
9975   in
9976
9977   generate_lang_bindtests (
9978     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9979   );
9980
9981   pr "print_endline \"EOF\"\n"
9982
9983 and generate_perl_bindtests () =
9984   pr "#!/usr/bin/perl -w\n";
9985   generate_header HashStyle GPLv2;
9986
9987   pr "\
9988 use strict;
9989
9990 use Sys::Guestfs;
9991
9992 my $g = Sys::Guestfs->new ();
9993 ";
9994
9995   let mkargs args =
9996     String.concat ", " (
9997       List.map (
9998         function
9999         | CallString s -> "\"" ^ s ^ "\""
10000         | CallOptString None -> "undef"
10001         | CallOptString (Some s) -> sprintf "\"%s\"" s
10002         | CallStringList xs ->
10003             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10004         | CallInt i -> string_of_int i
10005         | CallInt64 i -> Int64.to_string i
10006         | CallBool b -> if b then "1" else "0"
10007       ) args
10008     )
10009   in
10010
10011   generate_lang_bindtests (
10012     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10013   );
10014
10015   pr "print \"EOF\\n\"\n"
10016
10017 and generate_python_bindtests () =
10018   generate_header HashStyle GPLv2;
10019
10020   pr "\
10021 import guestfs
10022
10023 g = guestfs.GuestFS ()
10024 ";
10025
10026   let mkargs args =
10027     String.concat ", " (
10028       List.map (
10029         function
10030         | CallString s -> "\"" ^ s ^ "\""
10031         | CallOptString None -> "None"
10032         | CallOptString (Some s) -> sprintf "\"%s\"" s
10033         | CallStringList xs ->
10034             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10035         | CallInt i -> string_of_int i
10036         | CallInt64 i -> Int64.to_string i
10037         | CallBool b -> if b then "1" else "0"
10038       ) args
10039     )
10040   in
10041
10042   generate_lang_bindtests (
10043     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10044   );
10045
10046   pr "print \"EOF\"\n"
10047
10048 and generate_ruby_bindtests () =
10049   generate_header HashStyle GPLv2;
10050
10051   pr "\
10052 require 'guestfs'
10053
10054 g = Guestfs::create()
10055 ";
10056
10057   let mkargs args =
10058     String.concat ", " (
10059       List.map (
10060         function
10061         | CallString s -> "\"" ^ s ^ "\""
10062         | CallOptString None -> "nil"
10063         | CallOptString (Some s) -> sprintf "\"%s\"" s
10064         | CallStringList xs ->
10065             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10066         | CallInt i -> string_of_int i
10067         | CallInt64 i -> Int64.to_string i
10068         | CallBool b -> string_of_bool b
10069       ) args
10070     )
10071   in
10072
10073   generate_lang_bindtests (
10074     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10075   );
10076
10077   pr "print \"EOF\\n\"\n"
10078
10079 and generate_java_bindtests () =
10080   generate_header CStyle GPLv2;
10081
10082   pr "\
10083 import com.redhat.et.libguestfs.*;
10084
10085 public class Bindtests {
10086     public static void main (String[] argv)
10087     {
10088         try {
10089             GuestFS g = new GuestFS ();
10090 ";
10091
10092   let mkargs args =
10093     String.concat ", " (
10094       List.map (
10095         function
10096         | CallString s -> "\"" ^ s ^ "\""
10097         | CallOptString None -> "null"
10098         | CallOptString (Some s) -> sprintf "\"%s\"" s
10099         | CallStringList xs ->
10100             "new String[]{" ^
10101               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10102         | CallInt i -> string_of_int i
10103         | CallInt64 i -> Int64.to_string i
10104         | CallBool b -> string_of_bool b
10105       ) args
10106     )
10107   in
10108
10109   generate_lang_bindtests (
10110     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10111   );
10112
10113   pr "
10114             System.out.println (\"EOF\");
10115         }
10116         catch (Exception exn) {
10117             System.err.println (exn);
10118             System.exit (1);
10119         }
10120     }
10121 }
10122 "
10123
10124 and generate_haskell_bindtests () =
10125   generate_header HaskellStyle GPLv2;
10126
10127   pr "\
10128 module Bindtests where
10129 import qualified Guestfs
10130
10131 main = do
10132   g <- Guestfs.create
10133 ";
10134
10135   let mkargs args =
10136     String.concat " " (
10137       List.map (
10138         function
10139         | CallString s -> "\"" ^ s ^ "\""
10140         | CallOptString None -> "Nothing"
10141         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10142         | CallStringList xs ->
10143             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10144         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10145         | CallInt i -> string_of_int i
10146         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10147         | CallInt64 i -> Int64.to_string i
10148         | CallBool true -> "True"
10149         | CallBool false -> "False"
10150       ) args
10151     )
10152   in
10153
10154   generate_lang_bindtests (
10155     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10156   );
10157
10158   pr "  putStrLn \"EOF\"\n"
10159
10160 (* Language-independent bindings tests - we do it this way to
10161  * ensure there is parity in testing bindings across all languages.
10162  *)
10163 and generate_lang_bindtests call =
10164   call "test0" [CallString "abc"; CallOptString (Some "def");
10165                 CallStringList []; CallBool false;
10166                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10167   call "test0" [CallString "abc"; CallOptString None;
10168                 CallStringList []; CallBool false;
10169                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10170   call "test0" [CallString ""; CallOptString (Some "def");
10171                 CallStringList []; CallBool false;
10172                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10173   call "test0" [CallString ""; CallOptString (Some "");
10174                 CallStringList []; CallBool false;
10175                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10176   call "test0" [CallString "abc"; CallOptString (Some "def");
10177                 CallStringList ["1"]; CallBool false;
10178                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10179   call "test0" [CallString "abc"; CallOptString (Some "def");
10180                 CallStringList ["1"; "2"]; CallBool false;
10181                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10182   call "test0" [CallString "abc"; CallOptString (Some "def");
10183                 CallStringList ["1"]; CallBool true;
10184                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10185   call "test0" [CallString "abc"; CallOptString (Some "def");
10186                 CallStringList ["1"]; CallBool false;
10187                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10188   call "test0" [CallString "abc"; CallOptString (Some "def");
10189                 CallStringList ["1"]; CallBool false;
10190                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10191   call "test0" [CallString "abc"; CallOptString (Some "def");
10192                 CallStringList ["1"]; CallBool false;
10193                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10194   call "test0" [CallString "abc"; CallOptString (Some "def");
10195                 CallStringList ["1"]; CallBool false;
10196                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10197   call "test0" [CallString "abc"; CallOptString (Some "def");
10198                 CallStringList ["1"]; CallBool false;
10199                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10200   call "test0" [CallString "abc"; CallOptString (Some "def");
10201                 CallStringList ["1"]; CallBool false;
10202                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10203
10204 (* XXX Add here tests of the return and error functions. *)
10205
10206 (* This is used to generate the src/MAX_PROC_NR file which
10207  * contains the maximum procedure number, a surrogate for the
10208  * ABI version number.  See src/Makefile.am for the details.
10209  *)
10210 and generate_max_proc_nr () =
10211   let proc_nrs = List.map (
10212     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10213   ) daemon_functions in
10214
10215   let max_proc_nr = List.fold_left max 0 proc_nrs in
10216
10217   pr "%d\n" max_proc_nr
10218
10219 let output_to filename =
10220   let filename_new = filename ^ ".new" in
10221   chan := open_out filename_new;
10222   let close () =
10223     close_out !chan;
10224     chan := Pervasives.stdout;
10225
10226     (* Is the new file different from the current file? *)
10227     if Sys.file_exists filename && files_equal filename filename_new then
10228       unlink filename_new               (* same, so skip it *)
10229     else (
10230       (* different, overwrite old one *)
10231       (try chmod filename 0o644 with Unix_error _ -> ());
10232       rename filename_new filename;
10233       chmod filename 0o444;
10234       printf "written %s\n%!" filename;
10235     )
10236   in
10237   close
10238
10239 let perror msg = function
10240   | Unix_error (err, _, _) ->
10241       eprintf "%s: %s\n" msg (error_message err)
10242   | exn ->
10243       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10244
10245 (* Main program. *)
10246 let () =
10247   let lock_fd =
10248     try openfile "HACKING" [O_RDWR] 0
10249     with
10250     | Unix_error (ENOENT, _, _) ->
10251         eprintf "\
10252 You are probably running this from the wrong directory.
10253 Run it from the top source directory using the command
10254   src/generator.ml
10255 ";
10256         exit 1
10257     | exn ->
10258         perror "open: HACKING" exn;
10259         exit 1 in
10260
10261   (* Acquire a lock so parallel builds won't try to run the generator
10262    * twice at the same time.  Subsequent builds will wait for the first
10263    * one to finish.  Note the lock is released implicitly when the
10264    * program exits.
10265    *)
10266   (try lockf lock_fd F_LOCK 1
10267    with exn ->
10268      perror "lock: HACKING" exn;
10269      exit 1);
10270
10271   check_functions ();
10272
10273   let close = output_to "src/guestfs_protocol.x" in
10274   generate_xdr ();
10275   close ();
10276
10277   let close = output_to "src/guestfs-structs.h" in
10278   generate_structs_h ();
10279   close ();
10280
10281   let close = output_to "src/guestfs-actions.h" in
10282   generate_actions_h ();
10283   close ();
10284
10285   let close = output_to "src/guestfs-internal-actions.h" in
10286   generate_internal_actions_h ();
10287   close ();
10288
10289   let close = output_to "src/guestfs-actions.c" in
10290   generate_client_actions ();
10291   close ();
10292
10293   let close = output_to "daemon/actions.h" in
10294   generate_daemon_actions_h ();
10295   close ();
10296
10297   let close = output_to "daemon/stubs.c" in
10298   generate_daemon_actions ();
10299   close ();
10300
10301   let close = output_to "daemon/names.c" in
10302   generate_daemon_names ();
10303   close ();
10304
10305   let close = output_to "capitests/tests.c" in
10306   generate_tests ();
10307   close ();
10308
10309   let close = output_to "src/guestfs-bindtests.c" in
10310   generate_bindtests ();
10311   close ();
10312
10313   let close = output_to "fish/cmds.c" in
10314   generate_fish_cmds ();
10315   close ();
10316
10317   let close = output_to "fish/completion.c" in
10318   generate_fish_completion ();
10319   close ();
10320
10321   let close = output_to "guestfs-structs.pod" in
10322   generate_structs_pod ();
10323   close ();
10324
10325   let close = output_to "guestfs-actions.pod" in
10326   generate_actions_pod ();
10327   close ();
10328
10329   let close = output_to "guestfish-actions.pod" in
10330   generate_fish_actions_pod ();
10331   close ();
10332
10333   let close = output_to "ocaml/guestfs.mli" in
10334   generate_ocaml_mli ();
10335   close ();
10336
10337   let close = output_to "ocaml/guestfs.ml" in
10338   generate_ocaml_ml ();
10339   close ();
10340
10341   let close = output_to "ocaml/guestfs_c_actions.c" in
10342   generate_ocaml_c ();
10343   close ();
10344
10345   let close = output_to "ocaml/bindtests.ml" in
10346   generate_ocaml_bindtests ();
10347   close ();
10348
10349   let close = output_to "perl/Guestfs.xs" in
10350   generate_perl_xs ();
10351   close ();
10352
10353   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10354   generate_perl_pm ();
10355   close ();
10356
10357   let close = output_to "perl/bindtests.pl" in
10358   generate_perl_bindtests ();
10359   close ();
10360
10361   let close = output_to "python/guestfs-py.c" in
10362   generate_python_c ();
10363   close ();
10364
10365   let close = output_to "python/guestfs.py" in
10366   generate_python_py ();
10367   close ();
10368
10369   let close = output_to "python/bindtests.py" in
10370   generate_python_bindtests ();
10371   close ();
10372
10373   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10374   generate_ruby_c ();
10375   close ();
10376
10377   let close = output_to "ruby/bindtests.rb" in
10378   generate_ruby_bindtests ();
10379   close ();
10380
10381   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10382   generate_java_java ();
10383   close ();
10384
10385   List.iter (
10386     fun (typ, jtyp) ->
10387       let cols = cols_of_struct typ in
10388       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10389       let close = output_to filename in
10390       generate_java_struct jtyp cols;
10391       close ();
10392   ) java_structs;
10393
10394   let close = output_to "java/Makefile.inc" in
10395   generate_java_makefile_inc ();
10396   close ();
10397
10398   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10399   generate_java_c ();
10400   close ();
10401
10402   let close = output_to "java/Bindtests.java" in
10403   generate_java_bindtests ();
10404   close ();
10405
10406   let close = output_to "haskell/Guestfs.hs" in
10407   generate_haskell_hs ();
10408   close ();
10409
10410   let close = output_to "haskell/Bindtests.hs" in
10411   generate_haskell_bindtests ();
10412   close ();
10413
10414   let close = output_to "src/MAX_PROC_NR" in
10415   generate_max_proc_nr ();
10416   close ();
10417
10418   (* Always generate this file last, and unconditionally.  It's used
10419    * by the Makefile to know when we must re-run the generator.
10420    *)
10421   let chan = open_out "src/stamp-generator" in
10422   fprintf chan "1\n";
10423   close_out chan