1206be22fbd81323511f803dccd848bf65f3e2fa
[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   | Optional of string    (* function is part of an optional group *)
179
180 (* You can supply zero or as many tests as you want per API call.
181  *
182  * Note that the test environment has 3 block devices, of size 500MB,
183  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
184  * a fourth ISO block device with some known files on it (/dev/sdd).
185  *
186  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
187  * Number of cylinders was 63 for IDE emulated disks with precisely
188  * the same size.  How exactly this is calculated is a mystery.
189  *
190  * The ISO block device (/dev/sdd) comes from images/test.iso.
191  *
192  * To be able to run the tests in a reasonable amount of time,
193  * the virtual machine and block devices are reused between tests.
194  * So don't try testing kill_subprocess :-x
195  *
196  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
197  *
198  * Don't assume anything about the previous contents of the block
199  * devices.  Use 'Init*' to create some initial scenarios.
200  *
201  * You can add a prerequisite clause to any individual test.  This
202  * is a run-time check, which, if it fails, causes the test to be
203  * skipped.  Useful if testing a command which might not work on
204  * all variations of libguestfs builds.  A test that has prerequisite
205  * of 'Always' is run unconditionally.
206  *
207  * In addition, packagers can skip individual tests by setting the
208  * environment variables:     eg:
209  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
210  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
211  *)
212 type tests = (test_init * test_prereq * test) list
213 and test =
214     (* Run the command sequence and just expect nothing to fail. *)
215   | TestRun of seq
216
217     (* Run the command sequence and expect the output of the final
218      * command to be the string.
219      *)
220   | TestOutput of seq * string
221
222     (* Run the command sequence and expect the output of the final
223      * command to be the list of strings.
224      *)
225   | TestOutputList of seq * string list
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the list of block devices (could be either
229      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
230      * character of each string).
231      *)
232   | TestOutputListOfDevices of seq * string list
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the integer.
236      *)
237   | TestOutputInt of seq * int
238
239     (* Run the command sequence and expect the output of the final
240      * command to be <op> <int>, eg. ">=", "1".
241      *)
242   | TestOutputIntOp of seq * string * int
243
244     (* Run the command sequence and expect the output of the final
245      * command to be a true value (!= 0 or != NULL).
246      *)
247   | TestOutputTrue of seq
248
249     (* Run the command sequence and expect the output of the final
250      * command to be a false value (== 0 or == NULL, but not an error).
251      *)
252   | TestOutputFalse of seq
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a list of the given length (but don't care about
256      * content).
257      *)
258   | TestOutputLength of seq * int
259
260     (* Run the command sequence and expect the output of the final
261      * command to be a buffer (RBufferOut), ie. string + size.
262      *)
263   | TestOutputBuffer of seq * string
264
265     (* Run the command sequence and expect the output of the final
266      * command to be a structure.
267      *)
268   | TestOutputStruct of seq * test_field_compare list
269
270     (* Run the command sequence and expect the final command (only)
271      * to fail.
272      *)
273   | TestLastFail of seq
274
275 and test_field_compare =
276   | CompareWithInt of string * int
277   | CompareWithIntOp of string * string * int
278   | CompareWithString of string * string
279   | CompareFieldsIntEq of string * string
280   | CompareFieldsStrEq of string * string
281
282 (* Test prerequisites. *)
283 and test_prereq =
284     (* Test always runs. *)
285   | Always
286
287     (* Test is currently disabled - eg. it fails, or it tests some
288      * unimplemented feature.
289      *)
290   | Disabled
291
292     (* 'string' is some C code (a function body) that should return
293      * true or false.  The test will run if the code returns true.
294      *)
295   | If of string
296
297     (* As for 'If' but the test runs _unless_ the code returns true. *)
298   | Unless of string
299
300 (* Some initial scenarios for testing. *)
301 and test_init =
302     (* Do nothing, block devices could contain random stuff including
303      * LVM PVs, and some filesystems might be mounted.  This is usually
304      * a bad idea.
305      *)
306   | InitNone
307
308     (* Block devices are empty and no filesystems are mounted. *)
309   | InitEmpty
310
311     (* /dev/sda contains a single partition /dev/sda1, with random
312      * content.  /dev/sdb and /dev/sdc may have random content.
313      * No LVM.
314      *)
315   | InitPartition
316
317     (* /dev/sda contains a single partition /dev/sda1, which is formatted
318      * as ext2, empty [except for lost+found] and mounted on /.
319      * /dev/sdb and /dev/sdc may have random content.
320      * No LVM.
321      *)
322   | InitBasicFS
323
324     (* /dev/sda:
325      *   /dev/sda1 (is a PV):
326      *     /dev/VG/LV (size 8MB):
327      *       formatted as ext2, empty [except for lost+found], mounted on /
328      * /dev/sdb and /dev/sdc may have random content.
329      *)
330   | InitBasicFSonLVM
331
332     (* /dev/sdd (the ISO, see images/ directory in source)
333      * is mounted on /
334      *)
335   | InitISOFS
336
337 (* Sequence of commands for testing. *)
338 and seq = cmd list
339 and cmd = string list
340
341 (* Note about long descriptions: When referring to another
342  * action, use the format C<guestfs_other> (ie. the full name of
343  * the C function).  This will be replaced as appropriate in other
344  * language bindings.
345  *
346  * Apart from that, long descriptions are just perldoc paragraphs.
347  *)
348
349 (* Generate a random UUID (used in tests). *)
350 let uuidgen () =
351   let chan = open_process_in "uuidgen" in
352   let uuid = input_line chan in
353   (match close_process_in chan with
354    | WEXITED 0 -> ()
355    | WEXITED _ ->
356        failwith "uuidgen: process exited with non-zero status"
357    | WSIGNALED _ | WSTOPPED _ ->
358        failwith "uuidgen: process signalled or stopped by signal"
359   );
360   uuid
361
362 (* These test functions are used in the language binding tests. *)
363
364 let test_all_args = [
365   String "str";
366   OptString "optstr";
367   StringList "strlist";
368   Bool "b";
369   Int "integer";
370   Int64 "integer64";
371   FileIn "filein";
372   FileOut "fileout";
373 ]
374
375 let test_all_rets = [
376   (* except for RErr, which is tested thoroughly elsewhere *)
377   "test0rint",         RInt "valout";
378   "test0rint64",       RInt64 "valout";
379   "test0rbool",        RBool "valout";
380   "test0rconststring", RConstString "valout";
381   "test0rconstoptstring", RConstOptString "valout";
382   "test0rstring",      RString "valout";
383   "test0rstringlist",  RStringList "valout";
384   "test0rstruct",      RStruct ("valout", "lvm_pv");
385   "test0rstructlist",  RStructList ("valout", "lvm_pv");
386   "test0rhashtable",   RHashtable "valout";
387 ]
388
389 let test_functions = [
390   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
391    [],
392    "internal test function - do not use",
393    "\
394 This is an internal test function which is used to test whether
395 the automatically generated bindings can handle every possible
396 parameter type correctly.
397
398 It echos the contents of each parameter to stdout.
399
400 You probably don't want to call this function.");
401 ] @ List.flatten (
402   List.map (
403     fun (name, ret) ->
404       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
405         [],
406         "internal test function - do not use",
407         "\
408 This is an internal test function which is used to test whether
409 the automatically generated bindings can handle every possible
410 return type correctly.
411
412 It converts string C<val> to the return type.
413
414 You probably don't want to call this function.");
415        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
416         [],
417         "internal test function - do not use",
418         "\
419 This is an internal test function which is used to test whether
420 the automatically generated bindings can handle every possible
421 return type correctly.
422
423 This function always returns an error.
424
425 You probably don't want to call this function.")]
426   ) test_all_rets
427 )
428
429 (* non_daemon_functions are any functions which don't get processed
430  * in the daemon, eg. functions for setting and getting local
431  * configuration values.
432  *)
433
434 let non_daemon_functions = test_functions @ [
435   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
436    [],
437    "launch the qemu subprocess",
438    "\
439 Internally libguestfs is implemented by running a virtual machine
440 using L<qemu(1)>.
441
442 You should call this after configuring the handle
443 (eg. adding drives) but before performing any actions.");
444
445   ("wait_ready", (RErr, []), -1, [NotInFish],
446    [],
447    "wait until the qemu subprocess launches (no op)",
448    "\
449 This function is a no op.
450
451 In versions of the API E<lt> 1.0.71 you had to call this function
452 just after calling C<guestfs_launch> to wait for the launch
453 to complete.  However this is no longer necessary because
454 C<guestfs_launch> now does the waiting.
455
456 If you see any calls to this function in code then you can just
457 remove them, unless you want to retain compatibility with older
458 versions of the API.");
459
460   ("kill_subprocess", (RErr, []), -1, [],
461    [],
462    "kill the qemu subprocess",
463    "\
464 This kills the qemu subprocess.  You should never need to call this.");
465
466   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
467    [],
468    "add an image to examine or modify",
469    "\
470 This function adds a virtual machine disk image C<filename> to the
471 guest.  The first time you call this function, the disk appears as IDE
472 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
473 so on.
474
475 You don't necessarily need to be root when using libguestfs.  However
476 you obviously do need sufficient permissions to access the filename
477 for whatever operations you want to perform (ie. read access if you
478 just want to read the image or write access if you want to modify the
479 image).
480
481 This is equivalent to the qemu parameter
482 C<-drive file=filename,cache=off,if=...>.
483 C<cache=off> is omitted in cases where it is not supported by
484 the underlying filesystem.
485
486 Note that this call checks for the existence of C<filename>.  This
487 stops you from specifying other types of drive which are supported
488 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
489 the general C<guestfs_config> call instead.");
490
491   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
492    [],
493    "add a CD-ROM disk image to examine",
494    "\
495 This function adds a virtual CD-ROM disk image to the guest.
496
497 This is equivalent to the qemu parameter C<-cdrom filename>.
498
499 Note that this call checks for the existence of C<filename>.  This
500 stops you from specifying other types of drive which are supported
501 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
502 the general C<guestfs_config> call instead.");
503
504   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
505    [],
506    "add a drive in snapshot mode (read-only)",
507    "\
508 This adds a drive in snapshot mode, making it effectively
509 read-only.
510
511 Note that writes to the device are allowed, and will be seen for
512 the duration of the guestfs handle, but they are written
513 to a temporary file which is discarded as soon as the guestfs
514 handle is closed.  We don't currently have any method to enable
515 changes to be committed, although qemu can support this.
516
517 This is equivalent to the qemu parameter
518 C<-drive file=filename,snapshot=on,if=...>.
519
520 Note that this call checks for the existence of C<filename>.  This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
523 the general C<guestfs_config> call instead.");
524
525   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
526    [],
527    "add qemu parameters",
528    "\
529 This can be used to add arbitrary qemu command line parameters
530 of the form C<-param value>.  Actually it's not quite arbitrary - we
531 prevent you from setting some parameters which would interfere with
532 parameters that we use.
533
534 The first character of C<param> string must be a C<-> (dash).
535
536 C<value> can be NULL.");
537
538   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
539    [],
540    "set the qemu binary",
541    "\
542 Set the qemu binary that we will use.
543
544 The default is chosen when the library was compiled by the
545 configure script.
546
547 You can also override this by setting the C<LIBGUESTFS_QEMU>
548 environment variable.
549
550 Setting C<qemu> to C<NULL> restores the default qemu binary.");
551
552   ("get_qemu", (RConstString "qemu", []), -1, [],
553    [InitNone, Always, TestRun (
554       [["get_qemu"]])],
555    "get the qemu binary",
556    "\
557 Return the current qemu binary.
558
559 This is always non-NULL.  If it wasn't set already, then this will
560 return the default qemu binary name.");
561
562   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
563    [],
564    "set the search path",
565    "\
566 Set the path that libguestfs searches for kernel and initrd.img.
567
568 The default is C<$libdir/guestfs> unless overridden by setting
569 C<LIBGUESTFS_PATH> environment variable.
570
571 Setting C<path> to C<NULL> restores the default path.");
572
573   ("get_path", (RConstString "path", []), -1, [],
574    [InitNone, Always, TestRun (
575       [["get_path"]])],
576    "get the search path",
577    "\
578 Return the current search path.
579
580 This is always non-NULL.  If it wasn't set already, then this will
581 return the default path.");
582
583   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
584    [],
585    "add options to kernel command line",
586    "\
587 This function is used to add additional options to the
588 guest kernel command line.
589
590 The default is C<NULL> unless overridden by setting
591 C<LIBGUESTFS_APPEND> environment variable.
592
593 Setting C<append> to C<NULL> means I<no> additional options
594 are passed (libguestfs always adds a few of its own).");
595
596   ("get_append", (RConstOptString "append", []), -1, [],
597    (* This cannot be tested with the current framework.  The
598     * function can return NULL in normal operations, which the
599     * test framework interprets as an error.
600     *)
601    [],
602    "get the additional kernel options",
603    "\
604 Return the additional kernel options which are added to the
605 guest kernel command line.
606
607 If C<NULL> then no options are added.");
608
609   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
610    [],
611    "set autosync mode",
612    "\
613 If C<autosync> is true, this enables autosync.  Libguestfs will make a
614 best effort attempt to run C<guestfs_umount_all> followed by
615 C<guestfs_sync> when the handle is closed
616 (also if the program exits without closing handles).
617
618 This is disabled by default (except in guestfish where it is
619 enabled by default).");
620
621   ("get_autosync", (RBool "autosync", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_autosync"]])],
624    "get autosync mode",
625    "\
626 Get the autosync flag.");
627
628   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
629    [],
630    "set verbose mode",
631    "\
632 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
633
634 Verbose messages are disabled unless the environment variable
635 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
636
637   ("get_verbose", (RBool "verbose", []), -1, [],
638    [],
639    "get verbose mode",
640    "\
641 This returns the verbose messages flag.");
642
643   ("is_ready", (RBool "ready", []), -1, [],
644    [InitNone, Always, TestOutputTrue (
645       [["is_ready"]])],
646    "is ready to accept commands",
647    "\
648 This returns true iff this handle is ready to accept commands
649 (in the C<READY> state).
650
651 For more information on states, see L<guestfs(3)>.");
652
653   ("is_config", (RBool "config", []), -1, [],
654    [InitNone, Always, TestOutputFalse (
655       [["is_config"]])],
656    "is in configuration state",
657    "\
658 This returns true iff this handle is being configured
659 (in the C<CONFIG> state).
660
661 For more information on states, see L<guestfs(3)>.");
662
663   ("is_launching", (RBool "launching", []), -1, [],
664    [InitNone, Always, TestOutputFalse (
665       [["is_launching"]])],
666    "is launching subprocess",
667    "\
668 This returns true iff this handle is launching the subprocess
669 (in the C<LAUNCHING> state).
670
671 For more information on states, see L<guestfs(3)>.");
672
673   ("is_busy", (RBool "busy", []), -1, [],
674    [InitNone, Always, TestOutputFalse (
675       [["is_busy"]])],
676    "is busy processing a command",
677    "\
678 This returns true iff this handle is busy processing a command
679 (in the C<BUSY> state).
680
681 For more information on states, see L<guestfs(3)>.");
682
683   ("get_state", (RInt "state", []), -1, [],
684    [],
685    "get the current state",
686    "\
687 This returns the current state as an opaque integer.  This is
688 only useful for printing debug and internal error messages.
689
690 For more information on states, see L<guestfs(3)>.");
691
692   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
693    [InitNone, Always, TestOutputInt (
694       [["set_memsize"; "500"];
695        ["get_memsize"]], 500)],
696    "set memory allocated to the qemu subprocess",
697    "\
698 This sets the memory size in megabytes allocated to the
699 qemu subprocess.  This only has any effect if called before
700 C<guestfs_launch>.
701
702 You can also change this by setting the environment
703 variable C<LIBGUESTFS_MEMSIZE> before the handle is
704 created.
705
706 For more information on the architecture of libguestfs,
707 see L<guestfs(3)>.");
708
709   ("get_memsize", (RInt "memsize", []), -1, [],
710    [InitNone, Always, TestOutputIntOp (
711       [["get_memsize"]], ">=", 256)],
712    "get memory allocated to the qemu subprocess",
713    "\
714 This gets the memory size in megabytes allocated to the
715 qemu subprocess.
716
717 If C<guestfs_set_memsize> was not called
718 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
719 then this returns the compiled-in default value for memsize.
720
721 For more information on the architecture of libguestfs,
722 see L<guestfs(3)>.");
723
724   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
725    [InitNone, Always, TestOutputIntOp (
726       [["get_pid"]], ">=", 1)],
727    "get PID of qemu subprocess",
728    "\
729 Return the process ID of the qemu subprocess.  If there is no
730 qemu subprocess, then this will return an error.
731
732 This is an internal call used for debugging and testing.");
733
734   ("version", (RStruct ("version", "version"), []), -1, [],
735    [InitNone, Always, TestOutputStruct (
736       [["version"]], [CompareWithInt ("major", 1)])],
737    "get the library version number",
738    "\
739 Return the libguestfs version number that the program is linked
740 against.
741
742 Note that because of dynamic linking this is not necessarily
743 the version of libguestfs that you compiled against.  You can
744 compile the program, and then at runtime dynamically link
745 against a completely different C<libguestfs.so> library.
746
747 This call was added in version C<1.0.58>.  In previous
748 versions of libguestfs there was no way to get the version
749 number.  From C code you can use ELF weak linking tricks to find out if
750 this symbol exists (if it doesn't, then it's an earlier version).
751
752 The call returns a structure with four elements.  The first
753 three (C<major>, C<minor> and C<release>) are numbers and
754 correspond to the usual version triplet.  The fourth element
755 (C<extra>) is a string and is normally empty, but may be
756 used for distro-specific information.
757
758 To construct the original version string:
759 C<$major.$minor.$release$extra>
760
761 I<Note:> Don't use this call to test for availability
762 of features.  Distro backports makes this unreliable.  Use
763 C<guestfs_available> instead.");
764
765   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
766    [InitNone, Always, TestOutputTrue (
767       [["set_selinux"; "true"];
768        ["get_selinux"]])],
769    "set SELinux enabled or disabled at appliance boot",
770    "\
771 This sets the selinux flag that is passed to the appliance
772 at boot time.  The default is C<selinux=0> (disabled).
773
774 Note that if SELinux is enabled, it is always in
775 Permissive mode (C<enforcing=0>).
776
777 For more information on the architecture of libguestfs,
778 see L<guestfs(3)>.");
779
780   ("get_selinux", (RBool "selinux", []), -1, [],
781    [],
782    "get SELinux enabled flag",
783    "\
784 This returns the current setting of the selinux flag which
785 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
786
787 For more information on the architecture of libguestfs,
788 see L<guestfs(3)>.");
789
790   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
791    [InitNone, Always, TestOutputFalse (
792       [["set_trace"; "false"];
793        ["get_trace"]])],
794    "enable or disable command traces",
795    "\
796 If the command trace flag is set to 1, then commands are
797 printed on stdout before they are executed in a format
798 which is very similar to the one used by guestfish.  In
799 other words, you can run a program with this enabled, and
800 you will get out a script which you can feed to guestfish
801 to perform the same set of actions.
802
803 If you want to trace C API calls into libguestfs (and
804 other libraries) then possibly a better way is to use
805 the external ltrace(1) command.
806
807 Command traces are disabled unless the environment variable
808 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
809
810   ("get_trace", (RBool "trace", []), -1, [],
811    [],
812    "get command trace enabled flag",
813    "\
814 Return the command trace flag.");
815
816   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
817    [InitNone, Always, TestOutputFalse (
818       [["set_direct"; "false"];
819        ["get_direct"]])],
820    "enable or disable direct appliance mode",
821    "\
822 If the direct appliance mode flag is enabled, then stdin and
823 stdout are passed directly through to the appliance once it
824 is launched.
825
826 One consequence of this is that log messages aren't caught
827 by the library and handled by C<guestfs_set_log_message_callback>,
828 but go straight to stdout.
829
830 You probably don't want to use this unless you know what you
831 are doing.
832
833 The default is disabled.");
834
835   ("get_direct", (RBool "direct", []), -1, [],
836    [],
837    "get direct appliance mode flag",
838    "\
839 Return the direct appliance mode flag.");
840
841   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
842    [InitNone, Always, TestOutputTrue (
843       [["set_recovery_proc"; "true"];
844        ["get_recovery_proc"]])],
845    "enable or disable the recovery process",
846    "\
847 If this is called with the parameter C<false> then
848 C<guestfs_launch> does not create a recovery process.  The
849 purpose of the recovery process is to stop runaway qemu
850 processes in the case where the main program aborts abruptly.
851
852 This only has any effect if called before C<guestfs_launch>,
853 and the default is true.
854
855 About the only time when you would want to disable this is
856 if the main process will fork itself into the background
857 (\"daemonize\" itself).  In this case the recovery process
858 thinks that the main program has disappeared and so kills
859 qemu, which is not very helpful.");
860
861   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
862    [],
863    "get recovery process enabled flag",
864    "\
865 Return the recovery process enabled flag.");
866
867 ]
868
869 (* daemon_functions are any functions which cause some action
870  * to take place in the daemon.
871  *)
872
873 let daemon_functions = [
874   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
875    [InitEmpty, Always, TestOutput (
876       [["part_disk"; "/dev/sda"; "mbr"];
877        ["mkfs"; "ext2"; "/dev/sda1"];
878        ["mount"; "/dev/sda1"; "/"];
879        ["write_file"; "/new"; "new file contents"; "0"];
880        ["cat"; "/new"]], "new file contents")],
881    "mount a guest disk at a position in the filesystem",
882    "\
883 Mount a guest disk at a position in the filesystem.  Block devices
884 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
885 the guest.  If those block devices contain partitions, they will have
886 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
887 names can be used.
888
889 The rules are the same as for L<mount(2)>:  A filesystem must
890 first be mounted on C</> before others can be mounted.  Other
891 filesystems can only be mounted on directories which already
892 exist.
893
894 The mounted filesystem is writable, if we have sufficient permissions
895 on the underlying device.
896
897 The filesystem options C<sync> and C<noatime> are set with this
898 call, in order to improve reliability.");
899
900   ("sync", (RErr, []), 2, [],
901    [ InitEmpty, Always, TestRun [["sync"]]],
902    "sync disks, writes are flushed through to the disk image",
903    "\
904 This syncs the disk, so that any writes are flushed through to the
905 underlying disk image.
906
907 You should always call this if you have modified a disk image, before
908 closing the handle.");
909
910   ("touch", (RErr, [Pathname "path"]), 3, [],
911    [InitBasicFS, Always, TestOutputTrue (
912       [["touch"; "/new"];
913        ["exists"; "/new"]])],
914    "update file timestamps or create a new file",
915    "\
916 Touch acts like the L<touch(1)> command.  It can be used to
917 update the timestamps on a file, or, if the file does not exist,
918 to create a new zero-length file.");
919
920   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
921    [InitISOFS, Always, TestOutput (
922       [["cat"; "/known-2"]], "abcdef\n")],
923    "list the contents of a file",
924    "\
925 Return the contents of the file named C<path>.
926
927 Note that this function cannot correctly handle binary files
928 (specifically, files containing C<\\0> character which is treated
929 as end of string).  For those you need to use the C<guestfs_read_file>
930 or C<guestfs_download> functions which have a more complex interface.");
931
932   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
933    [], (* XXX Tricky to test because it depends on the exact format
934         * of the 'ls -l' command, which changes between F10 and F11.
935         *)
936    "list the files in a directory (long format)",
937    "\
938 List the files in C<directory> (relative to the root directory,
939 there is no cwd) in the format of 'ls -la'.
940
941 This command is mostly useful for interactive sessions.  It
942 is I<not> intended that you try to parse the output string.");
943
944   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
945    [InitBasicFS, Always, TestOutputList (
946       [["touch"; "/new"];
947        ["touch"; "/newer"];
948        ["touch"; "/newest"];
949        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
950    "list the files in a directory",
951    "\
952 List the files in C<directory> (relative to the root directory,
953 there is no cwd).  The '.' and '..' entries are not returned, but
954 hidden files are shown.
955
956 This command is mostly useful for interactive sessions.  Programs
957 should probably use C<guestfs_readdir> instead.");
958
959   ("list_devices", (RStringList "devices", []), 7, [],
960    [InitEmpty, Always, TestOutputListOfDevices (
961       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
962    "list the block devices",
963    "\
964 List all the block devices.
965
966 The full block device names are returned, eg. C</dev/sda>");
967
968   ("list_partitions", (RStringList "partitions", []), 8, [],
969    [InitBasicFS, Always, TestOutputListOfDevices (
970       [["list_partitions"]], ["/dev/sda1"]);
971     InitEmpty, Always, TestOutputListOfDevices (
972       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
973        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
974    "list the partitions",
975    "\
976 List all the partitions detected on all block devices.
977
978 The full partition device names are returned, eg. C</dev/sda1>
979
980 This does not return logical volumes.  For that you will need to
981 call C<guestfs_lvs>.");
982
983   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
984    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
985       [["pvs"]], ["/dev/sda1"]);
986     InitEmpty, Always, TestOutputListOfDevices (
987       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
988        ["pvcreate"; "/dev/sda1"];
989        ["pvcreate"; "/dev/sda2"];
990        ["pvcreate"; "/dev/sda3"];
991        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
992    "list the LVM physical volumes (PVs)",
993    "\
994 List all the physical volumes detected.  This is the equivalent
995 of the L<pvs(8)> command.
996
997 This returns a list of just the device names that contain
998 PVs (eg. C</dev/sda2>).
999
1000 See also C<guestfs_pvs_full>.");
1001
1002   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1003    [InitBasicFSonLVM, Always, TestOutputList (
1004       [["vgs"]], ["VG"]);
1005     InitEmpty, Always, TestOutputList (
1006       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1007        ["pvcreate"; "/dev/sda1"];
1008        ["pvcreate"; "/dev/sda2"];
1009        ["pvcreate"; "/dev/sda3"];
1010        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1011        ["vgcreate"; "VG2"; "/dev/sda3"];
1012        ["vgs"]], ["VG1"; "VG2"])],
1013    "list the LVM volume groups (VGs)",
1014    "\
1015 List all the volumes groups detected.  This is the equivalent
1016 of the L<vgs(8)> command.
1017
1018 This returns a list of just the volume group names that were
1019 detected (eg. C<VolGroup00>).
1020
1021 See also C<guestfs_vgs_full>.");
1022
1023   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1024    [InitBasicFSonLVM, Always, TestOutputList (
1025       [["lvs"]], ["/dev/VG/LV"]);
1026     InitEmpty, Always, TestOutputList (
1027       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1028        ["pvcreate"; "/dev/sda1"];
1029        ["pvcreate"; "/dev/sda2"];
1030        ["pvcreate"; "/dev/sda3"];
1031        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1032        ["vgcreate"; "VG2"; "/dev/sda3"];
1033        ["lvcreate"; "LV1"; "VG1"; "50"];
1034        ["lvcreate"; "LV2"; "VG1"; "50"];
1035        ["lvcreate"; "LV3"; "VG2"; "50"];
1036        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1037    "list the LVM logical volumes (LVs)",
1038    "\
1039 List all the logical volumes detected.  This is the equivalent
1040 of the L<lvs(8)> command.
1041
1042 This returns a list of the logical volume device names
1043 (eg. C</dev/VolGroup00/LogVol00>).
1044
1045 See also C<guestfs_lvs_full>.");
1046
1047   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1048    [], (* XXX how to test? *)
1049    "list the LVM physical volumes (PVs)",
1050    "\
1051 List all the physical volumes detected.  This is the equivalent
1052 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1053
1054   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1055    [], (* XXX how to test? *)
1056    "list the LVM volume groups (VGs)",
1057    "\
1058 List all the volumes groups detected.  This is the equivalent
1059 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1060
1061   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1062    [], (* XXX how to test? *)
1063    "list the LVM logical volumes (LVs)",
1064    "\
1065 List all the logical volumes detected.  This is the equivalent
1066 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1067
1068   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1069    [InitISOFS, Always, TestOutputList (
1070       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1071     InitISOFS, Always, TestOutputList (
1072       [["read_lines"; "/empty"]], [])],
1073    "read file as lines",
1074    "\
1075 Return the contents of the file named C<path>.
1076
1077 The file contents are returned as a list of lines.  Trailing
1078 C<LF> and C<CRLF> character sequences are I<not> returned.
1079
1080 Note that this function cannot correctly handle binary files
1081 (specifically, files containing C<\\0> character which is treated
1082 as end of line).  For those you need to use the C<guestfs_read_file>
1083 function which has a more complex interface.");
1084
1085   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1086    [], (* XXX Augeas code needs tests. *)
1087    "create a new Augeas handle",
1088    "\
1089 Create a new Augeas handle for editing configuration files.
1090 If there was any previous Augeas handle associated with this
1091 guestfs session, then it is closed.
1092
1093 You must call this before using any other C<guestfs_aug_*>
1094 commands.
1095
1096 C<root> is the filesystem root.  C<root> must not be NULL,
1097 use C</> instead.
1098
1099 The flags are the same as the flags defined in
1100 E<lt>augeas.hE<gt>, the logical I<or> of the following
1101 integers:
1102
1103 =over 4
1104
1105 =item C<AUG_SAVE_BACKUP> = 1
1106
1107 Keep the original file with a C<.augsave> extension.
1108
1109 =item C<AUG_SAVE_NEWFILE> = 2
1110
1111 Save changes into a file with extension C<.augnew>, and
1112 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1113
1114 =item C<AUG_TYPE_CHECK> = 4
1115
1116 Typecheck lenses (can be expensive).
1117
1118 =item C<AUG_NO_STDINC> = 8
1119
1120 Do not use standard load path for modules.
1121
1122 =item C<AUG_SAVE_NOOP> = 16
1123
1124 Make save a no-op, just record what would have been changed.
1125
1126 =item C<AUG_NO_LOAD> = 32
1127
1128 Do not load the tree in C<guestfs_aug_init>.
1129
1130 =back
1131
1132 To close the handle, you can call C<guestfs_aug_close>.
1133
1134 To find out more about Augeas, see L<http://augeas.net/>.");
1135
1136   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1137    [], (* XXX Augeas code needs tests. *)
1138    "close the current Augeas handle",
1139    "\
1140 Close the current Augeas handle and free up any resources
1141 used by it.  After calling this, you have to call
1142 C<guestfs_aug_init> again before you can use any other
1143 Augeas functions.");
1144
1145   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1146    [], (* XXX Augeas code needs tests. *)
1147    "define an Augeas variable",
1148    "\
1149 Defines an Augeas variable C<name> whose value is the result
1150 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1151 undefined.
1152
1153 On success this returns the number of nodes in C<expr>, or
1154 C<0> if C<expr> evaluates to something which is not a nodeset.");
1155
1156   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "define an Augeas node",
1159    "\
1160 Defines a variable C<name> whose value is the result of
1161 evaluating C<expr>.
1162
1163 If C<expr> evaluates to an empty nodeset, a node is created,
1164 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1165 C<name> will be the nodeset containing that single node.
1166
1167 On success this returns a pair containing the
1168 number of nodes in the nodeset, and a boolean flag
1169 if a node was created.");
1170
1171   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1172    [], (* XXX Augeas code needs tests. *)
1173    "look up the value of an Augeas path",
1174    "\
1175 Look up the value associated with C<path>.  If C<path>
1176 matches exactly one node, the C<value> is returned.");
1177
1178   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1179    [], (* XXX Augeas code needs tests. *)
1180    "set Augeas path to value",
1181    "\
1182 Set the value associated with C<path> to C<value>.");
1183
1184   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1185    [], (* XXX Augeas code needs tests. *)
1186    "insert a sibling Augeas node",
1187    "\
1188 Create a new sibling C<label> for C<path>, inserting it into
1189 the tree before or after C<path> (depending on the boolean
1190 flag C<before>).
1191
1192 C<path> must match exactly one existing node in the tree, and
1193 C<label> must be a label, ie. not contain C</>, C<*> or end
1194 with a bracketed index C<[N]>.");
1195
1196   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1197    [], (* XXX Augeas code needs tests. *)
1198    "remove an Augeas path",
1199    "\
1200 Remove C<path> and all of its children.
1201
1202 On success this returns the number of entries which were removed.");
1203
1204   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "move Augeas node",
1207    "\
1208 Move the node C<src> to C<dest>.  C<src> must match exactly
1209 one node.  C<dest> is overwritten if it exists.");
1210
1211   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1212    [], (* XXX Augeas code needs tests. *)
1213    "return Augeas nodes which match augpath",
1214    "\
1215 Returns a list of paths which match the path expression C<path>.
1216 The returned paths are sufficiently qualified so that they match
1217 exactly one node in the current tree.");
1218
1219   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "write all pending Augeas changes to disk",
1222    "\
1223 This writes all pending changes to disk.
1224
1225 The flags which were passed to C<guestfs_aug_init> affect exactly
1226 how files are saved.");
1227
1228   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1229    [], (* XXX Augeas code needs tests. *)
1230    "load files into the tree",
1231    "\
1232 Load files into the tree.
1233
1234 See C<aug_load> in the Augeas documentation for the full gory
1235 details.");
1236
1237   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "list Augeas nodes under augpath",
1240    "\
1241 This is just a shortcut for listing C<guestfs_aug_match>
1242 C<path/*> and sorting the resulting nodes into alphabetical order.");
1243
1244   ("rm", (RErr, [Pathname "path"]), 29, [],
1245    [InitBasicFS, Always, TestRun
1246       [["touch"; "/new"];
1247        ["rm"; "/new"]];
1248     InitBasicFS, Always, TestLastFail
1249       [["rm"; "/new"]];
1250     InitBasicFS, Always, TestLastFail
1251       [["mkdir"; "/new"];
1252        ["rm"; "/new"]]],
1253    "remove a file",
1254    "\
1255 Remove the single file C<path>.");
1256
1257   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1258    [InitBasicFS, Always, TestRun
1259       [["mkdir"; "/new"];
1260        ["rmdir"; "/new"]];
1261     InitBasicFS, Always, TestLastFail
1262       [["rmdir"; "/new"]];
1263     InitBasicFS, Always, TestLastFail
1264       [["touch"; "/new"];
1265        ["rmdir"; "/new"]]],
1266    "remove a directory",
1267    "\
1268 Remove the single directory C<path>.");
1269
1270   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1271    [InitBasicFS, Always, TestOutputFalse
1272       [["mkdir"; "/new"];
1273        ["mkdir"; "/new/foo"];
1274        ["touch"; "/new/foo/bar"];
1275        ["rm_rf"; "/new"];
1276        ["exists"; "/new"]]],
1277    "remove a file or directory recursively",
1278    "\
1279 Remove the file or directory C<path>, recursively removing the
1280 contents if its a directory.  This is like the C<rm -rf> shell
1281 command.");
1282
1283   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1284    [InitBasicFS, Always, TestOutputTrue
1285       [["mkdir"; "/new"];
1286        ["is_dir"; "/new"]];
1287     InitBasicFS, Always, TestLastFail
1288       [["mkdir"; "/new/foo/bar"]]],
1289    "create a directory",
1290    "\
1291 Create a directory named C<path>.");
1292
1293   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1294    [InitBasicFS, Always, TestOutputTrue
1295       [["mkdir_p"; "/new/foo/bar"];
1296        ["is_dir"; "/new/foo/bar"]];
1297     InitBasicFS, Always, TestOutputTrue
1298       [["mkdir_p"; "/new/foo/bar"];
1299        ["is_dir"; "/new/foo"]];
1300     InitBasicFS, Always, TestOutputTrue
1301       [["mkdir_p"; "/new/foo/bar"];
1302        ["is_dir"; "/new"]];
1303     (* Regression tests for RHBZ#503133: *)
1304     InitBasicFS, Always, TestRun
1305       [["mkdir"; "/new"];
1306        ["mkdir_p"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["touch"; "/new"];
1309        ["mkdir_p"; "/new"]]],
1310    "create a directory and parents",
1311    "\
1312 Create a directory named C<path>, creating any parent directories
1313 as necessary.  This is like the C<mkdir -p> shell command.");
1314
1315   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1316    [], (* XXX Need stat command to test *)
1317    "change file mode",
1318    "\
1319 Change the mode (permissions) of C<path> to C<mode>.  Only
1320 numeric modes are supported.");
1321
1322   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1323    [], (* XXX Need stat command to test *)
1324    "change file owner and group",
1325    "\
1326 Change the file owner to C<owner> and group to C<group>.
1327
1328 Only numeric uid and gid are supported.  If you want to use
1329 names, you will need to locate and parse the password file
1330 yourself (Augeas support makes this relatively easy).");
1331
1332   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1333    [InitISOFS, Always, TestOutputTrue (
1334       [["exists"; "/empty"]]);
1335     InitISOFS, Always, TestOutputTrue (
1336       [["exists"; "/directory"]])],
1337    "test if file or directory exists",
1338    "\
1339 This returns C<true> if and only if there is a file, directory
1340 (or anything) with the given C<path> name.
1341
1342 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1343
1344   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1345    [InitISOFS, Always, TestOutputTrue (
1346       [["is_file"; "/known-1"]]);
1347     InitISOFS, Always, TestOutputFalse (
1348       [["is_file"; "/directory"]])],
1349    "test if file exists",
1350    "\
1351 This returns C<true> if and only if there is a file
1352 with the given C<path> name.  Note that it returns false for
1353 other objects like directories.
1354
1355 See also C<guestfs_stat>.");
1356
1357   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1358    [InitISOFS, Always, TestOutputFalse (
1359       [["is_dir"; "/known-3"]]);
1360     InitISOFS, Always, TestOutputTrue (
1361       [["is_dir"; "/directory"]])],
1362    "test if file exists",
1363    "\
1364 This returns C<true> if and only if there is a directory
1365 with the given C<path> name.  Note that it returns false for
1366 other objects like files.
1367
1368 See also C<guestfs_stat>.");
1369
1370   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1371    [InitEmpty, Always, TestOutputListOfDevices (
1372       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1373        ["pvcreate"; "/dev/sda1"];
1374        ["pvcreate"; "/dev/sda2"];
1375        ["pvcreate"; "/dev/sda3"];
1376        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1377    "create an LVM physical volume",
1378    "\
1379 This creates an LVM physical volume on the named C<device>,
1380 where C<device> should usually be a partition name such
1381 as C</dev/sda1>.");
1382
1383   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1384    [InitEmpty, Always, TestOutputList (
1385       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1386        ["pvcreate"; "/dev/sda1"];
1387        ["pvcreate"; "/dev/sda2"];
1388        ["pvcreate"; "/dev/sda3"];
1389        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1390        ["vgcreate"; "VG2"; "/dev/sda3"];
1391        ["vgs"]], ["VG1"; "VG2"])],
1392    "create an LVM volume group",
1393    "\
1394 This creates an LVM volume group called C<volgroup>
1395 from the non-empty list of physical volumes C<physvols>.");
1396
1397   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1398    [InitEmpty, Always, TestOutputList (
1399       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1400        ["pvcreate"; "/dev/sda1"];
1401        ["pvcreate"; "/dev/sda2"];
1402        ["pvcreate"; "/dev/sda3"];
1403        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1404        ["vgcreate"; "VG2"; "/dev/sda3"];
1405        ["lvcreate"; "LV1"; "VG1"; "50"];
1406        ["lvcreate"; "LV2"; "VG1"; "50"];
1407        ["lvcreate"; "LV3"; "VG2"; "50"];
1408        ["lvcreate"; "LV4"; "VG2"; "50"];
1409        ["lvcreate"; "LV5"; "VG2"; "50"];
1410        ["lvs"]],
1411       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1412        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1413    "create an LVM volume group",
1414    "\
1415 This creates an LVM volume group called C<logvol>
1416 on the volume group C<volgroup>, with C<size> megabytes.");
1417
1418   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1419    [InitEmpty, Always, TestOutput (
1420       [["part_disk"; "/dev/sda"; "mbr"];
1421        ["mkfs"; "ext2"; "/dev/sda1"];
1422        ["mount"; "/dev/sda1"; "/"];
1423        ["write_file"; "/new"; "new file contents"; "0"];
1424        ["cat"; "/new"]], "new file contents")],
1425    "make a filesystem",
1426    "\
1427 This creates a filesystem on C<device> (usually a partition
1428 or LVM logical volume).  The filesystem type is C<fstype>, for
1429 example C<ext3>.");
1430
1431   ("sfdisk", (RErr, [Device "device";
1432                      Int "cyls"; Int "heads"; Int "sectors";
1433                      StringList "lines"]), 43, [DangerWillRobinson],
1434    [],
1435    "create partitions on a block device",
1436    "\
1437 This is a direct interface to the L<sfdisk(8)> program for creating
1438 partitions on block devices.
1439
1440 C<device> should be a block device, for example C</dev/sda>.
1441
1442 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1443 and sectors on the device, which are passed directly to sfdisk as
1444 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1445 of these, then the corresponding parameter is omitted.  Usually for
1446 'large' disks, you can just pass C<0> for these, but for small
1447 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1448 out the right geometry and you will need to tell it.
1449
1450 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1451 information refer to the L<sfdisk(8)> manpage.
1452
1453 To create a single partition occupying the whole disk, you would
1454 pass C<lines> as a single element list, when the single element being
1455 the string C<,> (comma).
1456
1457 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1458 C<guestfs_part_init>");
1459
1460   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1461    [InitBasicFS, Always, TestOutput (
1462       [["write_file"; "/new"; "new file contents"; "0"];
1463        ["cat"; "/new"]], "new file contents");
1464     InitBasicFS, Always, TestOutput (
1465       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1466        ["cat"; "/new"]], "\nnew file contents\n");
1467     InitBasicFS, Always, TestOutput (
1468       [["write_file"; "/new"; "\n\n"; "0"];
1469        ["cat"; "/new"]], "\n\n");
1470     InitBasicFS, Always, TestOutput (
1471       [["write_file"; "/new"; ""; "0"];
1472        ["cat"; "/new"]], "");
1473     InitBasicFS, Always, TestOutput (
1474       [["write_file"; "/new"; "\n\n\n"; "0"];
1475        ["cat"; "/new"]], "\n\n\n");
1476     InitBasicFS, Always, TestOutput (
1477       [["write_file"; "/new"; "\n"; "0"];
1478        ["cat"; "/new"]], "\n")],
1479    "create a file",
1480    "\
1481 This call creates a file called C<path>.  The contents of the
1482 file is the string C<content> (which can contain any 8 bit data),
1483 with length C<size>.
1484
1485 As a special case, if C<size> is C<0>
1486 then the length is calculated using C<strlen> (so in this case
1487 the content cannot contain embedded ASCII NULs).
1488
1489 I<NB.> Owing to a bug, writing content containing ASCII NUL
1490 characters does I<not> work, even if the length is specified.
1491 We hope to resolve this bug in a future version.  In the meantime
1492 use C<guestfs_upload>.");
1493
1494   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1495    [InitEmpty, Always, TestOutputListOfDevices (
1496       [["part_disk"; "/dev/sda"; "mbr"];
1497        ["mkfs"; "ext2"; "/dev/sda1"];
1498        ["mount"; "/dev/sda1"; "/"];
1499        ["mounts"]], ["/dev/sda1"]);
1500     InitEmpty, Always, TestOutputList (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount"; "/dev/sda1"; "/"];
1504        ["umount"; "/"];
1505        ["mounts"]], [])],
1506    "unmount a filesystem",
1507    "\
1508 This unmounts the given filesystem.  The filesystem may be
1509 specified either by its mountpoint (path) or the device which
1510 contains the filesystem.");
1511
1512   ("mounts", (RStringList "devices", []), 46, [],
1513    [InitBasicFS, Always, TestOutputListOfDevices (
1514       [["mounts"]], ["/dev/sda1"])],
1515    "show mounted filesystems",
1516    "\
1517 This returns the list of currently mounted filesystems.  It returns
1518 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1519
1520 Some internal mounts are not shown.
1521
1522 See also: C<guestfs_mountpoints>");
1523
1524   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1525    [InitBasicFS, Always, TestOutputList (
1526       [["umount_all"];
1527        ["mounts"]], []);
1528     (* check that umount_all can unmount nested mounts correctly: *)
1529     InitEmpty, Always, TestOutputList (
1530       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1531        ["mkfs"; "ext2"; "/dev/sda1"];
1532        ["mkfs"; "ext2"; "/dev/sda2"];
1533        ["mkfs"; "ext2"; "/dev/sda3"];
1534        ["mount"; "/dev/sda1"; "/"];
1535        ["mkdir"; "/mp1"];
1536        ["mount"; "/dev/sda2"; "/mp1"];
1537        ["mkdir"; "/mp1/mp2"];
1538        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1539        ["mkdir"; "/mp1/mp2/mp3"];
1540        ["umount_all"];
1541        ["mounts"]], [])],
1542    "unmount all filesystems",
1543    "\
1544 This unmounts all mounted filesystems.
1545
1546 Some internal mounts are not unmounted by this call.");
1547
1548   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1549    [],
1550    "remove all LVM LVs, VGs and PVs",
1551    "\
1552 This command removes all LVM logical volumes, volume groups
1553 and physical volumes.");
1554
1555   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1556    [InitISOFS, Always, TestOutput (
1557       [["file"; "/empty"]], "empty");
1558     InitISOFS, Always, TestOutput (
1559       [["file"; "/known-1"]], "ASCII text");
1560     InitISOFS, Always, TestLastFail (
1561       [["file"; "/notexists"]])],
1562    "determine file type",
1563    "\
1564 This call uses the standard L<file(1)> command to determine
1565 the type or contents of the file.  This also works on devices,
1566 for example to find out whether a partition contains a filesystem.
1567
1568 This call will also transparently look inside various types
1569 of compressed file.
1570
1571 The exact command which runs is C<file -zbsL path>.  Note in
1572 particular that the filename is not prepended to the output
1573 (the C<-b> option).");
1574
1575   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1576    [InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 1"]], "Result1");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 2"]], "Result2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 3"]], "\nResult3");
1588     InitBasicFS, Always, TestOutput (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command 4"]], "\nResult4\n");
1592     InitBasicFS, Always, TestOutput (
1593       [["upload"; "test-command"; "/test-command"];
1594        ["chmod"; "0o755"; "/test-command"];
1595        ["command"; "/test-command 5"]], "\nResult5\n\n");
1596     InitBasicFS, Always, TestOutput (
1597       [["upload"; "test-command"; "/test-command"];
1598        ["chmod"; "0o755"; "/test-command"];
1599        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1600     InitBasicFS, Always, TestOutput (
1601       [["upload"; "test-command"; "/test-command"];
1602        ["chmod"; "0o755"; "/test-command"];
1603        ["command"; "/test-command 7"]], "");
1604     InitBasicFS, Always, TestOutput (
1605       [["upload"; "test-command"; "/test-command"];
1606        ["chmod"; "0o755"; "/test-command"];
1607        ["command"; "/test-command 8"]], "\n");
1608     InitBasicFS, Always, TestOutput (
1609       [["upload"; "test-command"; "/test-command"];
1610        ["chmod"; "0o755"; "/test-command"];
1611        ["command"; "/test-command 9"]], "\n\n");
1612     InitBasicFS, Always, TestOutput (
1613       [["upload"; "test-command"; "/test-command"];
1614        ["chmod"; "0o755"; "/test-command"];
1615        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1616     InitBasicFS, Always, TestOutput (
1617       [["upload"; "test-command"; "/test-command"];
1618        ["chmod"; "0o755"; "/test-command"];
1619        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1620     InitBasicFS, Always, TestLastFail (
1621       [["upload"; "test-command"; "/test-command"];
1622        ["chmod"; "0o755"; "/test-command"];
1623        ["command"; "/test-command"]])],
1624    "run a command from the guest filesystem",
1625    "\
1626 This call runs a command from the guest filesystem.  The
1627 filesystem must be mounted, and must contain a compatible
1628 operating system (ie. something Linux, with the same
1629 or compatible processor architecture).
1630
1631 The single parameter is an argv-style list of arguments.
1632 The first element is the name of the program to run.
1633 Subsequent elements are parameters.  The list must be
1634 non-empty (ie. must contain a program name).  Note that
1635 the command runs directly, and is I<not> invoked via
1636 the shell (see C<guestfs_sh>).
1637
1638 The return value is anything printed to I<stdout> by
1639 the command.
1640
1641 If the command returns a non-zero exit status, then
1642 this function returns an error message.  The error message
1643 string is the content of I<stderr> from the command.
1644
1645 The C<$PATH> environment variable will contain at least
1646 C</usr/bin> and C</bin>.  If you require a program from
1647 another location, you should provide the full path in the
1648 first parameter.
1649
1650 Shared libraries and data files required by the program
1651 must be available on filesystems which are mounted in the
1652 correct places.  It is the caller's responsibility to ensure
1653 all filesystems that are needed are mounted at the right
1654 locations.");
1655
1656   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1657    [InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 1"]], ["Result1"]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 2"]], ["Result2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1669     InitBasicFS, Always, TestOutputList (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1673     InitBasicFS, Always, TestOutputList (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1677     InitBasicFS, Always, TestOutputList (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1681     InitBasicFS, Always, TestOutputList (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command_lines"; "/test-command 7"]], []);
1685     InitBasicFS, Always, TestOutputList (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command_lines"; "/test-command 8"]], [""]);
1689     InitBasicFS, Always, TestOutputList (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command_lines"; "/test-command 9"]], ["";""]);
1693     InitBasicFS, Always, TestOutputList (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1697     InitBasicFS, Always, TestOutputList (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1701    "run a command, returning lines",
1702    "\
1703 This is the same as C<guestfs_command>, but splits the
1704 result into a list of lines.
1705
1706 See also: C<guestfs_sh_lines>");
1707
1708   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1709    [InitISOFS, Always, TestOutputStruct (
1710       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1711    "get file information",
1712    "\
1713 Returns file information for the given C<path>.
1714
1715 This is the same as the C<stat(2)> system call.");
1716
1717   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1718    [InitISOFS, Always, TestOutputStruct (
1719       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1720    "get file information for a symbolic link",
1721    "\
1722 Returns file information for the given C<path>.
1723
1724 This is the same as C<guestfs_stat> except that if C<path>
1725 is a symbolic link, then the link is stat-ed, not the file it
1726 refers to.
1727
1728 This is the same as the C<lstat(2)> system call.");
1729
1730   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1731    [InitISOFS, Always, TestOutputStruct (
1732       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1733    "get file system statistics",
1734    "\
1735 Returns file system statistics for any mounted file system.
1736 C<path> should be a file or directory in the mounted file system
1737 (typically it is the mount point itself, but it doesn't need to be).
1738
1739 This is the same as the C<statvfs(2)> system call.");
1740
1741   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1742    [], (* XXX test *)
1743    "get ext2/ext3/ext4 superblock details",
1744    "\
1745 This returns the contents of the ext2, ext3 or ext4 filesystem
1746 superblock on C<device>.
1747
1748 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1749 manpage for more details.  The list of fields returned isn't
1750 clearly defined, and depends on both the version of C<tune2fs>
1751 that libguestfs was built against, and the filesystem itself.");
1752
1753   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1754    [InitEmpty, Always, TestOutputTrue (
1755       [["blockdev_setro"; "/dev/sda"];
1756        ["blockdev_getro"; "/dev/sda"]])],
1757    "set block device to read-only",
1758    "\
1759 Sets the block device named C<device> to read-only.
1760
1761 This uses the L<blockdev(8)> command.");
1762
1763   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1764    [InitEmpty, Always, TestOutputFalse (
1765       [["blockdev_setrw"; "/dev/sda"];
1766        ["blockdev_getro"; "/dev/sda"]])],
1767    "set block device to read-write",
1768    "\
1769 Sets the block device named C<device> to read-write.
1770
1771 This uses the L<blockdev(8)> command.");
1772
1773   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1774    [InitEmpty, Always, TestOutputTrue (
1775       [["blockdev_setro"; "/dev/sda"];
1776        ["blockdev_getro"; "/dev/sda"]])],
1777    "is block device set to read-only",
1778    "\
1779 Returns a boolean indicating if the block device is read-only
1780 (true if read-only, false if not).
1781
1782 This uses the L<blockdev(8)> command.");
1783
1784   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1785    [InitEmpty, Always, TestOutputInt (
1786       [["blockdev_getss"; "/dev/sda"]], 512)],
1787    "get sectorsize of block device",
1788    "\
1789 This returns the size of sectors on a block device.
1790 Usually 512, but can be larger for modern devices.
1791
1792 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1793 for that).
1794
1795 This uses the L<blockdev(8)> command.");
1796
1797   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1798    [InitEmpty, Always, TestOutputInt (
1799       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1800    "get blocksize of block device",
1801    "\
1802 This returns the block size of a device.
1803
1804 (Note this is different from both I<size in blocks> and
1805 I<filesystem block size>).
1806
1807 This uses the L<blockdev(8)> command.");
1808
1809   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1810    [], (* XXX test *)
1811    "set blocksize of block device",
1812    "\
1813 This sets the block size of a device.
1814
1815 (Note this is different from both I<size in blocks> and
1816 I<filesystem block size>).
1817
1818 This uses the L<blockdev(8)> command.");
1819
1820   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1821    [InitEmpty, Always, TestOutputInt (
1822       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1823    "get total size of device in 512-byte sectors",
1824    "\
1825 This returns the size of the device in units of 512-byte sectors
1826 (even if the sectorsize isn't 512 bytes ... weird).
1827
1828 See also C<guestfs_blockdev_getss> for the real sector size of
1829 the device, and C<guestfs_blockdev_getsize64> for the more
1830 useful I<size in bytes>.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1835    [InitEmpty, Always, TestOutputInt (
1836       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1837    "get total size of device in bytes",
1838    "\
1839 This returns the size of the device in bytes.
1840
1841 See also C<guestfs_blockdev_getsz>.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1846    [InitEmpty, Always, TestRun
1847       [["blockdev_flushbufs"; "/dev/sda"]]],
1848    "flush device buffers",
1849    "\
1850 This tells the kernel to flush internal buffers associated
1851 with C<device>.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1856    [InitEmpty, Always, TestRun
1857       [["blockdev_rereadpt"; "/dev/sda"]]],
1858    "reread partition table",
1859    "\
1860 Reread the partition table on C<device>.
1861
1862 This uses the L<blockdev(8)> command.");
1863
1864   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1865    [InitBasicFS, Always, TestOutput (
1866       (* Pick a file from cwd which isn't likely to change. *)
1867       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1868        ["checksum"; "md5"; "/COPYING.LIB"]],
1869         Digest.to_hex (Digest.file "COPYING.LIB"))],
1870    "upload a file from the local machine",
1871    "\
1872 Upload local file C<filename> to C<remotefilename> on the
1873 filesystem.
1874
1875 C<filename> can also be a named pipe.
1876
1877 See also C<guestfs_download>.");
1878
1879   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1880    [InitBasicFS, Always, TestOutput (
1881       (* Pick a file from cwd which isn't likely to change. *)
1882       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1883        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1884        ["upload"; "testdownload.tmp"; "/upload"];
1885        ["checksum"; "md5"; "/upload"]],
1886         Digest.to_hex (Digest.file "COPYING.LIB"))],
1887    "download a file to the local machine",
1888    "\
1889 Download file C<remotefilename> and save it as C<filename>
1890 on the local machine.
1891
1892 C<filename> can also be a named pipe.
1893
1894 See also C<guestfs_upload>, C<guestfs_cat>.");
1895
1896   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1897    [InitISOFS, Always, TestOutput (
1898       [["checksum"; "crc"; "/known-3"]], "2891671662");
1899     InitISOFS, Always, TestLastFail (
1900       [["checksum"; "crc"; "/notexists"]]);
1901     InitISOFS, Always, TestOutput (
1902       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1903     InitISOFS, Always, TestOutput (
1904       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1905     InitISOFS, Always, TestOutput (
1906       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1907     InitISOFS, Always, TestOutput (
1908       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1909     InitISOFS, Always, TestOutput (
1910       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1911     InitISOFS, Always, TestOutput (
1912       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1913    "compute MD5, SHAx or CRC checksum of file",
1914    "\
1915 This call computes the MD5, SHAx or CRC checksum of the
1916 file named C<path>.
1917
1918 The type of checksum to compute is given by the C<csumtype>
1919 parameter which must have one of the following values:
1920
1921 =over 4
1922
1923 =item C<crc>
1924
1925 Compute the cyclic redundancy check (CRC) specified by POSIX
1926 for the C<cksum> command.
1927
1928 =item C<md5>
1929
1930 Compute the MD5 hash (using the C<md5sum> program).
1931
1932 =item C<sha1>
1933
1934 Compute the SHA1 hash (using the C<sha1sum> program).
1935
1936 =item C<sha224>
1937
1938 Compute the SHA224 hash (using the C<sha224sum> program).
1939
1940 =item C<sha256>
1941
1942 Compute the SHA256 hash (using the C<sha256sum> program).
1943
1944 =item C<sha384>
1945
1946 Compute the SHA384 hash (using the C<sha384sum> program).
1947
1948 =item C<sha512>
1949
1950 Compute the SHA512 hash (using the C<sha512sum> program).
1951
1952 =back
1953
1954 The checksum is returned as a printable string.");
1955
1956   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1957    [InitBasicFS, Always, TestOutput (
1958       [["tar_in"; "../images/helloworld.tar"; "/"];
1959        ["cat"; "/hello"]], "hello\n")],
1960    "unpack tarfile to directory",
1961    "\
1962 This command uploads and unpacks local file C<tarfile> (an
1963 I<uncompressed> tar file) into C<directory>.
1964
1965 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1966
1967   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1968    [],
1969    "pack directory into tarfile",
1970    "\
1971 This command packs the contents of C<directory> and downloads
1972 it to local file C<tarfile>.
1973
1974 To download a compressed tarball, use C<guestfs_tgz_out>.");
1975
1976   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1977    [InitBasicFS, Always, TestOutput (
1978       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1979        ["cat"; "/hello"]], "hello\n")],
1980    "unpack compressed tarball to directory",
1981    "\
1982 This command uploads and unpacks local file C<tarball> (a
1983 I<gzip compressed> tar file) into C<directory>.
1984
1985 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1986
1987   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1988    [],
1989    "pack directory into compressed tarball",
1990    "\
1991 This command packs the contents of C<directory> and downloads
1992 it to local file C<tarball>.
1993
1994 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1995
1996   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1997    [InitBasicFS, Always, TestLastFail (
1998       [["umount"; "/"];
1999        ["mount_ro"; "/dev/sda1"; "/"];
2000        ["touch"; "/new"]]);
2001     InitBasicFS, Always, TestOutput (
2002       [["write_file"; "/new"; "data"; "0"];
2003        ["umount"; "/"];
2004        ["mount_ro"; "/dev/sda1"; "/"];
2005        ["cat"; "/new"]], "data")],
2006    "mount a guest disk, read-only",
2007    "\
2008 This is the same as the C<guestfs_mount> command, but it
2009 mounts the filesystem with the read-only (I<-o ro>) flag.");
2010
2011   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2012    [],
2013    "mount a guest disk with mount options",
2014    "\
2015 This is the same as the C<guestfs_mount> command, but it
2016 allows you to set the mount options as for the
2017 L<mount(8)> I<-o> flag.");
2018
2019   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2020    [],
2021    "mount a guest disk with mount options and vfstype",
2022    "\
2023 This is the same as the C<guestfs_mount> command, but it
2024 allows you to set both the mount options and the vfstype
2025 as for the L<mount(8)> I<-o> and I<-t> flags.");
2026
2027   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2028    [],
2029    "debugging and internals",
2030    "\
2031 The C<guestfs_debug> command exposes some internals of
2032 C<guestfsd> (the guestfs daemon) that runs inside the
2033 qemu subprocess.
2034
2035 There is no comprehensive help for this command.  You have
2036 to look at the file C<daemon/debug.c> in the libguestfs source
2037 to find out what you can do.");
2038
2039   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2040    [InitEmpty, Always, TestOutputList (
2041       [["part_disk"; "/dev/sda"; "mbr"];
2042        ["pvcreate"; "/dev/sda1"];
2043        ["vgcreate"; "VG"; "/dev/sda1"];
2044        ["lvcreate"; "LV1"; "VG"; "50"];
2045        ["lvcreate"; "LV2"; "VG"; "50"];
2046        ["lvremove"; "/dev/VG/LV1"];
2047        ["lvs"]], ["/dev/VG/LV2"]);
2048     InitEmpty, Always, TestOutputList (
2049       [["part_disk"; "/dev/sda"; "mbr"];
2050        ["pvcreate"; "/dev/sda1"];
2051        ["vgcreate"; "VG"; "/dev/sda1"];
2052        ["lvcreate"; "LV1"; "VG"; "50"];
2053        ["lvcreate"; "LV2"; "VG"; "50"];
2054        ["lvremove"; "/dev/VG"];
2055        ["lvs"]], []);
2056     InitEmpty, Always, TestOutputList (
2057       [["part_disk"; "/dev/sda"; "mbr"];
2058        ["pvcreate"; "/dev/sda1"];
2059        ["vgcreate"; "VG"; "/dev/sda1"];
2060        ["lvcreate"; "LV1"; "VG"; "50"];
2061        ["lvcreate"; "LV2"; "VG"; "50"];
2062        ["lvremove"; "/dev/VG"];
2063        ["vgs"]], ["VG"])],
2064    "remove an LVM logical volume",
2065    "\
2066 Remove an LVM logical volume C<device>, where C<device> is
2067 the path to the LV, such as C</dev/VG/LV>.
2068
2069 You can also remove all LVs in a volume group by specifying
2070 the VG name, C</dev/VG>.");
2071
2072   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2073    [InitEmpty, Always, TestOutputList (
2074       [["part_disk"; "/dev/sda"; "mbr"];
2075        ["pvcreate"; "/dev/sda1"];
2076        ["vgcreate"; "VG"; "/dev/sda1"];
2077        ["lvcreate"; "LV1"; "VG"; "50"];
2078        ["lvcreate"; "LV2"; "VG"; "50"];
2079        ["vgremove"; "VG"];
2080        ["lvs"]], []);
2081     InitEmpty, Always, TestOutputList (
2082       [["part_disk"; "/dev/sda"; "mbr"];
2083        ["pvcreate"; "/dev/sda1"];
2084        ["vgcreate"; "VG"; "/dev/sda1"];
2085        ["lvcreate"; "LV1"; "VG"; "50"];
2086        ["lvcreate"; "LV2"; "VG"; "50"];
2087        ["vgremove"; "VG"];
2088        ["vgs"]], [])],
2089    "remove an LVM volume group",
2090    "\
2091 Remove an LVM volume group C<vgname>, (for example C<VG>).
2092
2093 This also forcibly removes all logical volumes in the volume
2094 group (if any).");
2095
2096   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2097    [InitEmpty, Always, TestOutputListOfDevices (
2098       [["part_disk"; "/dev/sda"; "mbr"];
2099        ["pvcreate"; "/dev/sda1"];
2100        ["vgcreate"; "VG"; "/dev/sda1"];
2101        ["lvcreate"; "LV1"; "VG"; "50"];
2102        ["lvcreate"; "LV2"; "VG"; "50"];
2103        ["vgremove"; "VG"];
2104        ["pvremove"; "/dev/sda1"];
2105        ["lvs"]], []);
2106     InitEmpty, Always, TestOutputListOfDevices (
2107       [["part_disk"; "/dev/sda"; "mbr"];
2108        ["pvcreate"; "/dev/sda1"];
2109        ["vgcreate"; "VG"; "/dev/sda1"];
2110        ["lvcreate"; "LV1"; "VG"; "50"];
2111        ["lvcreate"; "LV2"; "VG"; "50"];
2112        ["vgremove"; "VG"];
2113        ["pvremove"; "/dev/sda1"];
2114        ["vgs"]], []);
2115     InitEmpty, Always, TestOutputListOfDevices (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["vgremove"; "VG"];
2122        ["pvremove"; "/dev/sda1"];
2123        ["pvs"]], [])],
2124    "remove an LVM physical volume",
2125    "\
2126 This wipes a physical volume C<device> so that LVM will no longer
2127 recognise it.
2128
2129 The implementation uses the C<pvremove> command which refuses to
2130 wipe physical volumes that contain any volume groups, so you have
2131 to remove those first.");
2132
2133   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2134    [InitBasicFS, Always, TestOutput (
2135       [["set_e2label"; "/dev/sda1"; "testlabel"];
2136        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2137    "set the ext2/3/4 filesystem label",
2138    "\
2139 This sets the ext2/3/4 filesystem label of the filesystem on
2140 C<device> to C<label>.  Filesystem labels are limited to
2141 16 characters.
2142
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2144 to return the existing label on a filesystem.");
2145
2146   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2147    [],
2148    "get the ext2/3/4 filesystem label",
2149    "\
2150 This returns the ext2/3/4 filesystem label of the filesystem on
2151 C<device>.");
2152
2153   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2154    (let uuid = uuidgen () in
2155     [InitBasicFS, Always, TestOutput (
2156        [["set_e2uuid"; "/dev/sda1"; uuid];
2157         ["get_e2uuid"; "/dev/sda1"]], uuid);
2158      InitBasicFS, Always, TestOutput (
2159        [["set_e2uuid"; "/dev/sda1"; "clear"];
2160         ["get_e2uuid"; "/dev/sda1"]], "");
2161      (* We can't predict what UUIDs will be, so just check the commands run. *)
2162      InitBasicFS, Always, TestRun (
2163        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2164      InitBasicFS, Always, TestRun (
2165        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2166    "set the ext2/3/4 filesystem UUID",
2167    "\
2168 This sets the ext2/3/4 filesystem UUID of the filesystem on
2169 C<device> to C<uuid>.  The format of the UUID and alternatives
2170 such as C<clear>, C<random> and C<time> are described in the
2171 L<tune2fs(8)> manpage.
2172
2173 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2174 to return the existing UUID of a filesystem.");
2175
2176   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2177    [],
2178    "get the ext2/3/4 filesystem UUID",
2179    "\
2180 This returns the ext2/3/4 filesystem UUID of the filesystem on
2181 C<device>.");
2182
2183   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2184    [InitBasicFS, Always, TestOutputInt (
2185       [["umount"; "/dev/sda1"];
2186        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2187     InitBasicFS, Always, TestOutputInt (
2188       [["umount"; "/dev/sda1"];
2189        ["zero"; "/dev/sda1"];
2190        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2191    "run the filesystem checker",
2192    "\
2193 This runs the filesystem checker (fsck) on C<device> which
2194 should have filesystem type C<fstype>.
2195
2196 The returned integer is the status.  See L<fsck(8)> for the
2197 list of status codes from C<fsck>.
2198
2199 Notes:
2200
2201 =over 4
2202
2203 =item *
2204
2205 Multiple status codes can be summed together.
2206
2207 =item *
2208
2209 A non-zero return code can mean \"success\", for example if
2210 errors have been corrected on the filesystem.
2211
2212 =item *
2213
2214 Checking or repairing NTFS volumes is not supported
2215 (by linux-ntfs).
2216
2217 =back
2218
2219 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2220
2221   ("zero", (RErr, [Device "device"]), 85, [],
2222    [InitBasicFS, Always, TestOutput (
2223       [["umount"; "/dev/sda1"];
2224        ["zero"; "/dev/sda1"];
2225        ["file"; "/dev/sda1"]], "data")],
2226    "write zeroes to the device",
2227    "\
2228 This command writes zeroes over the first few blocks of C<device>.
2229
2230 How many blocks are zeroed isn't specified (but it's I<not> enough
2231 to securely wipe the device).  It should be sufficient to remove
2232 any partition tables, filesystem superblocks and so on.
2233
2234 See also: C<guestfs_scrub_device>.");
2235
2236   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2237    (* Test disabled because grub-install incompatible with virtio-blk driver.
2238     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2239     *)
2240    [InitBasicFS, Disabled, TestOutputTrue (
2241       [["grub_install"; "/"; "/dev/sda1"];
2242        ["is_dir"; "/boot"]])],
2243    "install GRUB",
2244    "\
2245 This command installs GRUB (the Grand Unified Bootloader) on
2246 C<device>, with the root directory being C<root>.");
2247
2248   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2249    [InitBasicFS, Always, TestOutput (
2250       [["write_file"; "/old"; "file content"; "0"];
2251        ["cp"; "/old"; "/new"];
2252        ["cat"; "/new"]], "file content");
2253     InitBasicFS, Always, TestOutputTrue (
2254       [["write_file"; "/old"; "file content"; "0"];
2255        ["cp"; "/old"; "/new"];
2256        ["is_file"; "/old"]]);
2257     InitBasicFS, Always, TestOutput (
2258       [["write_file"; "/old"; "file content"; "0"];
2259        ["mkdir"; "/dir"];
2260        ["cp"; "/old"; "/dir/new"];
2261        ["cat"; "/dir/new"]], "file content")],
2262    "copy a file",
2263    "\
2264 This copies a file from C<src> to C<dest> where C<dest> is
2265 either a destination filename or destination directory.");
2266
2267   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2268    [InitBasicFS, Always, TestOutput (
2269       [["mkdir"; "/olddir"];
2270        ["mkdir"; "/newdir"];
2271        ["write_file"; "/olddir/file"; "file content"; "0"];
2272        ["cp_a"; "/olddir"; "/newdir"];
2273        ["cat"; "/newdir/olddir/file"]], "file content")],
2274    "copy a file or directory recursively",
2275    "\
2276 This copies a file or directory from C<src> to C<dest>
2277 recursively using the C<cp -a> command.");
2278
2279   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2280    [InitBasicFS, Always, TestOutput (
2281       [["write_file"; "/old"; "file content"; "0"];
2282        ["mv"; "/old"; "/new"];
2283        ["cat"; "/new"]], "file content");
2284     InitBasicFS, Always, TestOutputFalse (
2285       [["write_file"; "/old"; "file content"; "0"];
2286        ["mv"; "/old"; "/new"];
2287        ["is_file"; "/old"]])],
2288    "move a file",
2289    "\
2290 This moves a file from C<src> to C<dest> where C<dest> is
2291 either a destination filename or destination directory.");
2292
2293   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2294    [InitEmpty, Always, TestRun (
2295       [["drop_caches"; "3"]])],
2296    "drop kernel page cache, dentries and inodes",
2297    "\
2298 This instructs the guest kernel to drop its page cache,
2299 and/or dentries and inode caches.  The parameter C<whattodrop>
2300 tells the kernel what precisely to drop, see
2301 L<http://linux-mm.org/Drop_Caches>
2302
2303 Setting C<whattodrop> to 3 should drop everything.
2304
2305 This automatically calls L<sync(2)> before the operation,
2306 so that the maximum guest memory is freed.");
2307
2308   ("dmesg", (RString "kmsgs", []), 91, [],
2309    [InitEmpty, Always, TestRun (
2310       [["dmesg"]])],
2311    "return kernel messages",
2312    "\
2313 This returns the kernel messages (C<dmesg> output) from
2314 the guest kernel.  This is sometimes useful for extended
2315 debugging of problems.
2316
2317 Another way to get the same information is to enable
2318 verbose messages with C<guestfs_set_verbose> or by setting
2319 the environment variable C<LIBGUESTFS_DEBUG=1> before
2320 running the program.");
2321
2322   ("ping_daemon", (RErr, []), 92, [],
2323    [InitEmpty, Always, TestRun (
2324       [["ping_daemon"]])],
2325    "ping the guest daemon",
2326    "\
2327 This is a test probe into the guestfs daemon running inside
2328 the qemu subprocess.  Calling this function checks that the
2329 daemon responds to the ping message, without affecting the daemon
2330 or attached block device(s) in any other way.");
2331
2332   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2333    [InitBasicFS, Always, TestOutputTrue (
2334       [["write_file"; "/file1"; "contents of a file"; "0"];
2335        ["cp"; "/file1"; "/file2"];
2336        ["equal"; "/file1"; "/file2"]]);
2337     InitBasicFS, Always, TestOutputFalse (
2338       [["write_file"; "/file1"; "contents of a file"; "0"];
2339        ["write_file"; "/file2"; "contents of another file"; "0"];
2340        ["equal"; "/file1"; "/file2"]]);
2341     InitBasicFS, Always, TestLastFail (
2342       [["equal"; "/file1"; "/file2"]])],
2343    "test if two files have equal contents",
2344    "\
2345 This compares the two files C<file1> and C<file2> and returns
2346 true if their content is exactly equal, or false otherwise.
2347
2348 The external L<cmp(1)> program is used for the comparison.");
2349
2350   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2351    [InitISOFS, Always, TestOutputList (
2352       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2353     InitISOFS, Always, TestOutputList (
2354       [["strings"; "/empty"]], [])],
2355    "print the printable strings in a file",
2356    "\
2357 This runs the L<strings(1)> command on a file and returns
2358 the list of printable strings found.");
2359
2360   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2361    [InitISOFS, Always, TestOutputList (
2362       [["strings_e"; "b"; "/known-5"]], []);
2363     InitBasicFS, Disabled, TestOutputList (
2364       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2365        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2366    "print the printable strings in a file",
2367    "\
2368 This is like the C<guestfs_strings> command, but allows you to
2369 specify the encoding.
2370
2371 See the L<strings(1)> manpage for the full list of encodings.
2372
2373 Commonly useful encodings are C<l> (lower case L) which will
2374 show strings inside Windows/x86 files.
2375
2376 The returned strings are transcoded to UTF-8.");
2377
2378   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2379    [InitISOFS, Always, TestOutput (
2380       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2381     (* Test for RHBZ#501888c2 regression which caused large hexdump
2382      * commands to segfault.
2383      *)
2384     InitISOFS, Always, TestRun (
2385       [["hexdump"; "/100krandom"]])],
2386    "dump a file in hexadecimal",
2387    "\
2388 This runs C<hexdump -C> on the given C<path>.  The result is
2389 the human-readable, canonical hex dump of the file.");
2390
2391   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2392    [InitNone, Always, TestOutput (
2393       [["part_disk"; "/dev/sda"; "mbr"];
2394        ["mkfs"; "ext3"; "/dev/sda1"];
2395        ["mount"; "/dev/sda1"; "/"];
2396        ["write_file"; "/new"; "test file"; "0"];
2397        ["umount"; "/dev/sda1"];
2398        ["zerofree"; "/dev/sda1"];
2399        ["mount"; "/dev/sda1"; "/"];
2400        ["cat"; "/new"]], "test file")],
2401    "zero unused inodes and disk blocks on ext2/3 filesystem",
2402    "\
2403 This runs the I<zerofree> program on C<device>.  This program
2404 claims to zero unused inodes and disk blocks on an ext2/3
2405 filesystem, thus making it possible to compress the filesystem
2406 more effectively.
2407
2408 You should B<not> run this program if the filesystem is
2409 mounted.
2410
2411 It is possible that using this program can damage the filesystem
2412 or data on the filesystem.");
2413
2414   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2415    [],
2416    "resize an LVM physical volume",
2417    "\
2418 This resizes (expands or shrinks) an existing LVM physical
2419 volume to match the new size of the underlying device.");
2420
2421   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2422                        Int "cyls"; Int "heads"; Int "sectors";
2423                        String "line"]), 99, [DangerWillRobinson],
2424    [],
2425    "modify a single partition on a block device",
2426    "\
2427 This runs L<sfdisk(8)> option to modify just the single
2428 partition C<n> (note: C<n> counts from 1).
2429
2430 For other parameters, see C<guestfs_sfdisk>.  You should usually
2431 pass C<0> for the cyls/heads/sectors parameters.
2432
2433 See also: C<guestfs_part_add>");
2434
2435   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2436    [],
2437    "display the partition table",
2438    "\
2439 This displays the partition table on C<device>, in the
2440 human-readable output of the L<sfdisk(8)> command.  It is
2441 not intended to be parsed.
2442
2443 See also: C<guestfs_part_list>");
2444
2445   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2446    [],
2447    "display the kernel geometry",
2448    "\
2449 This displays the kernel's idea of the geometry of C<device>.
2450
2451 The result is in human-readable format, and not designed to
2452 be parsed.");
2453
2454   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2455    [],
2456    "display the disk geometry from the partition table",
2457    "\
2458 This displays the disk geometry of C<device> read from the
2459 partition table.  Especially in the case where the underlying
2460 block device has been resized, this can be different from the
2461 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2462
2463 The result is in human-readable format, and not designed to
2464 be parsed.");
2465
2466   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2467    [],
2468    "activate or deactivate all volume groups",
2469    "\
2470 This command activates or (if C<activate> is false) deactivates
2471 all logical volumes in all volume groups.
2472 If activated, then they are made known to the
2473 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2474 then those devices disappear.
2475
2476 This command is the same as running C<vgchange -a y|n>");
2477
2478   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2479    [],
2480    "activate or deactivate some volume groups",
2481    "\
2482 This command activates or (if C<activate> is false) deactivates
2483 all logical volumes in the listed volume groups C<volgroups>.
2484 If activated, then they are made known to the
2485 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2486 then those devices disappear.
2487
2488 This command is the same as running C<vgchange -a y|n volgroups...>
2489
2490 Note that if C<volgroups> is an empty list then B<all> volume groups
2491 are activated or deactivated.");
2492
2493   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2494    [InitNone, Always, TestOutput (
2495       [["part_disk"; "/dev/sda"; "mbr"];
2496        ["pvcreate"; "/dev/sda1"];
2497        ["vgcreate"; "VG"; "/dev/sda1"];
2498        ["lvcreate"; "LV"; "VG"; "10"];
2499        ["mkfs"; "ext2"; "/dev/VG/LV"];
2500        ["mount"; "/dev/VG/LV"; "/"];
2501        ["write_file"; "/new"; "test content"; "0"];
2502        ["umount"; "/"];
2503        ["lvresize"; "/dev/VG/LV"; "20"];
2504        ["e2fsck_f"; "/dev/VG/LV"];
2505        ["resize2fs"; "/dev/VG/LV"];
2506        ["mount"; "/dev/VG/LV"; "/"];
2507        ["cat"; "/new"]], "test content")],
2508    "resize an LVM logical volume",
2509    "\
2510 This resizes (expands or shrinks) an existing LVM logical
2511 volume to C<mbytes>.  When reducing, data in the reduced part
2512 is lost.");
2513
2514   ("resize2fs", (RErr, [Device "device"]), 106, [],
2515    [], (* lvresize tests this *)
2516    "resize an ext2/ext3 filesystem",
2517    "\
2518 This resizes an ext2 or ext3 filesystem to match the size of
2519 the underlying device.
2520
2521 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2522 on the C<device> before calling this command.  For unknown reasons
2523 C<resize2fs> sometimes gives an error about this and sometimes not.
2524 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2525 calling this function.");
2526
2527   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2528    [InitBasicFS, Always, TestOutputList (
2529       [["find"; "/"]], ["lost+found"]);
2530     InitBasicFS, Always, TestOutputList (
2531       [["touch"; "/a"];
2532        ["mkdir"; "/b"];
2533        ["touch"; "/b/c"];
2534        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2535     InitBasicFS, Always, TestOutputList (
2536       [["mkdir_p"; "/a/b/c"];
2537        ["touch"; "/a/b/c/d"];
2538        ["find"; "/a/b/"]], ["c"; "c/d"])],
2539    "find all files and directories",
2540    "\
2541 This command lists out all files and directories, recursively,
2542 starting at C<directory>.  It is essentially equivalent to
2543 running the shell command C<find directory -print> but some
2544 post-processing happens on the output, described below.
2545
2546 This returns a list of strings I<without any prefix>.  Thus
2547 if the directory structure was:
2548
2549  /tmp/a
2550  /tmp/b
2551  /tmp/c/d
2552
2553 then the returned list from C<guestfs_find> C</tmp> would be
2554 4 elements:
2555
2556  a
2557  b
2558  c
2559  c/d
2560
2561 If C<directory> is not a directory, then this command returns
2562 an error.
2563
2564 The returned list is sorted.
2565
2566 See also C<guestfs_find0>.");
2567
2568   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2569    [], (* lvresize tests this *)
2570    "check an ext2/ext3 filesystem",
2571    "\
2572 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2573 filesystem checker on C<device>, noninteractively (C<-p>),
2574 even if the filesystem appears to be clean (C<-f>).
2575
2576 This command is only needed because of C<guestfs_resize2fs>
2577 (q.v.).  Normally you should use C<guestfs_fsck>.");
2578
2579   ("sleep", (RErr, [Int "secs"]), 109, [],
2580    [InitNone, Always, TestRun (
2581       [["sleep"; "1"]])],
2582    "sleep for some seconds",
2583    "\
2584 Sleep for C<secs> seconds.");
2585
2586   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2587    [InitNone, Always, TestOutputInt (
2588       [["part_disk"; "/dev/sda"; "mbr"];
2589        ["mkfs"; "ntfs"; "/dev/sda1"];
2590        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2591     InitNone, Always, TestOutputInt (
2592       [["part_disk"; "/dev/sda"; "mbr"];
2593        ["mkfs"; "ext2"; "/dev/sda1"];
2594        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2595    "probe NTFS volume",
2596    "\
2597 This command runs the L<ntfs-3g.probe(8)> command which probes
2598 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2599 be mounted read-write, and some cannot be mounted at all).
2600
2601 C<rw> is a boolean flag.  Set it to true if you want to test
2602 if the volume can be mounted read-write.  Set it to false if
2603 you want to test if the volume can be mounted read-only.
2604
2605 The return value is an integer which C<0> if the operation
2606 would succeed, or some non-zero value documented in the
2607 L<ntfs-3g.probe(8)> manual page.");
2608
2609   ("sh", (RString "output", [String "command"]), 111, [],
2610    [], (* XXX needs tests *)
2611    "run a command via the shell",
2612    "\
2613 This call runs a command from the guest filesystem via the
2614 guest's C</bin/sh>.
2615
2616 This is like C<guestfs_command>, but passes the command to:
2617
2618  /bin/sh -c \"command\"
2619
2620 Depending on the guest's shell, this usually results in
2621 wildcards being expanded, shell expressions being interpolated
2622 and so on.
2623
2624 All the provisos about C<guestfs_command> apply to this call.");
2625
2626   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2627    [], (* XXX needs tests *)
2628    "run a command via the shell returning lines",
2629    "\
2630 This is the same as C<guestfs_sh>, but splits the result
2631 into a list of lines.
2632
2633 See also: C<guestfs_command_lines>");
2634
2635   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2636    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2637     * code in stubs.c, since all valid glob patterns must start with "/".
2638     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2639     *)
2640    [InitBasicFS, Always, TestOutputList (
2641       [["mkdir_p"; "/a/b/c"];
2642        ["touch"; "/a/b/c/d"];
2643        ["touch"; "/a/b/c/e"];
2644        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2645     InitBasicFS, Always, TestOutputList (
2646       [["mkdir_p"; "/a/b/c"];
2647        ["touch"; "/a/b/c/d"];
2648        ["touch"; "/a/b/c/e"];
2649        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2650     InitBasicFS, Always, TestOutputList (
2651       [["mkdir_p"; "/a/b/c"];
2652        ["touch"; "/a/b/c/d"];
2653        ["touch"; "/a/b/c/e"];
2654        ["glob_expand"; "/a/*/x/*"]], [])],
2655    "expand a wildcard path",
2656    "\
2657 This command searches for all the pathnames matching
2658 C<pattern> according to the wildcard expansion rules
2659 used by the shell.
2660
2661 If no paths match, then this returns an empty list
2662 (note: not an error).
2663
2664 It is just a wrapper around the C L<glob(3)> function
2665 with flags C<GLOB_MARK|GLOB_BRACE>.
2666 See that manual page for more details.");
2667
2668   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2669    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2670       [["scrub_device"; "/dev/sdc"]])],
2671    "scrub (securely wipe) a device",
2672    "\
2673 This command writes patterns over C<device> to make data retrieval
2674 more difficult.
2675
2676 It is an interface to the L<scrub(1)> program.  See that
2677 manual page for more details.");
2678
2679   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2680    [InitBasicFS, Always, TestRun (
2681       [["write_file"; "/file"; "content"; "0"];
2682        ["scrub_file"; "/file"]])],
2683    "scrub (securely wipe) a file",
2684    "\
2685 This command writes patterns over a file to make data retrieval
2686 more difficult.
2687
2688 The file is I<removed> after scrubbing.
2689
2690 It is an interface to the L<scrub(1)> program.  See that
2691 manual page for more details.");
2692
2693   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2694    [], (* XXX needs testing *)
2695    "scrub (securely wipe) free space",
2696    "\
2697 This command creates the directory C<dir> and then fills it
2698 with files until the filesystem is full, and scrubs the files
2699 as for C<guestfs_scrub_file>, and deletes them.
2700 The intention is to scrub any free space on the partition
2701 containing C<dir>.
2702
2703 It is an interface to the L<scrub(1)> program.  See that
2704 manual page for more details.");
2705
2706   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2707    [InitBasicFS, Always, TestRun (
2708       [["mkdir"; "/tmp"];
2709        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2710    "create a temporary directory",
2711    "\
2712 This command creates a temporary directory.  The
2713 C<template> parameter should be a full pathname for the
2714 temporary directory name with the final six characters being
2715 \"XXXXXX\".
2716
2717 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2718 the second one being suitable for Windows filesystems.
2719
2720 The name of the temporary directory that was created
2721 is returned.
2722
2723 The temporary directory is created with mode 0700
2724 and is owned by root.
2725
2726 The caller is responsible for deleting the temporary
2727 directory and its contents after use.
2728
2729 See also: L<mkdtemp(3)>");
2730
2731   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2732    [InitISOFS, Always, TestOutputInt (
2733       [["wc_l"; "/10klines"]], 10000)],
2734    "count lines in a file",
2735    "\
2736 This command counts the lines in a file, using the
2737 C<wc -l> external command.");
2738
2739   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2740    [InitISOFS, Always, TestOutputInt (
2741       [["wc_w"; "/10klines"]], 10000)],
2742    "count words in a file",
2743    "\
2744 This command counts the words in a file, using the
2745 C<wc -w> external command.");
2746
2747   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2748    [InitISOFS, Always, TestOutputInt (
2749       [["wc_c"; "/100kallspaces"]], 102400)],
2750    "count characters in a file",
2751    "\
2752 This command counts the characters in a file, using the
2753 C<wc -c> external command.");
2754
2755   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2756    [InitISOFS, Always, TestOutputList (
2757       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2758    "return first 10 lines of a file",
2759    "\
2760 This command returns up to the first 10 lines of a file as
2761 a list of strings.");
2762
2763   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2764    [InitISOFS, Always, TestOutputList (
2765       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2766     InitISOFS, Always, TestOutputList (
2767       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2768     InitISOFS, Always, TestOutputList (
2769       [["head_n"; "0"; "/10klines"]], [])],
2770    "return first N lines of a file",
2771    "\
2772 If the parameter C<nrlines> is a positive number, this returns the first
2773 C<nrlines> lines of the file C<path>.
2774
2775 If the parameter C<nrlines> is a negative number, this returns lines
2776 from the file C<path>, excluding the last C<nrlines> lines.
2777
2778 If the parameter C<nrlines> is zero, this returns an empty list.");
2779
2780   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2781    [InitISOFS, Always, TestOutputList (
2782       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2783    "return last 10 lines of a file",
2784    "\
2785 This command returns up to the last 10 lines of a file as
2786 a list of strings.");
2787
2788   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2789    [InitISOFS, Always, TestOutputList (
2790       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2791     InitISOFS, Always, TestOutputList (
2792       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2793     InitISOFS, Always, TestOutputList (
2794       [["tail_n"; "0"; "/10klines"]], [])],
2795    "return last N lines of a file",
2796    "\
2797 If the parameter C<nrlines> is a positive number, this returns the last
2798 C<nrlines> lines of the file C<path>.
2799
2800 If the parameter C<nrlines> is a negative number, this returns lines
2801 from the file C<path>, starting with the C<-nrlines>th line.
2802
2803 If the parameter C<nrlines> is zero, this returns an empty list.");
2804
2805   ("df", (RString "output", []), 125, [],
2806    [], (* XXX Tricky to test because it depends on the exact format
2807         * of the 'df' command and other imponderables.
2808         *)
2809    "report file system disk space usage",
2810    "\
2811 This command runs the C<df> command to report disk space used.
2812
2813 This command is mostly useful for interactive sessions.  It
2814 is I<not> intended that you try to parse the output string.
2815 Use C<statvfs> from programs.");
2816
2817   ("df_h", (RString "output", []), 126, [],
2818    [], (* XXX Tricky to test because it depends on the exact format
2819         * of the 'df' command and other imponderables.
2820         *)
2821    "report file system disk space usage (human readable)",
2822    "\
2823 This command runs the C<df -h> command to report disk space used
2824 in human-readable format.
2825
2826 This command is mostly useful for interactive sessions.  It
2827 is I<not> intended that you try to parse the output string.
2828 Use C<statvfs> from programs.");
2829
2830   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2831    [InitISOFS, Always, TestOutputInt (
2832       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2833    "estimate file space usage",
2834    "\
2835 This command runs the C<du -s> command to estimate file space
2836 usage for C<path>.
2837
2838 C<path> can be a file or a directory.  If C<path> is a directory
2839 then the estimate includes the contents of the directory and all
2840 subdirectories (recursively).
2841
2842 The result is the estimated size in I<kilobytes>
2843 (ie. units of 1024 bytes).");
2844
2845   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2846    [InitISOFS, Always, TestOutputList (
2847       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2848    "list files in an initrd",
2849    "\
2850 This command lists out files contained in an initrd.
2851
2852 The files are listed without any initial C</> character.  The
2853 files are listed in the order they appear (not necessarily
2854 alphabetical).  Directory names are listed as separate items.
2855
2856 Old Linux kernels (2.4 and earlier) used a compressed ext2
2857 filesystem as initrd.  We I<only> support the newer initramfs
2858 format (compressed cpio files).");
2859
2860   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2861    [],
2862    "mount a file using the loop device",
2863    "\
2864 This command lets you mount C<file> (a filesystem image
2865 in a file) on a mount point.  It is entirely equivalent to
2866 the command C<mount -o loop file mountpoint>.");
2867
2868   ("mkswap", (RErr, [Device "device"]), 130, [],
2869    [InitEmpty, Always, TestRun (
2870       [["part_disk"; "/dev/sda"; "mbr"];
2871        ["mkswap"; "/dev/sda1"]])],
2872    "create a swap partition",
2873    "\
2874 Create a swap partition on C<device>.");
2875
2876   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2877    [InitEmpty, Always, TestRun (
2878       [["part_disk"; "/dev/sda"; "mbr"];
2879        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2880    "create a swap partition with a label",
2881    "\
2882 Create a swap partition on C<device> with label C<label>.
2883
2884 Note that you cannot attach a swap label to a block device
2885 (eg. C</dev/sda>), just to a partition.  This appears to be
2886 a limitation of the kernel or swap tools.");
2887
2888   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2889    (let uuid = uuidgen () in
2890     [InitEmpty, Always, TestRun (
2891        [["part_disk"; "/dev/sda"; "mbr"];
2892         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2893    "create a swap partition with an explicit UUID",
2894    "\
2895 Create a swap partition on C<device> with UUID C<uuid>.");
2896
2897   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2898    [InitBasicFS, Always, TestOutputStruct (
2899       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2900        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2901        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2902     InitBasicFS, Always, TestOutputStruct (
2903       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2904        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2905    "make block, character or FIFO devices",
2906    "\
2907 This call creates block or character special devices, or
2908 named pipes (FIFOs).
2909
2910 The C<mode> parameter should be the mode, using the standard
2911 constants.  C<devmajor> and C<devminor> are the
2912 device major and minor numbers, only used when creating block
2913 and character special devices.");
2914
2915   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2916    [InitBasicFS, Always, TestOutputStruct (
2917       [["mkfifo"; "0o777"; "/node"];
2918        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2919    "make FIFO (named pipe)",
2920    "\
2921 This call creates a FIFO (named pipe) called C<path> with
2922 mode C<mode>.  It is just a convenient wrapper around
2923 C<guestfs_mknod>.");
2924
2925   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2926    [InitBasicFS, Always, TestOutputStruct (
2927       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2928        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2929    "make block device node",
2930    "\
2931 This call creates a block device node called C<path> with
2932 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2933 It is just a convenient wrapper around C<guestfs_mknod>.");
2934
2935   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2936    [InitBasicFS, Always, TestOutputStruct (
2937       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2938        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2939    "make char device node",
2940    "\
2941 This call creates a char device node called C<path> with
2942 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2943 It is just a convenient wrapper around C<guestfs_mknod>.");
2944
2945   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2946    [], (* XXX umask is one of those stateful things that we should
2947         * reset between each test.
2948         *)
2949    "set file mode creation mask (umask)",
2950    "\
2951 This function sets the mask used for creating new files and
2952 device nodes to C<mask & 0777>.
2953
2954 Typical umask values would be C<022> which creates new files
2955 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2956 C<002> which creates new files with permissions like
2957 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2958
2959 The default umask is C<022>.  This is important because it
2960 means that directories and device nodes will be created with
2961 C<0644> or C<0755> mode even if you specify C<0777>.
2962
2963 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2964
2965 This call returns the previous umask.");
2966
2967   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2968    [],
2969    "read directories entries",
2970    "\
2971 This returns the list of directory entries in directory C<dir>.
2972
2973 All entries in the directory are returned, including C<.> and
2974 C<..>.  The entries are I<not> sorted, but returned in the same
2975 order as the underlying filesystem.
2976
2977 Also this call returns basic file type information about each
2978 file.  The C<ftyp> field will contain one of the following characters:
2979
2980 =over 4
2981
2982 =item 'b'
2983
2984 Block special
2985
2986 =item 'c'
2987
2988 Char special
2989
2990 =item 'd'
2991
2992 Directory
2993
2994 =item 'f'
2995
2996 FIFO (named pipe)
2997
2998 =item 'l'
2999
3000 Symbolic link
3001
3002 =item 'r'
3003
3004 Regular file
3005
3006 =item 's'
3007
3008 Socket
3009
3010 =item 'u'
3011
3012 Unknown file type
3013
3014 =item '?'
3015
3016 The L<readdir(3)> returned a C<d_type> field with an
3017 unexpected value
3018
3019 =back
3020
3021 This function is primarily intended for use by programs.  To
3022 get a simple list of names, use C<guestfs_ls>.  To get a printable
3023 directory for human consumption, use C<guestfs_ll>.");
3024
3025   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3026    [],
3027    "create partitions on a block device",
3028    "\
3029 This is a simplified interface to the C<guestfs_sfdisk>
3030 command, where partition sizes are specified in megabytes
3031 only (rounded to the nearest cylinder) and you don't need
3032 to specify the cyls, heads and sectors parameters which
3033 were rarely if ever used anyway.
3034
3035 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3036 and C<guestfs_part_disk>");
3037
3038   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3039    [],
3040    "determine file type inside a compressed file",
3041    "\
3042 This command runs C<file> after first decompressing C<path>
3043 using C<method>.
3044
3045 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3046
3047 Since 1.0.63, use C<guestfs_file> instead which can now
3048 process compressed files.");
3049
3050   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3051    [],
3052    "list extended attributes of a file or directory",
3053    "\
3054 This call lists the extended attributes of the file or directory
3055 C<path>.
3056
3057 At the system call level, this is a combination of the
3058 L<listxattr(2)> and L<getxattr(2)> calls.
3059
3060 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3061
3062   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3063    [],
3064    "list extended attributes of a file or directory",
3065    "\
3066 This is the same as C<guestfs_getxattrs>, but if C<path>
3067 is a symbolic link, then it returns the extended attributes
3068 of the link itself.");
3069
3070   ("setxattr", (RErr, [String "xattr";
3071                        String "val"; Int "vallen"; (* will be BufferIn *)
3072                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3073    [],
3074    "set extended attribute of a file or directory",
3075    "\
3076 This call sets the extended attribute named C<xattr>
3077 of the file C<path> to the value C<val> (of length C<vallen>).
3078 The value is arbitrary 8 bit data.
3079
3080 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3081
3082   ("lsetxattr", (RErr, [String "xattr";
3083                         String "val"; Int "vallen"; (* will be BufferIn *)
3084                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3085    [],
3086    "set extended attribute of a file or directory",
3087    "\
3088 This is the same as C<guestfs_setxattr>, but if C<path>
3089 is a symbolic link, then it sets an extended attribute
3090 of the link itself.");
3091
3092   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3093    [],
3094    "remove extended attribute of a file or directory",
3095    "\
3096 This call removes the extended attribute named C<xattr>
3097 of the file C<path>.
3098
3099 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3100
3101   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3102    [],
3103    "remove extended attribute of a file or directory",
3104    "\
3105 This is the same as C<guestfs_removexattr>, but if C<path>
3106 is a symbolic link, then it removes an extended attribute
3107 of the link itself.");
3108
3109   ("mountpoints", (RHashtable "mps", []), 147, [],
3110    [],
3111    "show mountpoints",
3112    "\
3113 This call is similar to C<guestfs_mounts>.  That call returns
3114 a list of devices.  This one returns a hash table (map) of
3115 device name to directory where the device is mounted.");
3116
3117   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3118   (* This is a special case: while you would expect a parameter
3119    * of type "Pathname", that doesn't work, because it implies
3120    * NEED_ROOT in the generated calling code in stubs.c, and
3121    * this function cannot use NEED_ROOT.
3122    *)
3123    [],
3124    "create a mountpoint",
3125    "\
3126 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3127 specialized calls that can be used to create extra mountpoints
3128 before mounting the first filesystem.
3129
3130 These calls are I<only> necessary in some very limited circumstances,
3131 mainly the case where you want to mount a mix of unrelated and/or
3132 read-only filesystems together.
3133
3134 For example, live CDs often contain a \"Russian doll\" nest of
3135 filesystems, an ISO outer layer, with a squashfs image inside, with
3136 an ext2/3 image inside that.  You can unpack this as follows
3137 in guestfish:
3138
3139  add-ro Fedora-11-i686-Live.iso
3140  run
3141  mkmountpoint /cd
3142  mkmountpoint /squash
3143  mkmountpoint /ext3
3144  mount /dev/sda /cd
3145  mount-loop /cd/LiveOS/squashfs.img /squash
3146  mount-loop /squash/LiveOS/ext3fs.img /ext3
3147
3148 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3149
3150   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3151    [],
3152    "remove a mountpoint",
3153    "\
3154 This calls removes a mountpoint that was previously created
3155 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3156 for full details.");
3157
3158   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3159    [InitISOFS, Always, TestOutputBuffer (
3160       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3161    "read a file",
3162    "\
3163 This calls returns the contents of the file C<path> as a
3164 buffer.
3165
3166 Unlike C<guestfs_cat>, this function can correctly
3167 handle files that contain embedded ASCII NUL characters.
3168 However unlike C<guestfs_download>, this function is limited
3169 in the total size of file that can be handled.");
3170
3171   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3172    [InitISOFS, Always, TestOutputList (
3173       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3174     InitISOFS, Always, TestOutputList (
3175       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3176    "return lines matching a pattern",
3177    "\
3178 This calls the external C<grep> program and returns the
3179 matching lines.");
3180
3181   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3182    [InitISOFS, Always, TestOutputList (
3183       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3184    "return lines matching a pattern",
3185    "\
3186 This calls the external C<egrep> program and returns the
3187 matching lines.");
3188
3189   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3190    [InitISOFS, Always, TestOutputList (
3191       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3192    "return lines matching a pattern",
3193    "\
3194 This calls the external C<fgrep> program and returns the
3195 matching lines.");
3196
3197   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3198    [InitISOFS, Always, TestOutputList (
3199       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3200    "return lines matching a pattern",
3201    "\
3202 This calls the external C<grep -i> program and returns the
3203 matching lines.");
3204
3205   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3206    [InitISOFS, Always, TestOutputList (
3207       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3208    "return lines matching a pattern",
3209    "\
3210 This calls the external C<egrep -i> program and returns the
3211 matching lines.");
3212
3213   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3214    [InitISOFS, Always, TestOutputList (
3215       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3216    "return lines matching a pattern",
3217    "\
3218 This calls the external C<fgrep -i> program and returns the
3219 matching lines.");
3220
3221   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputList (
3223       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3224    "return lines matching a pattern",
3225    "\
3226 This calls the external C<zgrep> program and returns the
3227 matching lines.");
3228
3229   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3230    [InitISOFS, Always, TestOutputList (
3231       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3232    "return lines matching a pattern",
3233    "\
3234 This calls the external C<zegrep> program and returns the
3235 matching lines.");
3236
3237   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3238    [InitISOFS, Always, TestOutputList (
3239       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3240    "return lines matching a pattern",
3241    "\
3242 This calls the external C<zfgrep> program and returns the
3243 matching lines.");
3244
3245   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3246    [InitISOFS, Always, TestOutputList (
3247       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3248    "return lines matching a pattern",
3249    "\
3250 This calls the external C<zgrep -i> program and returns the
3251 matching lines.");
3252
3253   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3254    [InitISOFS, Always, TestOutputList (
3255       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3256    "return lines matching a pattern",
3257    "\
3258 This calls the external C<zegrep -i> program and returns the
3259 matching lines.");
3260
3261   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3262    [InitISOFS, Always, TestOutputList (
3263       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3264    "return lines matching a pattern",
3265    "\
3266 This calls the external C<zfgrep -i> program and returns the
3267 matching lines.");
3268
3269   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3270    [InitISOFS, Always, TestOutput (
3271       [["realpath"; "/../directory"]], "/directory")],
3272    "canonicalized absolute pathname",
3273    "\
3274 Return the canonicalized absolute pathname of C<path>.  The
3275 returned path has no C<.>, C<..> or symbolic link path elements.");
3276
3277   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3278    [InitBasicFS, Always, TestOutputStruct (
3279       [["touch"; "/a"];
3280        ["ln"; "/a"; "/b"];
3281        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3282    "create a hard link",
3283    "\
3284 This command creates a hard link using the C<ln> command.");
3285
3286   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["touch"; "/a"];
3289        ["touch"; "/b"];
3290        ["ln_f"; "/a"; "/b"];
3291        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3292    "create a hard link",
3293    "\
3294 This command creates a hard link using the C<ln -f> command.
3295 The C<-f> option removes the link (C<linkname>) if it exists already.");
3296
3297   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3298    [InitBasicFS, Always, TestOutputStruct (
3299       [["touch"; "/a"];
3300        ["ln_s"; "a"; "/b"];
3301        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3302    "create a symbolic link",
3303    "\
3304 This command creates a symbolic link using the C<ln -s> command.");
3305
3306   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3307    [InitBasicFS, Always, TestOutput (
3308       [["mkdir_p"; "/a/b"];
3309        ["touch"; "/a/b/c"];
3310        ["ln_sf"; "../d"; "/a/b/c"];
3311        ["readlink"; "/a/b/c"]], "../d")],
3312    "create a symbolic link",
3313    "\
3314 This command creates a symbolic link using the C<ln -sf> command,
3315 The C<-f> option removes the link (C<linkname>) if it exists already.");
3316
3317   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3318    [] (* XXX tested above *),
3319    "read the target of a symbolic link",
3320    "\
3321 This command reads the target of a symbolic link.");
3322
3323   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3324    [InitBasicFS, Always, TestOutputStruct (
3325       [["fallocate"; "/a"; "1000000"];
3326        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3327    "preallocate a file in the guest filesystem",
3328    "\
3329 This command preallocates a file (containing zero bytes) named
3330 C<path> of size C<len> bytes.  If the file exists already, it
3331 is overwritten.
3332
3333 Do not confuse this with the guestfish-specific
3334 C<alloc> command which allocates a file in the host and
3335 attaches it as a device.");
3336
3337   ("swapon_device", (RErr, [Device "device"]), 170, [],
3338    [InitPartition, Always, TestRun (
3339       [["mkswap"; "/dev/sda1"];
3340        ["swapon_device"; "/dev/sda1"];
3341        ["swapoff_device"; "/dev/sda1"]])],
3342    "enable swap on device",
3343    "\
3344 This command enables the libguestfs appliance to use the
3345 swap device or partition named C<device>.  The increased
3346 memory is made available for all commands, for example
3347 those run using C<guestfs_command> or C<guestfs_sh>.
3348
3349 Note that you should not swap to existing guest swap
3350 partitions unless you know what you are doing.  They may
3351 contain hibernation information, or other information that
3352 the guest doesn't want you to trash.  You also risk leaking
3353 information about the host to the guest this way.  Instead,
3354 attach a new host device to the guest and swap on that.");
3355
3356   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3357    [], (* XXX tested by swapon_device *)
3358    "disable swap on device",
3359    "\
3360 This command disables the libguestfs appliance swap
3361 device or partition named C<device>.
3362 See C<guestfs_swapon_device>.");
3363
3364   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3365    [InitBasicFS, Always, TestRun (
3366       [["fallocate"; "/swap"; "8388608"];
3367        ["mkswap_file"; "/swap"];
3368        ["swapon_file"; "/swap"];
3369        ["swapoff_file"; "/swap"]])],
3370    "enable swap on file",
3371    "\
3372 This command enables swap to a file.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3376    [], (* XXX tested by swapon_file *)
3377    "disable swap on file",
3378    "\
3379 This command disables the libguestfs appliance swap on file.");
3380
3381   ("swapon_label", (RErr, [String "label"]), 174, [],
3382    [InitEmpty, Always, TestRun (
3383       [["part_disk"; "/dev/sdb"; "mbr"];
3384        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3385        ["swapon_label"; "swapit"];
3386        ["swapoff_label"; "swapit"];
3387        ["zero"; "/dev/sdb"];
3388        ["blockdev_rereadpt"; "/dev/sdb"]])],
3389    "enable swap on labeled swap partition",
3390    "\
3391 This command enables swap to a labeled swap partition.
3392 See C<guestfs_swapon_device> for other notes.");
3393
3394   ("swapoff_label", (RErr, [String "label"]), 175, [],
3395    [], (* XXX tested by swapon_label *)
3396    "disable swap on labeled swap partition",
3397    "\
3398 This command disables the libguestfs appliance swap on
3399 labeled swap partition.");
3400
3401   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3402    (let uuid = uuidgen () in
3403     [InitEmpty, Always, TestRun (
3404        [["mkswap_U"; uuid; "/dev/sdb"];
3405         ["swapon_uuid"; uuid];
3406         ["swapoff_uuid"; uuid]])]),
3407    "enable swap on swap partition by UUID",
3408    "\
3409 This command enables swap to a swap partition with the given UUID.
3410 See C<guestfs_swapon_device> for other notes.");
3411
3412   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3413    [], (* XXX tested by swapon_uuid *)
3414    "disable swap on swap partition by UUID",
3415    "\
3416 This command disables the libguestfs appliance swap partition
3417 with the given UUID.");
3418
3419   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3420    [InitBasicFS, Always, TestRun (
3421       [["fallocate"; "/swap"; "8388608"];
3422        ["mkswap_file"; "/swap"]])],
3423    "create a swap file",
3424    "\
3425 Create a swap file.
3426
3427 This command just writes a swap file signature to an existing
3428 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3429
3430   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3431    [InitISOFS, Always, TestRun (
3432       [["inotify_init"; "0"]])],
3433    "create an inotify handle",
3434    "\
3435 This command creates a new inotify handle.
3436 The inotify subsystem can be used to notify events which happen to
3437 objects in the guest filesystem.
3438
3439 C<maxevents> is the maximum number of events which will be
3440 queued up between calls to C<guestfs_inotify_read> or
3441 C<guestfs_inotify_files>.
3442 If this is passed as C<0>, then the kernel (or previously set)
3443 default is used.  For Linux 2.6.29 the default was 16384 events.
3444 Beyond this limit, the kernel throws away events, but records
3445 the fact that it threw them away by setting a flag
3446 C<IN_Q_OVERFLOW> in the returned structure list (see
3447 C<guestfs_inotify_read>).
3448
3449 Before any events are generated, you have to add some
3450 watches to the internal watch list.  See:
3451 C<guestfs_inotify_add_watch>,
3452 C<guestfs_inotify_rm_watch> and
3453 C<guestfs_inotify_watch_all>.
3454
3455 Queued up events should be read periodically by calling
3456 C<guestfs_inotify_read>
3457 (or C<guestfs_inotify_files> which is just a helpful
3458 wrapper around C<guestfs_inotify_read>).  If you don't
3459 read the events out often enough then you risk the internal
3460 queue overflowing.
3461
3462 The handle should be closed after use by calling
3463 C<guestfs_inotify_close>.  This also removes any
3464 watches automatically.
3465
3466 See also L<inotify(7)> for an overview of the inotify interface
3467 as exposed by the Linux kernel, which is roughly what we expose
3468 via libguestfs.  Note that there is one global inotify handle
3469 per libguestfs instance.");
3470
3471   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3472    [InitBasicFS, Always, TestOutputList (
3473       [["inotify_init"; "0"];
3474        ["inotify_add_watch"; "/"; "1073741823"];
3475        ["touch"; "/a"];
3476        ["touch"; "/b"];
3477        ["inotify_files"]], ["a"; "b"])],
3478    "add an inotify watch",
3479    "\
3480 Watch C<path> for the events listed in C<mask>.
3481
3482 Note that if C<path> is a directory then events within that
3483 directory are watched, but this does I<not> happen recursively
3484 (in subdirectories).
3485
3486 Note for non-C or non-Linux callers: the inotify events are
3487 defined by the Linux kernel ABI and are listed in
3488 C</usr/include/sys/inotify.h>.");
3489
3490   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3491    [],
3492    "remove an inotify watch",
3493    "\
3494 Remove a previously defined inotify watch.
3495 See C<guestfs_inotify_add_watch>.");
3496
3497   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3498    [],
3499    "return list of inotify events",
3500    "\
3501 Return the complete queue of events that have happened
3502 since the previous read call.
3503
3504 If no events have happened, this returns an empty list.
3505
3506 I<Note>: In order to make sure that all events have been
3507 read, you must call this function repeatedly until it
3508 returns an empty list.  The reason is that the call will
3509 read events up to the maximum appliance-to-host message
3510 size and leave remaining events in the queue.");
3511
3512   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3513    [],
3514    "return list of watched files that had events",
3515    "\
3516 This function is a helpful wrapper around C<guestfs_inotify_read>
3517 which just returns a list of pathnames of objects that were
3518 touched.  The returned pathnames are sorted and deduplicated.");
3519
3520   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3521    [],
3522    "close the inotify handle",
3523    "\
3524 This closes the inotify handle which was previously
3525 opened by inotify_init.  It removes all watches, throws
3526 away any pending events, and deallocates all resources.");
3527
3528   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3529    [],
3530    "set SELinux security context",
3531    "\
3532 This sets the SELinux security context of the daemon
3533 to the string C<context>.
3534
3535 See the documentation about SELINUX in L<guestfs(3)>.");
3536
3537   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3538    [],
3539    "get SELinux security context",
3540    "\
3541 This gets the SELinux security context of the daemon.
3542
3543 See the documentation about SELINUX in L<guestfs(3)>,
3544 and C<guestfs_setcon>");
3545
3546   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3547    [InitEmpty, Always, TestOutput (
3548       [["part_disk"; "/dev/sda"; "mbr"];
3549        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3550        ["mount"; "/dev/sda1"; "/"];
3551        ["write_file"; "/new"; "new file contents"; "0"];
3552        ["cat"; "/new"]], "new file contents")],
3553    "make a filesystem with block size",
3554    "\
3555 This call is similar to C<guestfs_mkfs>, but it allows you to
3556 control the block size of the resulting filesystem.  Supported
3557 block sizes depend on the filesystem type, but typically they
3558 are C<1024>, C<2048> or C<4096> only.");
3559
3560   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3561    [InitEmpty, Always, TestOutput (
3562       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3563        ["mke2journal"; "4096"; "/dev/sda1"];
3564        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3565        ["mount"; "/dev/sda2"; "/"];
3566        ["write_file"; "/new"; "new file contents"; "0"];
3567        ["cat"; "/new"]], "new file contents")],
3568    "make ext2/3/4 external journal",
3569    "\
3570 This creates an ext2 external journal on C<device>.  It is equivalent
3571 to the command:
3572
3573  mke2fs -O journal_dev -b blocksize device");
3574
3575   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3576    [InitEmpty, Always, TestOutput (
3577       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3578        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3579        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3580        ["mount"; "/dev/sda2"; "/"];
3581        ["write_file"; "/new"; "new file contents"; "0"];
3582        ["cat"; "/new"]], "new file contents")],
3583    "make ext2/3/4 external journal with label",
3584    "\
3585 This creates an ext2 external journal on C<device> with label C<label>.");
3586
3587   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3588    (let uuid = uuidgen () in
3589     [InitEmpty, Always, TestOutput (
3590        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3591         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3592         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3593         ["mount"; "/dev/sda2"; "/"];
3594         ["write_file"; "/new"; "new file contents"; "0"];
3595         ["cat"; "/new"]], "new file contents")]),
3596    "make ext2/3/4 external journal with UUID",
3597    "\
3598 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3599
3600   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3601    [],
3602    "make ext2/3/4 filesystem with external journal",
3603    "\
3604 This creates an ext2/3/4 filesystem on C<device> with
3605 an external journal on C<journal>.  It is equivalent
3606 to the command:
3607
3608  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3609
3610 See also C<guestfs_mke2journal>.");
3611
3612   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3613    [],
3614    "make ext2/3/4 filesystem with external journal",
3615    "\
3616 This creates an ext2/3/4 filesystem on C<device> with
3617 an external journal on the journal labeled C<label>.
3618
3619 See also C<guestfs_mke2journal_L>.");
3620
3621   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3622    [],
3623    "make ext2/3/4 filesystem with external journal",
3624    "\
3625 This creates an ext2/3/4 filesystem on C<device> with
3626 an external journal on the journal with UUID C<uuid>.
3627
3628 See also C<guestfs_mke2journal_U>.");
3629
3630   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3631    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3632    "load a kernel module",
3633    "\
3634 This loads a kernel module in the appliance.
3635
3636 The kernel module must have been whitelisted when libguestfs
3637 was built (see C<appliance/kmod.whitelist.in> in the source).");
3638
3639   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3640    [InitNone, Always, TestOutput (
3641      [["echo_daemon"; "This is a test"]], "This is a test"
3642    )],
3643    "echo arguments back to the client",
3644    "\
3645 This command concatenate the list of C<words> passed with single spaces between
3646 them and returns the resulting string.
3647
3648 You can use this command to test the connection through to the daemon.
3649
3650 See also C<guestfs_ping_daemon>.");
3651
3652   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3653    [], (* There is a regression test for this. *)
3654    "find all files and directories, returning NUL-separated list",
3655    "\
3656 This command lists out all files and directories, recursively,
3657 starting at C<directory>, placing the resulting list in the
3658 external file called C<files>.
3659
3660 This command works the same way as C<guestfs_find> with the
3661 following exceptions:
3662
3663 =over 4
3664
3665 =item *
3666
3667 The resulting list is written to an external file.
3668
3669 =item *
3670
3671 Items (filenames) in the result are separated
3672 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3673
3674 =item *
3675
3676 This command is not limited in the number of names that it
3677 can return.
3678
3679 =item *
3680
3681 The result list is not sorted.
3682
3683 =back");
3684
3685   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3686    [InitISOFS, Always, TestOutput (
3687       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3688     InitISOFS, Always, TestOutput (
3689       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3690     InitISOFS, Always, TestOutput (
3691       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3692     InitISOFS, Always, TestLastFail (
3693       [["case_sensitive_path"; "/Known-1/"]]);
3694     InitBasicFS, Always, TestOutput (
3695       [["mkdir"; "/a"];
3696        ["mkdir"; "/a/bbb"];
3697        ["touch"; "/a/bbb/c"];
3698        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3699     InitBasicFS, Always, TestOutput (
3700       [["mkdir"; "/a"];
3701        ["mkdir"; "/a/bbb"];
3702        ["touch"; "/a/bbb/c"];
3703        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3704     InitBasicFS, Always, TestLastFail (
3705       [["mkdir"; "/a"];
3706        ["mkdir"; "/a/bbb"];
3707        ["touch"; "/a/bbb/c"];
3708        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3709    "return true path on case-insensitive filesystem",
3710    "\
3711 This can be used to resolve case insensitive paths on
3712 a filesystem which is case sensitive.  The use case is
3713 to resolve paths which you have read from Windows configuration
3714 files or the Windows Registry, to the true path.
3715
3716 The command handles a peculiarity of the Linux ntfs-3g
3717 filesystem driver (and probably others), which is that although
3718 the underlying filesystem is case-insensitive, the driver
3719 exports the filesystem to Linux as case-sensitive.
3720
3721 One consequence of this is that special directories such
3722 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3723 (or other things) depending on the precise details of how
3724 they were created.  In Windows itself this would not be
3725 a problem.
3726
3727 Bug or feature?  You decide:
3728 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3729
3730 This function resolves the true case of each element in the
3731 path and returns the case-sensitive path.
3732
3733 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3734 might return C<\"/WINDOWS/system32\"> (the exact return value
3735 would depend on details of how the directories were originally
3736 created under Windows).
3737
3738 I<Note>:
3739 This function does not handle drive names, backslashes etc.
3740
3741 See also C<guestfs_realpath>.");
3742
3743   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3744    [InitBasicFS, Always, TestOutput (
3745       [["vfs_type"; "/dev/sda1"]], "ext2")],
3746    "get the Linux VFS type corresponding to a mounted device",
3747    "\
3748 This command gets the block device type corresponding to
3749 a mounted device called C<device>.
3750
3751 Usually the result is the name of the Linux VFS module that
3752 is used to mount this device (probably determined automatically
3753 if you used the C<guestfs_mount> call).");
3754
3755   ("truncate", (RErr, [Pathname "path"]), 199, [],
3756    [InitBasicFS, Always, TestOutputStruct (
3757       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3758        ["truncate"; "/test"];
3759        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3760    "truncate a file to zero size",
3761    "\
3762 This command truncates C<path> to a zero-length file.  The
3763 file must exist already.");
3764
3765   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3766    [InitBasicFS, Always, TestOutputStruct (
3767       [["touch"; "/test"];
3768        ["truncate_size"; "/test"; "1000"];
3769        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3770    "truncate a file to a particular size",
3771    "\
3772 This command truncates C<path> to size C<size> bytes.  The file
3773 must exist already.  If the file is smaller than C<size> then
3774 the file is extended to the required size with null bytes.");
3775
3776   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3777    [InitBasicFS, Always, TestOutputStruct (
3778       [["touch"; "/test"];
3779        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3780        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3781    "set timestamp of a file with nanosecond precision",
3782    "\
3783 This command sets the timestamps of a file with nanosecond
3784 precision.
3785
3786 C<atsecs, atnsecs> are the last access time (atime) in secs and
3787 nanoseconds from the epoch.
3788
3789 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3790 secs and nanoseconds from the epoch.
3791
3792 If the C<*nsecs> field contains the special value C<-1> then
3793 the corresponding timestamp is set to the current time.  (The
3794 C<*secs> field is ignored in this case).
3795
3796 If the C<*nsecs> field contains the special value C<-2> then
3797 the corresponding timestamp is left unchanged.  (The
3798 C<*secs> field is ignored in this case).");
3799
3800   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3801    [InitBasicFS, Always, TestOutputStruct (
3802       [["mkdir_mode"; "/test"; "0o111"];
3803        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3804    "create a directory with a particular mode",
3805    "\
3806 This command creates a directory, setting the initial permissions
3807 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3808
3809   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3810    [], (* XXX *)
3811    "change file owner and group",
3812    "\
3813 Change the file owner to C<owner> and group to C<group>.
3814 This is like C<guestfs_chown> but if C<path> is a symlink then
3815 the link itself is changed, not the target.
3816
3817 Only numeric uid and gid are supported.  If you want to use
3818 names, you will need to locate and parse the password file
3819 yourself (Augeas support makes this relatively easy).");
3820
3821   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3822    [], (* XXX *)
3823    "lstat on multiple files",
3824    "\
3825 This call allows you to perform the C<guestfs_lstat> operation
3826 on multiple files, where all files are in the directory C<path>.
3827 C<names> is the list of files from this directory.
3828
3829 On return you get a list of stat structs, with a one-to-one
3830 correspondence to the C<names> list.  If any name did not exist
3831 or could not be lstat'd, then the C<ino> field of that structure
3832 is set to C<-1>.
3833
3834 This call is intended for programs that want to efficiently
3835 list a directory contents without making many round-trips.
3836 See also C<guestfs_lxattrlist> for a similarly efficient call
3837 for getting extended attributes.  Very long directory listings
3838 might cause the protocol message size to be exceeded, causing
3839 this call to fail.  The caller must split up such requests
3840 into smaller groups of names.");
3841
3842   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3843    [], (* XXX *)
3844    "lgetxattr on multiple files",
3845    "\
3846 This call allows you to get the extended attributes
3847 of multiple files, where all files are in the directory C<path>.
3848 C<names> is the list of files from this directory.
3849
3850 On return you get a flat list of xattr structs which must be
3851 interpreted sequentially.  The first xattr struct always has a zero-length
3852 C<attrname>.  C<attrval> in this struct is zero-length
3853 to indicate there was an error doing C<lgetxattr> for this
3854 file, I<or> is a C string which is a decimal number
3855 (the number of following attributes for this file, which could
3856 be C<\"0\">).  Then after the first xattr struct are the
3857 zero or more attributes for the first named file.
3858 This repeats for the second and subsequent files.
3859
3860 This call is intended for programs that want to efficiently
3861 list a directory contents without making many round-trips.
3862 See also C<guestfs_lstatlist> for a similarly efficient call
3863 for getting standard stats.  Very long directory listings
3864 might cause the protocol message size to be exceeded, causing
3865 this call to fail.  The caller must split up such requests
3866 into smaller groups of names.");
3867
3868   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3869    [], (* XXX *)
3870    "readlink on multiple files",
3871    "\
3872 This call allows you to do a C<readlink> operation
3873 on multiple files, where all files are in the directory C<path>.
3874 C<names> is the list of files from this directory.
3875
3876 On return you get a list of strings, with a one-to-one
3877 correspondence to the C<names> list.  Each string is the
3878 value of the symbol link.
3879
3880 If the C<readlink(2)> operation fails on any name, then
3881 the corresponding result string is the empty string C<\"\">.
3882 However the whole operation is completed even if there
3883 were C<readlink(2)> errors, and so you can call this
3884 function with names where you don't know if they are
3885 symbolic links already (albeit slightly less efficient).
3886
3887 This call is intended for programs that want to efficiently
3888 list a directory contents without making many round-trips.
3889 Very long directory listings might cause the protocol
3890 message size to be exceeded, causing
3891 this call to fail.  The caller must split up such requests
3892 into smaller groups of names.");
3893
3894   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3895    [InitISOFS, Always, TestOutputBuffer (
3896       [["pread"; "/known-4"; "1"; "3"]], "\n");
3897     InitISOFS, Always, TestOutputBuffer (
3898       [["pread"; "/empty"; "0"; "100"]], "")],
3899    "read part of a file",
3900    "\
3901 This command lets you read part of a file.  It reads C<count>
3902 bytes of the file, starting at C<offset>, from file C<path>.
3903
3904 This may read fewer bytes than requested.  For further details
3905 see the L<pread(2)> system call.");
3906
3907   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3908    [InitEmpty, Always, TestRun (
3909       [["part_init"; "/dev/sda"; "gpt"]])],
3910    "create an empty partition table",
3911    "\
3912 This creates an empty partition table on C<device> of one of the
3913 partition types listed below.  Usually C<parttype> should be
3914 either C<msdos> or C<gpt> (for large disks).
3915
3916 Initially there are no partitions.  Following this, you should
3917 call C<guestfs_part_add> for each partition required.
3918
3919 Possible values for C<parttype> are:
3920
3921 =over 4
3922
3923 =item B<efi> | B<gpt>
3924
3925 Intel EFI / GPT partition table.
3926
3927 This is recommended for >= 2 TB partitions that will be accessed
3928 from Linux and Intel-based Mac OS X.  It also has limited backwards
3929 compatibility with the C<mbr> format.
3930
3931 =item B<mbr> | B<msdos>
3932
3933 The standard PC \"Master Boot Record\" (MBR) format used
3934 by MS-DOS and Windows.  This partition type will B<only> work
3935 for device sizes up to 2 TB.  For large disks we recommend
3936 using C<gpt>.
3937
3938 =back
3939
3940 Other partition table types that may work but are not
3941 supported include:
3942
3943 =over 4
3944
3945 =item B<aix>
3946
3947 AIX disk labels.
3948
3949 =item B<amiga> | B<rdb>
3950
3951 Amiga \"Rigid Disk Block\" format.
3952
3953 =item B<bsd>
3954
3955 BSD disk labels.
3956
3957 =item B<dasd>
3958
3959 DASD, used on IBM mainframes.
3960
3961 =item B<dvh>
3962
3963 MIPS/SGI volumes.
3964
3965 =item B<mac>
3966
3967 Old Mac partition format.  Modern Macs use C<gpt>.
3968
3969 =item B<pc98>
3970
3971 NEC PC-98 format, common in Japan apparently.
3972
3973 =item B<sun>
3974
3975 Sun disk labels.
3976
3977 =back");
3978
3979   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3980    [InitEmpty, Always, TestRun (
3981       [["part_init"; "/dev/sda"; "mbr"];
3982        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3983     InitEmpty, Always, TestRun (
3984       [["part_init"; "/dev/sda"; "gpt"];
3985        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3986        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3987     InitEmpty, Always, TestRun (
3988       [["part_init"; "/dev/sda"; "mbr"];
3989        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3990        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3991        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3992        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3993    "add a partition to the device",
3994    "\
3995 This command adds a partition to C<device>.  If there is no partition
3996 table on the device, call C<guestfs_part_init> first.
3997
3998 The C<prlogex> parameter is the type of partition.  Normally you
3999 should pass C<p> or C<primary> here, but MBR partition tables also
4000 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4001 types.
4002
4003 C<startsect> and C<endsect> are the start and end of the partition
4004 in I<sectors>.  C<endsect> may be negative, which means it counts
4005 backwards from the end of the disk (C<-1> is the last sector).
4006
4007 Creating a partition which covers the whole disk is not so easy.
4008 Use C<guestfs_part_disk> to do that.");
4009
4010   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4011    [InitEmpty, Always, TestRun (
4012       [["part_disk"; "/dev/sda"; "mbr"]]);
4013     InitEmpty, Always, TestRun (
4014       [["part_disk"; "/dev/sda"; "gpt"]])],
4015    "partition whole disk with a single primary partition",
4016    "\
4017 This command is simply a combination of C<guestfs_part_init>
4018 followed by C<guestfs_part_add> to create a single primary partition
4019 covering the whole disk.
4020
4021 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4022 but other possible values are described in C<guestfs_part_init>.");
4023
4024   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4025    [InitEmpty, Always, TestRun (
4026       [["part_disk"; "/dev/sda"; "mbr"];
4027        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4028    "make a partition bootable",
4029    "\
4030 This sets the bootable flag on partition numbered C<partnum> on
4031 device C<device>.  Note that partitions are numbered from 1.
4032
4033 The bootable flag is used by some PC BIOSes to determine which
4034 partition to boot from.  It is by no means universally recognized,
4035 and in any case if your operating system installed a boot
4036 sector on the device itself, then that takes precedence.");
4037
4038   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4039    [InitEmpty, Always, TestRun (
4040       [["part_disk"; "/dev/sda"; "gpt"];
4041        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4042    "set partition name",
4043    "\
4044 This sets the partition name on partition numbered C<partnum> on
4045 device C<device>.  Note that partitions are numbered from 1.
4046
4047 The partition name can only be set on certain types of partition
4048 table.  This works on C<gpt> but not on C<mbr> partitions.");
4049
4050   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4051    [], (* XXX Add a regression test for this. *)
4052    "list partitions on a device",
4053    "\
4054 This command parses the partition table on C<device> and
4055 returns the list of partitions found.
4056
4057 The fields in the returned structure are:
4058
4059 =over 4
4060
4061 =item B<part_num>
4062
4063 Partition number, counting from 1.
4064
4065 =item B<part_start>
4066
4067 Start of the partition I<in bytes>.  To get sectors you have to
4068 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4069
4070 =item B<part_end>
4071
4072 End of the partition in bytes.
4073
4074 =item B<part_size>
4075
4076 Size of the partition in bytes.
4077
4078 =back");
4079
4080   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4081    [InitEmpty, Always, TestOutput (
4082       [["part_disk"; "/dev/sda"; "gpt"];
4083        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4084    "get the partition table type",
4085    "\
4086 This command examines the partition table on C<device> and
4087 returns the partition table type (format) being used.
4088
4089 Common return values include: C<msdos> (a DOS/Windows style MBR
4090 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4091 values are possible, although unusual.  See C<guestfs_part_init>
4092 for a full list.");
4093
4094   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4095    [InitBasicFS, Always, TestOutputBuffer (
4096       [["fill"; "0x63"; "10"; "/test"];
4097        ["read_file"; "/test"]], "cccccccccc")],
4098    "fill a file with octets",
4099    "\
4100 This command creates a new file called C<path>.  The initial
4101 content of the file is C<len> octets of C<c>, where C<c>
4102 must be a number in the range C<[0..255]>.
4103
4104 To fill a file with zero bytes (sparsely), it is
4105 much more efficient to use C<guestfs_truncate_size>.");
4106
4107   ("available", (RErr, [StringList "groups"]), 216, [],
4108    [],
4109    "test availability of some parts of the API",
4110    "\
4111 This command is used to check the availability of some
4112 groups of libguestfs functions which not all builds of
4113 libguestfs will be able to provide.
4114
4115 The precise libguestfs function groups that may be checked by this
4116 command are listed in L<guestfs(3)/AVAILABILITY>.
4117
4118 The argument C<groups> is a list of API group names, eg:
4119 C<[\"inotify\", \"augeas\"]> would check for the availability of
4120 the C<guestfs_inotify_*> functions and C<guestfs_aug_*>
4121 (partition editing) functions.
4122
4123 The command returns no error if I<all> requested groups are available.
4124
4125 It returns an error if one or more of the requested
4126 groups is unavailable.
4127
4128 If an unknown group name is included in the
4129 list of C<groups> then an error is always returned.
4130
4131 I<Notes:>
4132
4133 =over 4
4134
4135 =item *
4136
4137 You must call C<guestfs_launch> before calling this function.
4138 The reason is because we don't know what function groups are
4139 supported by the appliance/daemon until it is running and can
4140 be queried.
4141
4142 =item *
4143
4144 If a group of functions is available, this does not necessarily
4145 mean that they will work.  You still have to check for errors
4146 when calling individual API functions even if they are
4147 available.
4148
4149 =item *
4150
4151 It is usually the job of distro packagers to build
4152 complete functionality into the libguestfs appliance.
4153 Upstream libguestfs, if built from source with all
4154 requirements satisfied, will support everything.
4155
4156 =item *
4157
4158 This call was added in version C<1.0.80>.  In previous
4159 versions of libguestfs all you could do would be to speculatively
4160 execute a command to find out if the daemon implemented it.
4161 See also C<guestfs_version>.
4162
4163 =back");
4164
4165   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4166    [InitBasicFS, Always, TestOutputBuffer (
4167       [["write_file"; "/src"; "hello, world"; "0"];
4168        ["dd"; "/src"; "/dest"];
4169        ["read_file"; "/dest"]], "hello, world")],
4170    "copy from source to destination using dd",
4171    "\
4172 This command copies from one source device or file C<src>
4173 to another destination device or file C<dest>.  Normally you
4174 would use this to copy to or from a device or partition, for
4175 example to duplicate a filesystem.
4176
4177 If the destination is a device, it must be as large or larger
4178 than the source file or device, otherwise the copy will fail.
4179 This command cannot do partial copies.");
4180
4181 ]
4182
4183 let all_functions = non_daemon_functions @ daemon_functions
4184
4185 (* In some places we want the functions to be displayed sorted
4186  * alphabetically, so this is useful:
4187  *)
4188 let all_functions_sorted =
4189   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4190                compare n1 n2) all_functions
4191
4192 (* Field types for structures. *)
4193 type field =
4194   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4195   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4196   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4197   | FUInt32
4198   | FInt32
4199   | FUInt64
4200   | FInt64
4201   | FBytes                      (* Any int measure that counts bytes. *)
4202   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4203   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4204
4205 (* Because we generate extra parsing code for LVM command line tools,
4206  * we have to pull out the LVM columns separately here.
4207  *)
4208 let lvm_pv_cols = [
4209   "pv_name", FString;
4210   "pv_uuid", FUUID;
4211   "pv_fmt", FString;
4212   "pv_size", FBytes;
4213   "dev_size", FBytes;
4214   "pv_free", FBytes;
4215   "pv_used", FBytes;
4216   "pv_attr", FString (* XXX *);
4217   "pv_pe_count", FInt64;
4218   "pv_pe_alloc_count", FInt64;
4219   "pv_tags", FString;
4220   "pe_start", FBytes;
4221   "pv_mda_count", FInt64;
4222   "pv_mda_free", FBytes;
4223   (* Not in Fedora 10:
4224      "pv_mda_size", FBytes;
4225   *)
4226 ]
4227 let lvm_vg_cols = [
4228   "vg_name", FString;
4229   "vg_uuid", FUUID;
4230   "vg_fmt", FString;
4231   "vg_attr", FString (* XXX *);
4232   "vg_size", FBytes;
4233   "vg_free", FBytes;
4234   "vg_sysid", FString;
4235   "vg_extent_size", FBytes;
4236   "vg_extent_count", FInt64;
4237   "vg_free_count", FInt64;
4238   "max_lv", FInt64;
4239   "max_pv", FInt64;
4240   "pv_count", FInt64;
4241   "lv_count", FInt64;
4242   "snap_count", FInt64;
4243   "vg_seqno", FInt64;
4244   "vg_tags", FString;
4245   "vg_mda_count", FInt64;
4246   "vg_mda_free", FBytes;
4247   (* Not in Fedora 10:
4248      "vg_mda_size", FBytes;
4249   *)
4250 ]
4251 let lvm_lv_cols = [
4252   "lv_name", FString;
4253   "lv_uuid", FUUID;
4254   "lv_attr", FString (* XXX *);
4255   "lv_major", FInt64;
4256   "lv_minor", FInt64;
4257   "lv_kernel_major", FInt64;
4258   "lv_kernel_minor", FInt64;
4259   "lv_size", FBytes;
4260   "seg_count", FInt64;
4261   "origin", FString;
4262   "snap_percent", FOptPercent;
4263   "copy_percent", FOptPercent;
4264   "move_pv", FString;
4265   "lv_tags", FString;
4266   "mirror_log", FString;
4267   "modules", FString;
4268 ]
4269
4270 (* Names and fields in all structures (in RStruct and RStructList)
4271  * that we support.
4272  *)
4273 let structs = [
4274   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4275    * not use this struct in any new code.
4276    *)
4277   "int_bool", [
4278     "i", FInt32;                (* for historical compatibility *)
4279     "b", FInt32;                (* for historical compatibility *)
4280   ];
4281
4282   (* LVM PVs, VGs, LVs. *)
4283   "lvm_pv", lvm_pv_cols;
4284   "lvm_vg", lvm_vg_cols;
4285   "lvm_lv", lvm_lv_cols;
4286
4287   (* Column names and types from stat structures.
4288    * NB. Can't use things like 'st_atime' because glibc header files
4289    * define some of these as macros.  Ugh.
4290    *)
4291   "stat", [
4292     "dev", FInt64;
4293     "ino", FInt64;
4294     "mode", FInt64;
4295     "nlink", FInt64;
4296     "uid", FInt64;
4297     "gid", FInt64;
4298     "rdev", FInt64;
4299     "size", FInt64;
4300     "blksize", FInt64;
4301     "blocks", FInt64;
4302     "atime", FInt64;
4303     "mtime", FInt64;
4304     "ctime", FInt64;
4305   ];
4306   "statvfs", [
4307     "bsize", FInt64;
4308     "frsize", FInt64;
4309     "blocks", FInt64;
4310     "bfree", FInt64;
4311     "bavail", FInt64;
4312     "files", FInt64;
4313     "ffree", FInt64;
4314     "favail", FInt64;
4315     "fsid", FInt64;
4316     "flag", FInt64;
4317     "namemax", FInt64;
4318   ];
4319
4320   (* Column names in dirent structure. *)
4321   "dirent", [
4322     "ino", FInt64;
4323     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4324     "ftyp", FChar;
4325     "name", FString;
4326   ];
4327
4328   (* Version numbers. *)
4329   "version", [
4330     "major", FInt64;
4331     "minor", FInt64;
4332     "release", FInt64;
4333     "extra", FString;
4334   ];
4335
4336   (* Extended attribute. *)
4337   "xattr", [
4338     "attrname", FString;
4339     "attrval", FBuffer;
4340   ];
4341
4342   (* Inotify events. *)
4343   "inotify_event", [
4344     "in_wd", FInt64;
4345     "in_mask", FUInt32;
4346     "in_cookie", FUInt32;
4347     "in_name", FString;
4348   ];
4349
4350   (* Partition table entry. *)
4351   "partition", [
4352     "part_num", FInt32;
4353     "part_start", FBytes;
4354     "part_end", FBytes;
4355     "part_size", FBytes;
4356   ];
4357 ] (* end of structs *)
4358
4359 (* Ugh, Java has to be different ..
4360  * These names are also used by the Haskell bindings.
4361  *)
4362 let java_structs = [
4363   "int_bool", "IntBool";
4364   "lvm_pv", "PV";
4365   "lvm_vg", "VG";
4366   "lvm_lv", "LV";
4367   "stat", "Stat";
4368   "statvfs", "StatVFS";
4369   "dirent", "Dirent";
4370   "version", "Version";
4371   "xattr", "XAttr";
4372   "inotify_event", "INotifyEvent";
4373   "partition", "Partition";
4374 ]
4375
4376 (* What structs are actually returned. *)
4377 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4378
4379 (* Returns a list of RStruct/RStructList structs that are returned
4380  * by any function.  Each element of returned list is a pair:
4381  *
4382  * (structname, RStructOnly)
4383  *    == there exists function which returns RStruct (_, structname)
4384  * (structname, RStructListOnly)
4385  *    == there exists function which returns RStructList (_, structname)
4386  * (structname, RStructAndList)
4387  *    == there are functions returning both RStruct (_, structname)
4388  *                                      and RStructList (_, structname)
4389  *)
4390 let rstructs_used_by functions =
4391   (* ||| is a "logical OR" for rstructs_used_t *)
4392   let (|||) a b =
4393     match a, b with
4394     | RStructAndList, _
4395     | _, RStructAndList -> RStructAndList
4396     | RStructOnly, RStructListOnly
4397     | RStructListOnly, RStructOnly -> RStructAndList
4398     | RStructOnly, RStructOnly -> RStructOnly
4399     | RStructListOnly, RStructListOnly -> RStructListOnly
4400   in
4401
4402   let h = Hashtbl.create 13 in
4403
4404   (* if elem->oldv exists, update entry using ||| operator,
4405    * else just add elem->newv to the hash
4406    *)
4407   let update elem newv =
4408     try  let oldv = Hashtbl.find h elem in
4409          Hashtbl.replace h elem (newv ||| oldv)
4410     with Not_found -> Hashtbl.add h elem newv
4411   in
4412
4413   List.iter (
4414     fun (_, style, _, _, _, _, _) ->
4415       match fst style with
4416       | RStruct (_, structname) -> update structname RStructOnly
4417       | RStructList (_, structname) -> update structname RStructListOnly
4418       | _ -> ()
4419   ) functions;
4420
4421   (* return key->values as a list of (key,value) *)
4422   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4423
4424 (* Used for testing language bindings. *)
4425 type callt =
4426   | CallString of string
4427   | CallOptString of string option
4428   | CallStringList of string list
4429   | CallInt of int
4430   | CallInt64 of int64
4431   | CallBool of bool
4432
4433 (* Used to memoize the result of pod2text. *)
4434 let pod2text_memo_filename = "src/.pod2text.data"
4435 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4436   try
4437     let chan = open_in pod2text_memo_filename in
4438     let v = input_value chan in
4439     close_in chan;
4440     v
4441   with
4442     _ -> Hashtbl.create 13
4443 let pod2text_memo_updated () =
4444   let chan = open_out pod2text_memo_filename in
4445   output_value chan pod2text_memo;
4446   close_out chan
4447
4448 (* Useful functions.
4449  * Note we don't want to use any external OCaml libraries which
4450  * makes this a bit harder than it should be.
4451  *)
4452 let failwithf fs = ksprintf failwith fs
4453
4454 let replace_char s c1 c2 =
4455   let s2 = String.copy s in
4456   let r = ref false in
4457   for i = 0 to String.length s2 - 1 do
4458     if String.unsafe_get s2 i = c1 then (
4459       String.unsafe_set s2 i c2;
4460       r := true
4461     )
4462   done;
4463   if not !r then s else s2
4464
4465 let isspace c =
4466   c = ' '
4467   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4468
4469 let triml ?(test = isspace) str =
4470   let i = ref 0 in
4471   let n = ref (String.length str) in
4472   while !n > 0 && test str.[!i]; do
4473     decr n;
4474     incr i
4475   done;
4476   if !i = 0 then str
4477   else String.sub str !i !n
4478
4479 let trimr ?(test = isspace) str =
4480   let n = ref (String.length str) in
4481   while !n > 0 && test str.[!n-1]; do
4482     decr n
4483   done;
4484   if !n = String.length str then str
4485   else String.sub str 0 !n
4486
4487 let trim ?(test = isspace) str =
4488   trimr ~test (triml ~test str)
4489
4490 let rec find s sub =
4491   let len = String.length s in
4492   let sublen = String.length sub in
4493   let rec loop i =
4494     if i <= len-sublen then (
4495       let rec loop2 j =
4496         if j < sublen then (
4497           if s.[i+j] = sub.[j] then loop2 (j+1)
4498           else -1
4499         ) else
4500           i (* found *)
4501       in
4502       let r = loop2 0 in
4503       if r = -1 then loop (i+1) else r
4504     ) else
4505       -1 (* not found *)
4506   in
4507   loop 0
4508
4509 let rec replace_str s s1 s2 =
4510   let len = String.length s in
4511   let sublen = String.length s1 in
4512   let i = find s s1 in
4513   if i = -1 then s
4514   else (
4515     let s' = String.sub s 0 i in
4516     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4517     s' ^ s2 ^ replace_str s'' s1 s2
4518   )
4519
4520 let rec string_split sep str =
4521   let len = String.length str in
4522   let seplen = String.length sep in
4523   let i = find str sep in
4524   if i = -1 then [str]
4525   else (
4526     let s' = String.sub str 0 i in
4527     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4528     s' :: string_split sep s''
4529   )
4530
4531 let files_equal n1 n2 =
4532   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4533   match Sys.command cmd with
4534   | 0 -> true
4535   | 1 -> false
4536   | i -> failwithf "%s: failed with error code %d" cmd i
4537
4538 let rec filter_map f = function
4539   | [] -> []
4540   | x :: xs ->
4541       match f x with
4542       | Some y -> y :: filter_map f xs
4543       | None -> filter_map f xs
4544
4545 let rec find_map f = function
4546   | [] -> raise Not_found
4547   | x :: xs ->
4548       match f x with
4549       | Some y -> y
4550       | None -> find_map f xs
4551
4552 let iteri f xs =
4553   let rec loop i = function
4554     | [] -> ()
4555     | x :: xs -> f i x; loop (i+1) xs
4556   in
4557   loop 0 xs
4558
4559 let mapi f xs =
4560   let rec loop i = function
4561     | [] -> []
4562     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4563   in
4564   loop 0 xs
4565
4566 let name_of_argt = function
4567   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4568   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4569   | FileIn n | FileOut n -> n
4570
4571 let java_name_of_struct typ =
4572   try List.assoc typ java_structs
4573   with Not_found ->
4574     failwithf
4575       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4576
4577 let cols_of_struct typ =
4578   try List.assoc typ structs
4579   with Not_found ->
4580     failwithf "cols_of_struct: unknown struct %s" typ
4581
4582 let seq_of_test = function
4583   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4584   | TestOutputListOfDevices (s, _)
4585   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4586   | TestOutputTrue s | TestOutputFalse s
4587   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4588   | TestOutputStruct (s, _)
4589   | TestLastFail s -> s
4590
4591 (* Handling for function flags. *)
4592 let protocol_limit_warning =
4593   "Because of the message protocol, there is a transfer limit
4594 of somewhere between 2MB and 4MB.  To transfer large files you should use
4595 FTP."
4596
4597 let danger_will_robinson =
4598   "B<This command is dangerous.  Without careful use you
4599 can easily destroy all your data>."
4600
4601 let deprecation_notice flags =
4602   try
4603     let alt =
4604       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4605     let txt =
4606       sprintf "This function is deprecated.
4607 In new code, use the C<%s> call instead.
4608
4609 Deprecated functions will not be removed from the API, but the
4610 fact that they are deprecated indicates that there are problems
4611 with correct use of these functions." alt in
4612     Some txt
4613   with
4614     Not_found -> None
4615
4616 (* Create list of optional groups. *)
4617 let optgroups =
4618   let h = Hashtbl.create 13 in
4619   List.iter (
4620     fun (name, _, _, flags, _, _, _) ->
4621       List.iter (
4622         function
4623         | Optional group ->
4624             let names = try Hashtbl.find h group with Not_found -> [] in
4625             Hashtbl.replace h group (name :: names)
4626         | _ -> ()
4627       ) flags
4628   ) daemon_functions;
4629   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4630   let groups =
4631     List.map (
4632       fun group -> group, List.sort compare (Hashtbl.find h group)
4633     ) groups in
4634   List.sort (fun x y -> compare (fst x) (fst y)) groups
4635
4636 (* Check function names etc. for consistency. *)
4637 let check_functions () =
4638   let contains_uppercase str =
4639     let len = String.length str in
4640     let rec loop i =
4641       if i >= len then false
4642       else (
4643         let c = str.[i] in
4644         if c >= 'A' && c <= 'Z' then true
4645         else loop (i+1)
4646       )
4647     in
4648     loop 0
4649   in
4650
4651   (* Check function names. *)
4652   List.iter (
4653     fun (name, _, _, _, _, _, _) ->
4654       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4655         failwithf "function name %s does not need 'guestfs' prefix" name;
4656       if name = "" then
4657         failwithf "function name is empty";
4658       if name.[0] < 'a' || name.[0] > 'z' then
4659         failwithf "function name %s must start with lowercase a-z" name;
4660       if String.contains name '-' then
4661         failwithf "function name %s should not contain '-', use '_' instead."
4662           name
4663   ) all_functions;
4664
4665   (* Check function parameter/return names. *)
4666   List.iter (
4667     fun (name, style, _, _, _, _, _) ->
4668       let check_arg_ret_name n =
4669         if contains_uppercase n then
4670           failwithf "%s param/ret %s should not contain uppercase chars"
4671             name n;
4672         if String.contains n '-' || String.contains n '_' then
4673           failwithf "%s param/ret %s should not contain '-' or '_'"
4674             name n;
4675         if n = "value" then
4676           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;
4677         if n = "int" || n = "char" || n = "short" || n = "long" then
4678           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4679         if n = "i" || n = "n" then
4680           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4681         if n = "argv" || n = "args" then
4682           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4683
4684         (* List Haskell, OCaml and C keywords here.
4685          * http://www.haskell.org/haskellwiki/Keywords
4686          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4687          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4688          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4689          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4690          * Omitting _-containing words, since they're handled above.
4691          * Omitting the OCaml reserved word, "val", is ok,
4692          * and saves us from renaming several parameters.
4693          *)
4694         let reserved = [
4695           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4696           "char"; "class"; "const"; "constraint"; "continue"; "data";
4697           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4698           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4699           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4700           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4701           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4702           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4703           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4704           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4705           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4706           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4707           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4708           "volatile"; "when"; "where"; "while";
4709           ] in
4710         if List.mem n reserved then
4711           failwithf "%s has param/ret using reserved word %s" name n;
4712       in
4713
4714       (match fst style with
4715        | RErr -> ()
4716        | RInt n | RInt64 n | RBool n
4717        | RConstString n | RConstOptString n | RString n
4718        | RStringList n | RStruct (n, _) | RStructList (n, _)
4719        | RHashtable n | RBufferOut n ->
4720            check_arg_ret_name n
4721       );
4722       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4723   ) all_functions;
4724
4725   (* Check short descriptions. *)
4726   List.iter (
4727     fun (name, _, _, _, _, shortdesc, _) ->
4728       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4729         failwithf "short description of %s should begin with lowercase." name;
4730       let c = shortdesc.[String.length shortdesc-1] in
4731       if c = '\n' || c = '.' then
4732         failwithf "short description of %s should not end with . or \\n." name
4733   ) all_functions;
4734
4735   (* Check long dscriptions. *)
4736   List.iter (
4737     fun (name, _, _, _, _, _, longdesc) ->
4738       if longdesc.[String.length longdesc-1] = '\n' then
4739         failwithf "long description of %s should not end with \\n." name
4740   ) all_functions;
4741
4742   (* Check proc_nrs. *)
4743   List.iter (
4744     fun (name, _, proc_nr, _, _, _, _) ->
4745       if proc_nr <= 0 then
4746         failwithf "daemon function %s should have proc_nr > 0" name
4747   ) daemon_functions;
4748
4749   List.iter (
4750     fun (name, _, proc_nr, _, _, _, _) ->
4751       if proc_nr <> -1 then
4752         failwithf "non-daemon function %s should have proc_nr -1" name
4753   ) non_daemon_functions;
4754
4755   let proc_nrs =
4756     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4757       daemon_functions in
4758   let proc_nrs =
4759     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4760   let rec loop = function
4761     | [] -> ()
4762     | [_] -> ()
4763     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4764         loop rest
4765     | (name1,nr1) :: (name2,nr2) :: _ ->
4766         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4767           name1 name2 nr1 nr2
4768   in
4769   loop proc_nrs;
4770
4771   (* Check tests. *)
4772   List.iter (
4773     function
4774       (* Ignore functions that have no tests.  We generate a
4775        * warning when the user does 'make check' instead.
4776        *)
4777     | name, _, _, _, [], _, _ -> ()
4778     | name, _, _, _, tests, _, _ ->
4779         let funcs =
4780           List.map (
4781             fun (_, _, test) ->
4782               match seq_of_test test with
4783               | [] ->
4784                   failwithf "%s has a test containing an empty sequence" name
4785               | cmds -> List.map List.hd cmds
4786           ) tests in
4787         let funcs = List.flatten funcs in
4788
4789         let tested = List.mem name funcs in
4790
4791         if not tested then
4792           failwithf "function %s has tests but does not test itself" name
4793   ) all_functions
4794
4795 (* 'pr' prints to the current output file. *)
4796 let chan = ref Pervasives.stdout
4797 let pr fs = ksprintf (output_string !chan) fs
4798
4799 (* Generate a header block in a number of standard styles. *)
4800 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4801 type license = GPLv2 | LGPLv2
4802
4803 let generate_header comment license =
4804   let c = match comment with
4805     | CStyle ->     pr "/* "; " *"
4806     | HashStyle ->  pr "# ";  "#"
4807     | OCamlStyle -> pr "(* "; " *"
4808     | HaskellStyle -> pr "{- "; "  " in
4809   pr "libguestfs generated file\n";
4810   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4811   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4812   pr "%s\n" c;
4813   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4814   pr "%s\n" c;
4815   (match license with
4816    | GPLv2 ->
4817        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4818        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4819        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4820        pr "%s (at your option) any later version.\n" c;
4821        pr "%s\n" c;
4822        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4823        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4824        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4825        pr "%s GNU General Public License for more details.\n" c;
4826        pr "%s\n" c;
4827        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4828        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4829        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4830
4831    | LGPLv2 ->
4832        pr "%s This library is free software; you can redistribute it and/or\n" c;
4833        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4834        pr "%s License as published by the Free Software Foundation; either\n" c;
4835        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4836        pr "%s\n" c;
4837        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4838        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4839        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4840        pr "%s Lesser General Public License for more details.\n" c;
4841        pr "%s\n" c;
4842        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4843        pr "%s License along with this library; if not, write to the Free Software\n" c;
4844        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4845   );
4846   (match comment with
4847    | CStyle -> pr " */\n"
4848    | HashStyle -> ()
4849    | OCamlStyle -> pr " *)\n"
4850    | HaskellStyle -> pr "-}\n"
4851   );
4852   pr "\n"
4853
4854 (* Start of main code generation functions below this line. *)
4855
4856 (* Generate the pod documentation for the C API. *)
4857 let rec generate_actions_pod () =
4858   List.iter (
4859     fun (shortname, style, _, flags, _, _, longdesc) ->
4860       if not (List.mem NotInDocs flags) then (
4861         let name = "guestfs_" ^ shortname in
4862         pr "=head2 %s\n\n" name;
4863         pr " ";
4864         generate_prototype ~extern:false ~handle:"handle" name style;
4865         pr "\n\n";
4866         pr "%s\n\n" longdesc;
4867         (match fst style with
4868          | RErr ->
4869              pr "This function returns 0 on success or -1 on error.\n\n"
4870          | RInt _ ->
4871              pr "On error this function returns -1.\n\n"
4872          | RInt64 _ ->
4873              pr "On error this function returns -1.\n\n"
4874          | RBool _ ->
4875              pr "This function returns a C truth value on success or -1 on error.\n\n"
4876          | RConstString _ ->
4877              pr "This function returns a string, or NULL on error.
4878 The string is owned by the guest handle and must I<not> be freed.\n\n"
4879          | RConstOptString _ ->
4880              pr "This function returns a string which may be NULL.
4881 There is way to return an error from this function.
4882 The string is owned by the guest handle and must I<not> be freed.\n\n"
4883          | RString _ ->
4884              pr "This function returns a string, or NULL on error.
4885 I<The caller must free the returned string after use>.\n\n"
4886          | RStringList _ ->
4887              pr "This function returns a NULL-terminated array of strings
4888 (like L<environ(3)>), or NULL if there was an error.
4889 I<The caller must free the strings and the array after use>.\n\n"
4890          | RStruct (_, typ) ->
4891              pr "This function returns a C<struct guestfs_%s *>,
4892 or NULL if there was an error.
4893 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4894          | RStructList (_, typ) ->
4895              pr "This function returns a C<struct guestfs_%s_list *>
4896 (see E<lt>guestfs-structs.hE<gt>),
4897 or NULL if there was an error.
4898 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4899          | RHashtable _ ->
4900              pr "This function returns a NULL-terminated array of
4901 strings, or NULL if there was an error.
4902 The array of strings will always have length C<2n+1>, where
4903 C<n> keys and values alternate, followed by the trailing NULL entry.
4904 I<The caller must free the strings and the array after use>.\n\n"
4905          | RBufferOut _ ->
4906              pr "This function returns a buffer, or NULL on error.
4907 The size of the returned buffer is written to C<*size_r>.
4908 I<The caller must free the returned buffer after use>.\n\n"
4909         );
4910         if List.mem ProtocolLimitWarning flags then
4911           pr "%s\n\n" protocol_limit_warning;
4912         if List.mem DangerWillRobinson flags then
4913           pr "%s\n\n" danger_will_robinson;
4914         match deprecation_notice flags with
4915         | None -> ()
4916         | Some txt -> pr "%s\n\n" txt
4917       )
4918   ) all_functions_sorted
4919
4920 and generate_structs_pod () =
4921   (* Structs documentation. *)
4922   List.iter (
4923     fun (typ, cols) ->
4924       pr "=head2 guestfs_%s\n" typ;
4925       pr "\n";
4926       pr " struct guestfs_%s {\n" typ;
4927       List.iter (
4928         function
4929         | name, FChar -> pr "   char %s;\n" name
4930         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4931         | name, FInt32 -> pr "   int32_t %s;\n" name
4932         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4933         | name, FInt64 -> pr "   int64_t %s;\n" name
4934         | name, FString -> pr "   char *%s;\n" name
4935         | name, FBuffer ->
4936             pr "   /* The next two fields describe a byte array. */\n";
4937             pr "   uint32_t %s_len;\n" name;
4938             pr "   char *%s;\n" name
4939         | name, FUUID ->
4940             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4941             pr "   char %s[32];\n" name
4942         | name, FOptPercent ->
4943             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4944             pr "   float %s;\n" name
4945       ) cols;
4946       pr " };\n";
4947       pr " \n";
4948       pr " struct guestfs_%s_list {\n" typ;
4949       pr "   uint32_t len; /* Number of elements in list. */\n";
4950       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4951       pr " };\n";
4952       pr " \n";
4953       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4954       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4955         typ typ;
4956       pr "\n"
4957   ) structs
4958
4959 and generate_availability_pod () =
4960   (* Availability documentation. *)
4961   pr "=over 4\n";
4962   pr "\n";
4963   List.iter (
4964     fun (group, functions) ->
4965       pr "=item B<%s>\n" group;
4966       pr "\n";
4967       pr "The following functions:\n";
4968       List.iter (pr "L</guestfs_%s>\n") functions;
4969       pr "\n"
4970   ) optgroups;
4971   pr "=back\n";
4972   pr "\n"
4973
4974 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4975  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4976  *
4977  * We have to use an underscore instead of a dash because otherwise
4978  * rpcgen generates incorrect code.
4979  *
4980  * This header is NOT exported to clients, but see also generate_structs_h.
4981  *)
4982 and generate_xdr () =
4983   generate_header CStyle LGPLv2;
4984
4985   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4986   pr "typedef string str<>;\n";
4987   pr "\n";
4988
4989   (* Internal structures. *)
4990   List.iter (
4991     function
4992     | typ, cols ->
4993         pr "struct guestfs_int_%s {\n" typ;
4994         List.iter (function
4995                    | name, FChar -> pr "  char %s;\n" name
4996                    | name, FString -> pr "  string %s<>;\n" name
4997                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4998                    | name, FUUID -> pr "  opaque %s[32];\n" name
4999                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5000                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5001                    | name, FOptPercent -> pr "  float %s;\n" name
5002                   ) cols;
5003         pr "};\n";
5004         pr "\n";
5005         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5006         pr "\n";
5007   ) structs;
5008
5009   List.iter (
5010     fun (shortname, style, _, _, _, _, _) ->
5011       let name = "guestfs_" ^ shortname in
5012
5013       (match snd style with
5014        | [] -> ()
5015        | args ->
5016            pr "struct %s_args {\n" name;
5017            List.iter (
5018              function
5019              | Pathname n | Device n | Dev_or_Path n | String n ->
5020                  pr "  string %s<>;\n" n
5021              | OptString n -> pr "  str *%s;\n" n
5022              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5023              | Bool n -> pr "  bool %s;\n" n
5024              | Int n -> pr "  int %s;\n" n
5025              | Int64 n -> pr "  hyper %s;\n" n
5026              | FileIn _ | FileOut _ -> ()
5027            ) args;
5028            pr "};\n\n"
5029       );
5030       (match fst style with
5031        | RErr -> ()
5032        | RInt n ->
5033            pr "struct %s_ret {\n" name;
5034            pr "  int %s;\n" n;
5035            pr "};\n\n"
5036        | RInt64 n ->
5037            pr "struct %s_ret {\n" name;
5038            pr "  hyper %s;\n" n;
5039            pr "};\n\n"
5040        | RBool n ->
5041            pr "struct %s_ret {\n" name;
5042            pr "  bool %s;\n" n;
5043            pr "};\n\n"
5044        | RConstString _ | RConstOptString _ ->
5045            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5046        | RString n ->
5047            pr "struct %s_ret {\n" name;
5048            pr "  string %s<>;\n" n;
5049            pr "};\n\n"
5050        | RStringList n ->
5051            pr "struct %s_ret {\n" name;
5052            pr "  str %s<>;\n" n;
5053            pr "};\n\n"
5054        | RStruct (n, typ) ->
5055            pr "struct %s_ret {\n" name;
5056            pr "  guestfs_int_%s %s;\n" typ n;
5057            pr "};\n\n"
5058        | RStructList (n, typ) ->
5059            pr "struct %s_ret {\n" name;
5060            pr "  guestfs_int_%s_list %s;\n" typ n;
5061            pr "};\n\n"
5062        | RHashtable n ->
5063            pr "struct %s_ret {\n" name;
5064            pr "  str %s<>;\n" n;
5065            pr "};\n\n"
5066        | RBufferOut n ->
5067            pr "struct %s_ret {\n" name;
5068            pr "  opaque %s<>;\n" n;
5069            pr "};\n\n"
5070       );
5071   ) daemon_functions;
5072
5073   (* Table of procedure numbers. *)
5074   pr "enum guestfs_procedure {\n";
5075   List.iter (
5076     fun (shortname, _, proc_nr, _, _, _, _) ->
5077       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5078   ) daemon_functions;
5079   pr "  GUESTFS_PROC_NR_PROCS\n";
5080   pr "};\n";
5081   pr "\n";
5082
5083   (* Having to choose a maximum message size is annoying for several
5084    * reasons (it limits what we can do in the API), but it (a) makes
5085    * the protocol a lot simpler, and (b) provides a bound on the size
5086    * of the daemon which operates in limited memory space.  For large
5087    * file transfers you should use FTP.
5088    *)
5089   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5090   pr "\n";
5091
5092   (* Message header, etc. *)
5093   pr "\
5094 /* The communication protocol is now documented in the guestfs(3)
5095  * manpage.
5096  */
5097
5098 const GUESTFS_PROGRAM = 0x2000F5F5;
5099 const GUESTFS_PROTOCOL_VERSION = 1;
5100
5101 /* These constants must be larger than any possible message length. */
5102 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5103 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5104
5105 enum guestfs_message_direction {
5106   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5107   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5108 };
5109
5110 enum guestfs_message_status {
5111   GUESTFS_STATUS_OK = 0,
5112   GUESTFS_STATUS_ERROR = 1
5113 };
5114
5115 const GUESTFS_ERROR_LEN = 256;
5116
5117 struct guestfs_message_error {
5118   string error_message<GUESTFS_ERROR_LEN>;
5119 };
5120
5121 struct guestfs_message_header {
5122   unsigned prog;                     /* GUESTFS_PROGRAM */
5123   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5124   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5125   guestfs_message_direction direction;
5126   unsigned serial;                   /* message serial number */
5127   guestfs_message_status status;
5128 };
5129
5130 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5131
5132 struct guestfs_chunk {
5133   int cancel;                        /* if non-zero, transfer is cancelled */
5134   /* data size is 0 bytes if the transfer has finished successfully */
5135   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5136 };
5137 "
5138
5139 (* Generate the guestfs-structs.h file. *)
5140 and generate_structs_h () =
5141   generate_header CStyle LGPLv2;
5142
5143   (* This is a public exported header file containing various
5144    * structures.  The structures are carefully written to have
5145    * exactly the same in-memory format as the XDR structures that
5146    * we use on the wire to the daemon.  The reason for creating
5147    * copies of these structures here is just so we don't have to
5148    * export the whole of guestfs_protocol.h (which includes much
5149    * unrelated and XDR-dependent stuff that we don't want to be
5150    * public, or required by clients).
5151    *
5152    * To reiterate, we will pass these structures to and from the
5153    * client with a simple assignment or memcpy, so the format
5154    * must be identical to what rpcgen / the RFC defines.
5155    *)
5156
5157   (* Public structures. *)
5158   List.iter (
5159     fun (typ, cols) ->
5160       pr "struct guestfs_%s {\n" typ;
5161       List.iter (
5162         function
5163         | name, FChar -> pr "  char %s;\n" name
5164         | name, FString -> pr "  char *%s;\n" name
5165         | name, FBuffer ->
5166             pr "  uint32_t %s_len;\n" name;
5167             pr "  char *%s;\n" name
5168         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5169         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5170         | name, FInt32 -> pr "  int32_t %s;\n" name
5171         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5172         | name, FInt64 -> pr "  int64_t %s;\n" name
5173         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5174       ) cols;
5175       pr "};\n";
5176       pr "\n";
5177       pr "struct guestfs_%s_list {\n" typ;
5178       pr "  uint32_t len;\n";
5179       pr "  struct guestfs_%s *val;\n" typ;
5180       pr "};\n";
5181       pr "\n";
5182       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5183       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5184       pr "\n"
5185   ) structs
5186
5187 (* Generate the guestfs-actions.h file. *)
5188 and generate_actions_h () =
5189   generate_header CStyle LGPLv2;
5190   List.iter (
5191     fun (shortname, style, _, _, _, _, _) ->
5192       let name = "guestfs_" ^ shortname in
5193       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5194         name style
5195   ) all_functions
5196
5197 (* Generate the guestfs-internal-actions.h file. *)
5198 and generate_internal_actions_h () =
5199   generate_header CStyle LGPLv2;
5200   List.iter (
5201     fun (shortname, style, _, _, _, _, _) ->
5202       let name = "guestfs__" ^ shortname in
5203       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5204         name style
5205   ) non_daemon_functions
5206
5207 (* Generate the client-side dispatch stubs. *)
5208 and generate_client_actions () =
5209   generate_header CStyle LGPLv2;
5210
5211   pr "\
5212 #include <stdio.h>
5213 #include <stdlib.h>
5214 #include <stdint.h>
5215 #include <inttypes.h>
5216
5217 #include \"guestfs.h\"
5218 #include \"guestfs-internal.h\"
5219 #include \"guestfs-internal-actions.h\"
5220 #include \"guestfs_protocol.h\"
5221
5222 #define error guestfs_error
5223 //#define perrorf guestfs_perrorf
5224 #define safe_malloc guestfs_safe_malloc
5225 #define safe_realloc guestfs_safe_realloc
5226 //#define safe_strdup guestfs_safe_strdup
5227 #define safe_memdup guestfs_safe_memdup
5228
5229 /* Check the return message from a call for validity. */
5230 static int
5231 check_reply_header (guestfs_h *g,
5232                     const struct guestfs_message_header *hdr,
5233                     unsigned int proc_nr, unsigned int serial)
5234 {
5235   if (hdr->prog != GUESTFS_PROGRAM) {
5236     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5237     return -1;
5238   }
5239   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5240     error (g, \"wrong protocol version (%%d/%%d)\",
5241            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5242     return -1;
5243   }
5244   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5245     error (g, \"unexpected message direction (%%d/%%d)\",
5246            hdr->direction, GUESTFS_DIRECTION_REPLY);
5247     return -1;
5248   }
5249   if (hdr->proc != proc_nr) {
5250     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5251     return -1;
5252   }
5253   if (hdr->serial != serial) {
5254     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5255     return -1;
5256   }
5257
5258   return 0;
5259 }
5260
5261 /* Check we are in the right state to run a high-level action. */
5262 static int
5263 check_state (guestfs_h *g, const char *caller)
5264 {
5265   if (!guestfs__is_ready (g)) {
5266     if (guestfs__is_config (g) || guestfs__is_launching (g))
5267       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5268         caller);
5269     else
5270       error (g, \"%%s called from the wrong state, %%d != READY\",
5271         caller, guestfs__get_state (g));
5272     return -1;
5273   }
5274   return 0;
5275 }
5276
5277 ";
5278
5279   (* Generate code to generate guestfish call traces. *)
5280   let trace_call shortname style =
5281     pr "  if (guestfs__get_trace (g)) {\n";
5282
5283     let needs_i =
5284       List.exists (function
5285                    | StringList _ | DeviceList _ -> true
5286                    | _ -> false) (snd style) in
5287     if needs_i then (
5288       pr "    int i;\n";
5289       pr "\n"
5290     );
5291
5292     pr "    printf (\"%s\");\n" shortname;
5293     List.iter (
5294       function
5295       | String n                        (* strings *)
5296       | Device n
5297       | Pathname n
5298       | Dev_or_Path n
5299       | FileIn n
5300       | FileOut n ->
5301           (* guestfish doesn't support string escaping, so neither do we *)
5302           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5303       | OptString n ->                  (* string option *)
5304           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5305           pr "    else printf (\" null\");\n"
5306       | StringList n
5307       | DeviceList n ->                 (* string list *)
5308           pr "    putchar (' ');\n";
5309           pr "    putchar ('\"');\n";
5310           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5311           pr "      if (i > 0) putchar (' ');\n";
5312           pr "      fputs (%s[i], stdout);\n" n;
5313           pr "    }\n";
5314           pr "    putchar ('\"');\n";
5315       | Bool n ->                       (* boolean *)
5316           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5317       | Int n ->                        (* int *)
5318           pr "    printf (\" %%d\", %s);\n" n
5319       | Int64 n ->
5320           pr "    printf (\" %%\" PRIi64, %s);\n" n
5321     ) (snd style);
5322     pr "    putchar ('\\n');\n";
5323     pr "  }\n";
5324     pr "\n";
5325   in
5326
5327   (* For non-daemon functions, generate a wrapper around each function. *)
5328   List.iter (
5329     fun (shortname, style, _, _, _, _, _) ->
5330       let name = "guestfs_" ^ shortname in
5331
5332       generate_prototype ~extern:false ~semicolon:false ~newline:true
5333         ~handle:"g" name style;
5334       pr "{\n";
5335       trace_call shortname style;
5336       pr "  return guestfs__%s " shortname;
5337       generate_c_call_args ~handle:"g" style;
5338       pr ";\n";
5339       pr "}\n";
5340       pr "\n"
5341   ) non_daemon_functions;
5342
5343   (* Client-side stubs for each function. *)
5344   List.iter (
5345     fun (shortname, style, _, _, _, _, _) ->
5346       let name = "guestfs_" ^ shortname in
5347
5348       (* Generate the action stub. *)
5349       generate_prototype ~extern:false ~semicolon:false ~newline:true
5350         ~handle:"g" name style;
5351
5352       let error_code =
5353         match fst style with
5354         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5355         | RConstString _ | RConstOptString _ ->
5356             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5357         | RString _ | RStringList _
5358         | RStruct _ | RStructList _
5359         | RHashtable _ | RBufferOut _ ->
5360             "NULL" in
5361
5362       pr "{\n";
5363
5364       (match snd style with
5365        | [] -> ()
5366        | _ -> pr "  struct %s_args args;\n" name
5367       );
5368
5369       pr "  guestfs_message_header hdr;\n";
5370       pr "  guestfs_message_error err;\n";
5371       let has_ret =
5372         match fst style with
5373         | RErr -> false
5374         | RConstString _ | RConstOptString _ ->
5375             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5376         | RInt _ | RInt64 _
5377         | RBool _ | RString _ | RStringList _
5378         | RStruct _ | RStructList _
5379         | RHashtable _ | RBufferOut _ ->
5380             pr "  struct %s_ret ret;\n" name;
5381             true in
5382
5383       pr "  int serial;\n";
5384       pr "  int r;\n";
5385       pr "\n";
5386       trace_call shortname style;
5387       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5388       pr "  guestfs___set_busy (g);\n";
5389       pr "\n";
5390
5391       (* Send the main header and arguments. *)
5392       (match snd style with
5393        | [] ->
5394            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5395              (String.uppercase shortname)
5396        | args ->
5397            List.iter (
5398              function
5399              | Pathname n | Device n | Dev_or_Path n | String n ->
5400                  pr "  args.%s = (char *) %s;\n" n n
5401              | OptString n ->
5402                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5403              | StringList n | DeviceList n ->
5404                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5405                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5406              | Bool n ->
5407                  pr "  args.%s = %s;\n" n n
5408              | Int n ->
5409                  pr "  args.%s = %s;\n" n n
5410              | Int64 n ->
5411                  pr "  args.%s = %s;\n" n n
5412              | FileIn _ | FileOut _ -> ()
5413            ) args;
5414            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5415              (String.uppercase shortname);
5416            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5417              name;
5418       );
5419       pr "  if (serial == -1) {\n";
5420       pr "    guestfs___end_busy (g);\n";
5421       pr "    return %s;\n" error_code;
5422       pr "  }\n";
5423       pr "\n";
5424
5425       (* Send any additional files (FileIn) requested. *)
5426       let need_read_reply_label = ref false in
5427       List.iter (
5428         function
5429         | FileIn n ->
5430             pr "  r = guestfs___send_file (g, %s);\n" n;
5431             pr "  if (r == -1) {\n";
5432             pr "    guestfs___end_busy (g);\n";
5433             pr "    return %s;\n" error_code;
5434             pr "  }\n";
5435             pr "  if (r == -2) /* daemon cancelled */\n";
5436             pr "    goto read_reply;\n";
5437             need_read_reply_label := true;
5438             pr "\n";
5439         | _ -> ()
5440       ) (snd style);
5441
5442       (* Wait for the reply from the remote end. *)
5443       if !need_read_reply_label then pr " read_reply:\n";
5444       pr "  memset (&hdr, 0, sizeof hdr);\n";
5445       pr "  memset (&err, 0, sizeof err);\n";
5446       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5447       pr "\n";
5448       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5449       if not has_ret then
5450         pr "NULL, NULL"
5451       else
5452         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5453       pr ");\n";
5454
5455       pr "  if (r == -1) {\n";
5456       pr "    guestfs___end_busy (g);\n";
5457       pr "    return %s;\n" error_code;
5458       pr "  }\n";
5459       pr "\n";
5460
5461       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5462         (String.uppercase shortname);
5463       pr "    guestfs___end_busy (g);\n";
5464       pr "    return %s;\n" error_code;
5465       pr "  }\n";
5466       pr "\n";
5467
5468       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5469       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5470       pr "    free (err.error_message);\n";
5471       pr "    guestfs___end_busy (g);\n";
5472       pr "    return %s;\n" error_code;
5473       pr "  }\n";
5474       pr "\n";
5475
5476       (* Expecting to receive further files (FileOut)? *)
5477       List.iter (
5478         function
5479         | FileOut n ->
5480             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5481             pr "    guestfs___end_busy (g);\n";
5482             pr "    return %s;\n" error_code;
5483             pr "  }\n";
5484             pr "\n";
5485         | _ -> ()
5486       ) (snd style);
5487
5488       pr "  guestfs___end_busy (g);\n";
5489
5490       (match fst style with
5491        | RErr -> pr "  return 0;\n"
5492        | RInt n | RInt64 n | RBool n ->
5493            pr "  return ret.%s;\n" n
5494        | RConstString _ | RConstOptString _ ->
5495            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5496        | RString n ->
5497            pr "  return ret.%s; /* caller will free */\n" n
5498        | RStringList n | RHashtable n ->
5499            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5500            pr "  ret.%s.%s_val =\n" n n;
5501            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5502            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5503              n n;
5504            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5505            pr "  return ret.%s.%s_val;\n" n n
5506        | RStruct (n, _) ->
5507            pr "  /* caller will free this */\n";
5508            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5509        | RStructList (n, _) ->
5510            pr "  /* caller will free this */\n";
5511            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5512        | RBufferOut n ->
5513            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5514            pr "   * _val might be NULL here.  To make the API saner for\n";
5515            pr "   * callers, we turn this case into a unique pointer (using\n";
5516            pr "   * malloc(1)).\n";
5517            pr "   */\n";
5518            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5519            pr "    *size_r = ret.%s.%s_len;\n" n n;
5520            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5521            pr "  } else {\n";
5522            pr "    free (ret.%s.%s_val);\n" n n;
5523            pr "    char *p = safe_malloc (g, 1);\n";
5524            pr "    *size_r = ret.%s.%s_len;\n" n n;
5525            pr "    return p;\n";
5526            pr "  }\n";
5527       );
5528
5529       pr "}\n\n"
5530   ) daemon_functions;
5531
5532   (* Functions to free structures. *)
5533   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5534   pr " * structure format is identical to the XDR format.  See note in\n";
5535   pr " * generator.ml.\n";
5536   pr " */\n";
5537   pr "\n";
5538
5539   List.iter (
5540     fun (typ, _) ->
5541       pr "void\n";
5542       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5543       pr "{\n";
5544       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5545       pr "  free (x);\n";
5546       pr "}\n";
5547       pr "\n";
5548
5549       pr "void\n";
5550       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5551       pr "{\n";
5552       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5553       pr "  free (x);\n";
5554       pr "}\n";
5555       pr "\n";
5556
5557   ) structs;
5558
5559 (* Generate daemon/actions.h. *)
5560 and generate_daemon_actions_h () =
5561   generate_header CStyle GPLv2;
5562
5563   pr "#include \"../src/guestfs_protocol.h\"\n";
5564   pr "\n";
5565
5566   List.iter (
5567     fun (name, style, _, _, _, _, _) ->
5568       generate_prototype
5569         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5570         name style;
5571   ) daemon_functions
5572
5573 (* Generate the server-side stubs. *)
5574 and generate_daemon_actions () =
5575   generate_header CStyle GPLv2;
5576
5577   pr "#include <config.h>\n";
5578   pr "\n";
5579   pr "#include <stdio.h>\n";
5580   pr "#include <stdlib.h>\n";
5581   pr "#include <string.h>\n";
5582   pr "#include <inttypes.h>\n";
5583   pr "#include <rpc/types.h>\n";
5584   pr "#include <rpc/xdr.h>\n";
5585   pr "\n";
5586   pr "#include \"daemon.h\"\n";
5587   pr "#include \"c-ctype.h\"\n";
5588   pr "#include \"../src/guestfs_protocol.h\"\n";
5589   pr "#include \"actions.h\"\n";
5590   pr "\n";
5591
5592   List.iter (
5593     fun (name, style, _, _, _, _, _) ->
5594       (* Generate server-side stubs. *)
5595       pr "static void %s_stub (XDR *xdr_in)\n" name;
5596       pr "{\n";
5597       let error_code =
5598         match fst style with
5599         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5600         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5601         | RBool _ -> pr "  int r;\n"; "-1"
5602         | RConstString _ | RConstOptString _ ->
5603             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5604         | RString _ -> pr "  char *r;\n"; "NULL"
5605         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5606         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5607         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5608         | RBufferOut _ ->
5609             pr "  size_t size = 1;\n";
5610             pr "  char *r;\n";
5611             "NULL" in
5612
5613       (match snd style with
5614        | [] -> ()
5615        | args ->
5616            pr "  struct guestfs_%s_args args;\n" name;
5617            List.iter (
5618              function
5619              | Device n | Dev_or_Path n
5620              | Pathname n
5621              | String n -> ()
5622              | OptString n -> pr "  char *%s;\n" n
5623              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5624              | Bool n -> pr "  int %s;\n" n
5625              | Int n -> pr "  int %s;\n" n
5626              | Int64 n -> pr "  int64_t %s;\n" n
5627              | FileIn _ | FileOut _ -> ()
5628            ) args
5629       );
5630       pr "\n";
5631
5632       (match snd style with
5633        | [] -> ()
5634        | args ->
5635            pr "  memset (&args, 0, sizeof args);\n";
5636            pr "\n";
5637            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5638            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5639            pr "    return;\n";
5640            pr "  }\n";
5641            let pr_args n =
5642              pr "  char *%s = args.%s;\n" n n
5643            in
5644            let pr_list_handling_code n =
5645              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5646              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5647              pr "  if (%s == NULL) {\n" n;
5648              pr "    reply_with_perror (\"realloc\");\n";
5649              pr "    goto done;\n";
5650              pr "  }\n";
5651              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5652              pr "  args.%s.%s_val = %s;\n" n n n;
5653            in
5654            List.iter (
5655              function
5656              | Pathname n ->
5657                  pr_args n;
5658                  pr "  ABS_PATH (%s, goto done);\n" n;
5659              | Device n ->
5660                  pr_args n;
5661                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5662              | Dev_or_Path n ->
5663                  pr_args n;
5664                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5665              | String n -> pr_args n
5666              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5667              | StringList n ->
5668                  pr_list_handling_code n;
5669              | DeviceList n ->
5670                  pr_list_handling_code n;
5671                  pr "  /* Ensure that each is a device,\n";
5672                  pr "   * and perform device name translation. */\n";
5673                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5674                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5675                  pr "  }\n";
5676              | Bool n -> pr "  %s = args.%s;\n" n n
5677              | Int n -> pr "  %s = args.%s;\n" n n
5678              | Int64 n -> pr "  %s = args.%s;\n" n n
5679              | FileIn _ | FileOut _ -> ()
5680            ) args;
5681            pr "\n"
5682       );
5683
5684
5685       (* this is used at least for do_equal *)
5686       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5687         (* Emit NEED_ROOT just once, even when there are two or
5688            more Pathname args *)
5689         pr "  NEED_ROOT (goto done);\n";
5690       );
5691
5692       (* Don't want to call the impl with any FileIn or FileOut
5693        * parameters, since these go "outside" the RPC protocol.
5694        *)
5695       let args' =
5696         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5697           (snd style) in
5698       pr "  r = do_%s " name;
5699       generate_c_call_args (fst style, args');
5700       pr ";\n";
5701
5702       (match fst style with
5703        | RErr | RInt _ | RInt64 _ | RBool _
5704        | RConstString _ | RConstOptString _
5705        | RString _ | RStringList _ | RHashtable _
5706        | RStruct (_, _) | RStructList (_, _) ->
5707            pr "  if (r == %s)\n" error_code;
5708            pr "    /* do_%s has already called reply_with_error */\n" name;
5709            pr "    goto done;\n";
5710            pr "\n"
5711        | RBufferOut _ ->
5712            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5713            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5714            pr "   */\n";
5715            pr "  if (size == 1 && r == %s)\n" error_code;
5716            pr "    /* do_%s has already called reply_with_error */\n" name;
5717            pr "    goto done;\n";
5718            pr "\n"
5719       );
5720
5721       (* If there are any FileOut parameters, then the impl must
5722        * send its own reply.
5723        *)
5724       let no_reply =
5725         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5726       if no_reply then
5727         pr "  /* do_%s has already sent a reply */\n" name
5728       else (
5729         match fst style with
5730         | RErr -> pr "  reply (NULL, NULL);\n"
5731         | RInt n | RInt64 n | RBool n ->
5732             pr "  struct guestfs_%s_ret ret;\n" name;
5733             pr "  ret.%s = r;\n" n;
5734             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5735               name
5736         | RConstString _ | RConstOptString _ ->
5737             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5738         | RString n ->
5739             pr "  struct guestfs_%s_ret ret;\n" name;
5740             pr "  ret.%s = r;\n" n;
5741             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5742               name;
5743             pr "  free (r);\n"
5744         | RStringList n | RHashtable n ->
5745             pr "  struct guestfs_%s_ret ret;\n" name;
5746             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5747             pr "  ret.%s.%s_val = r;\n" n n;
5748             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5749               name;
5750             pr "  free_strings (r);\n"
5751         | RStruct (n, _) ->
5752             pr "  struct guestfs_%s_ret ret;\n" name;
5753             pr "  ret.%s = *r;\n" n;
5754             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5755               name;
5756             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5757               name
5758         | RStructList (n, _) ->
5759             pr "  struct guestfs_%s_ret ret;\n" name;
5760             pr "  ret.%s = *r;\n" n;
5761             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5762               name;
5763             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5764               name
5765         | RBufferOut n ->
5766             pr "  struct guestfs_%s_ret ret;\n" name;
5767             pr "  ret.%s.%s_val = r;\n" n n;
5768             pr "  ret.%s.%s_len = size;\n" n n;
5769             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5770               name;
5771             pr "  free (r);\n"
5772       );
5773
5774       (* Free the args. *)
5775       (match snd style with
5776        | [] ->
5777            pr "done: ;\n";
5778        | _ ->
5779            pr "done:\n";
5780            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5781              name
5782       );
5783
5784       pr "}\n\n";
5785   ) daemon_functions;
5786
5787   (* Dispatch function. *)
5788   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5789   pr "{\n";
5790   pr "  switch (proc_nr) {\n";
5791
5792   List.iter (
5793     fun (name, style, _, _, _, _, _) ->
5794       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5795       pr "      %s_stub (xdr_in);\n" name;
5796       pr "      break;\n"
5797   ) daemon_functions;
5798
5799   pr "    default:\n";
5800   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";
5801   pr "  }\n";
5802   pr "}\n";
5803   pr "\n";
5804
5805   (* LVM columns and tokenization functions. *)
5806   (* XXX This generates crap code.  We should rethink how we
5807    * do this parsing.
5808    *)
5809   List.iter (
5810     function
5811     | typ, cols ->
5812         pr "static const char *lvm_%s_cols = \"%s\";\n"
5813           typ (String.concat "," (List.map fst cols));
5814         pr "\n";
5815
5816         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5817         pr "{\n";
5818         pr "  char *tok, *p, *next;\n";
5819         pr "  int i, j;\n";
5820         pr "\n";
5821         (*
5822           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5823           pr "\n";
5824         *)
5825         pr "  if (!str) {\n";
5826         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5827         pr "    return -1;\n";
5828         pr "  }\n";
5829         pr "  if (!*str || c_isspace (*str)) {\n";
5830         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5831         pr "    return -1;\n";
5832         pr "  }\n";
5833         pr "  tok = str;\n";
5834         List.iter (
5835           fun (name, coltype) ->
5836             pr "  if (!tok) {\n";
5837             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5838             pr "    return -1;\n";
5839             pr "  }\n";
5840             pr "  p = strchrnul (tok, ',');\n";
5841             pr "  if (*p) next = p+1; else next = NULL;\n";
5842             pr "  *p = '\\0';\n";
5843             (match coltype with
5844              | FString ->
5845                  pr "  r->%s = strdup (tok);\n" name;
5846                  pr "  if (r->%s == NULL) {\n" name;
5847                  pr "    perror (\"strdup\");\n";
5848                  pr "    return -1;\n";
5849                  pr "  }\n"
5850              | FUUID ->
5851                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5852                  pr "    if (tok[j] == '\\0') {\n";
5853                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5854                  pr "      return -1;\n";
5855                  pr "    } else if (tok[j] != '-')\n";
5856                  pr "      r->%s[i++] = tok[j];\n" name;
5857                  pr "  }\n";
5858              | FBytes ->
5859                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5860                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5861                  pr "    return -1;\n";
5862                  pr "  }\n";
5863              | FInt64 ->
5864                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5865                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5866                  pr "    return -1;\n";
5867                  pr "  }\n";
5868              | FOptPercent ->
5869                  pr "  if (tok[0] == '\\0')\n";
5870                  pr "    r->%s = -1;\n" name;
5871                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5872                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5873                  pr "    return -1;\n";
5874                  pr "  }\n";
5875              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5876                  assert false (* can never be an LVM column *)
5877             );
5878             pr "  tok = next;\n";
5879         ) cols;
5880
5881         pr "  if (tok != NULL) {\n";
5882         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5883         pr "    return -1;\n";
5884         pr "  }\n";
5885         pr "  return 0;\n";
5886         pr "}\n";
5887         pr "\n";
5888
5889         pr "guestfs_int_lvm_%s_list *\n" typ;
5890         pr "parse_command_line_%ss (void)\n" typ;
5891         pr "{\n";
5892         pr "  char *out, *err;\n";
5893         pr "  char *p, *pend;\n";
5894         pr "  int r, i;\n";
5895         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5896         pr "  void *newp;\n";
5897         pr "\n";
5898         pr "  ret = malloc (sizeof *ret);\n";
5899         pr "  if (!ret) {\n";
5900         pr "    reply_with_perror (\"malloc\");\n";
5901         pr "    return NULL;\n";
5902         pr "  }\n";
5903         pr "\n";
5904         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5905         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5906         pr "\n";
5907         pr "  r = command (&out, &err,\n";
5908         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5909         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5910         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5911         pr "  if (r == -1) {\n";
5912         pr "    reply_with_error (\"%%s\", err);\n";
5913         pr "    free (out);\n";
5914         pr "    free (err);\n";
5915         pr "    free (ret);\n";
5916         pr "    return NULL;\n";
5917         pr "  }\n";
5918         pr "\n";
5919         pr "  free (err);\n";
5920         pr "\n";
5921         pr "  /* Tokenize each line of the output. */\n";
5922         pr "  p = out;\n";
5923         pr "  i = 0;\n";
5924         pr "  while (p) {\n";
5925         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5926         pr "    if (pend) {\n";
5927         pr "      *pend = '\\0';\n";
5928         pr "      pend++;\n";
5929         pr "    }\n";
5930         pr "\n";
5931         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5932         pr "      p++;\n";
5933         pr "\n";
5934         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5935         pr "      p = pend;\n";
5936         pr "      continue;\n";
5937         pr "    }\n";
5938         pr "\n";
5939         pr "    /* Allocate some space to store this next entry. */\n";
5940         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5941         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5942         pr "    if (newp == NULL) {\n";
5943         pr "      reply_with_perror (\"realloc\");\n";
5944         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5945         pr "      free (ret);\n";
5946         pr "      free (out);\n";
5947         pr "      return NULL;\n";
5948         pr "    }\n";
5949         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5950         pr "\n";
5951         pr "    /* Tokenize the next entry. */\n";
5952         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5953         pr "    if (r == -1) {\n";
5954         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5955         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5956         pr "      free (ret);\n";
5957         pr "      free (out);\n";
5958         pr "      return NULL;\n";
5959         pr "    }\n";
5960         pr "\n";
5961         pr "    ++i;\n";
5962         pr "    p = pend;\n";
5963         pr "  }\n";
5964         pr "\n";
5965         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5966         pr "\n";
5967         pr "  free (out);\n";
5968         pr "  return ret;\n";
5969         pr "}\n"
5970
5971   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5972
5973 (* Generate a list of function names, for debugging in the daemon.. *)
5974 and generate_daemon_names () =
5975   generate_header CStyle GPLv2;
5976
5977   pr "#include <config.h>\n";
5978   pr "\n";
5979   pr "#include \"daemon.h\"\n";
5980   pr "\n";
5981
5982   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5983   pr "const char *function_names[] = {\n";
5984   List.iter (
5985     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5986   ) daemon_functions;
5987   pr "};\n";
5988
5989 (* Generate the optional groups for the daemon to implement
5990  * guestfs_available.
5991  *)
5992 and generate_daemon_optgroups_c () =
5993   generate_header CStyle GPLv2;
5994
5995   pr "#include <config.h>\n";
5996   pr "\n";
5997   pr "#include \"daemon.h\"\n";
5998   pr "#include \"optgroups.h\"\n";
5999   pr "\n";
6000
6001   pr "struct optgroup optgroups[] = {\n";
6002   List.iter (
6003     fun (group, _) ->
6004       pr "  { \"%s\", optgroup_%s_available },\n" group group
6005   ) optgroups;
6006   pr "  { NULL, NULL }\n";
6007   pr "};\n"
6008
6009 and generate_daemon_optgroups_h () =
6010   generate_header CStyle GPLv2;
6011
6012   List.iter (
6013     fun (group, _) ->
6014       pr "extern int optgroup_%s_available (void);\n" group
6015   ) optgroups
6016
6017 (* Generate the tests. *)
6018 and generate_tests () =
6019   generate_header CStyle GPLv2;
6020
6021   pr "\
6022 #include <stdio.h>
6023 #include <stdlib.h>
6024 #include <string.h>
6025 #include <unistd.h>
6026 #include <sys/types.h>
6027 #include <fcntl.h>
6028
6029 #include \"guestfs.h\"
6030 #include \"guestfs-internal.h\"
6031
6032 static guestfs_h *g;
6033 static int suppress_error = 0;
6034
6035 static void print_error (guestfs_h *g, void *data, const char *msg)
6036 {
6037   if (!suppress_error)
6038     fprintf (stderr, \"%%s\\n\", msg);
6039 }
6040
6041 /* FIXME: nearly identical code appears in fish.c */
6042 static void print_strings (char *const *argv)
6043 {
6044   int argc;
6045
6046   for (argc = 0; argv[argc] != NULL; ++argc)
6047     printf (\"\\t%%s\\n\", argv[argc]);
6048 }
6049
6050 /*
6051 static void print_table (char const *const *argv)
6052 {
6053   int i;
6054
6055   for (i = 0; argv[i] != NULL; i += 2)
6056     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6057 }
6058 */
6059
6060 ";
6061
6062   (* Generate a list of commands which are not tested anywhere. *)
6063   pr "static void no_test_warnings (void)\n";
6064   pr "{\n";
6065
6066   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6067   List.iter (
6068     fun (_, _, _, _, tests, _, _) ->
6069       let tests = filter_map (
6070         function
6071         | (_, (Always|If _|Unless _), test) -> Some test
6072         | (_, Disabled, _) -> None
6073       ) tests in
6074       let seq = List.concat (List.map seq_of_test tests) in
6075       let cmds_tested = List.map List.hd seq in
6076       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6077   ) all_functions;
6078
6079   List.iter (
6080     fun (name, _, _, _, _, _, _) ->
6081       if not (Hashtbl.mem hash name) then
6082         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6083   ) all_functions;
6084
6085   pr "}\n";
6086   pr "\n";
6087
6088   (* Generate the actual tests.  Note that we generate the tests
6089    * in reverse order, deliberately, so that (in general) the
6090    * newest tests run first.  This makes it quicker and easier to
6091    * debug them.
6092    *)
6093   let test_names =
6094     List.map (
6095       fun (name, _, _, flags, tests, _, _) ->
6096         mapi (generate_one_test name flags) tests
6097     ) (List.rev all_functions) in
6098   let test_names = List.concat test_names in
6099   let nr_tests = List.length test_names in
6100
6101   pr "\
6102 int main (int argc, char *argv[])
6103 {
6104   char c = 0;
6105   unsigned long int n_failed = 0;
6106   const char *filename;
6107   int fd;
6108   int nr_tests, test_num = 0;
6109
6110   setbuf (stdout, NULL);
6111
6112   no_test_warnings ();
6113
6114   g = guestfs_create ();
6115   if (g == NULL) {
6116     printf (\"guestfs_create FAILED\\n\");
6117     exit (EXIT_FAILURE);
6118   }
6119
6120   guestfs_set_error_handler (g, print_error, NULL);
6121
6122   guestfs_set_path (g, \"../appliance\");
6123
6124   filename = \"test1.img\";
6125   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6126   if (fd == -1) {
6127     perror (filename);
6128     exit (EXIT_FAILURE);
6129   }
6130   if (lseek (fd, %d, SEEK_SET) == -1) {
6131     perror (\"lseek\");
6132     close (fd);
6133     unlink (filename);
6134     exit (EXIT_FAILURE);
6135   }
6136   if (write (fd, &c, 1) == -1) {
6137     perror (\"write\");
6138     close (fd);
6139     unlink (filename);
6140     exit (EXIT_FAILURE);
6141   }
6142   if (close (fd) == -1) {
6143     perror (filename);
6144     unlink (filename);
6145     exit (EXIT_FAILURE);
6146   }
6147   if (guestfs_add_drive (g, filename) == -1) {
6148     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6149     exit (EXIT_FAILURE);
6150   }
6151
6152   filename = \"test2.img\";
6153   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6154   if (fd == -1) {
6155     perror (filename);
6156     exit (EXIT_FAILURE);
6157   }
6158   if (lseek (fd, %d, SEEK_SET) == -1) {
6159     perror (\"lseek\");
6160     close (fd);
6161     unlink (filename);
6162     exit (EXIT_FAILURE);
6163   }
6164   if (write (fd, &c, 1) == -1) {
6165     perror (\"write\");
6166     close (fd);
6167     unlink (filename);
6168     exit (EXIT_FAILURE);
6169   }
6170   if (close (fd) == -1) {
6171     perror (filename);
6172     unlink (filename);
6173     exit (EXIT_FAILURE);
6174   }
6175   if (guestfs_add_drive (g, filename) == -1) {
6176     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6177     exit (EXIT_FAILURE);
6178   }
6179
6180   filename = \"test3.img\";
6181   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6182   if (fd == -1) {
6183     perror (filename);
6184     exit (EXIT_FAILURE);
6185   }
6186   if (lseek (fd, %d, SEEK_SET) == -1) {
6187     perror (\"lseek\");
6188     close (fd);
6189     unlink (filename);
6190     exit (EXIT_FAILURE);
6191   }
6192   if (write (fd, &c, 1) == -1) {
6193     perror (\"write\");
6194     close (fd);
6195     unlink (filename);
6196     exit (EXIT_FAILURE);
6197   }
6198   if (close (fd) == -1) {
6199     perror (filename);
6200     unlink (filename);
6201     exit (EXIT_FAILURE);
6202   }
6203   if (guestfs_add_drive (g, filename) == -1) {
6204     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6205     exit (EXIT_FAILURE);
6206   }
6207
6208   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6209     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6210     exit (EXIT_FAILURE);
6211   }
6212
6213   if (guestfs_launch (g) == -1) {
6214     printf (\"guestfs_launch FAILED\\n\");
6215     exit (EXIT_FAILURE);
6216   }
6217
6218   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6219   alarm (600);
6220
6221   /* Cancel previous alarm. */
6222   alarm (0);
6223
6224   nr_tests = %d;
6225
6226 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6227
6228   iteri (
6229     fun i test_name ->
6230       pr "  test_num++;\n";
6231       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6232       pr "  if (%s () == -1) {\n" test_name;
6233       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6234       pr "    n_failed++;\n";
6235       pr "  }\n";
6236   ) test_names;
6237   pr "\n";
6238
6239   pr "  guestfs_close (g);\n";
6240   pr "  unlink (\"test1.img\");\n";
6241   pr "  unlink (\"test2.img\");\n";
6242   pr "  unlink (\"test3.img\");\n";
6243   pr "\n";
6244
6245   pr "  if (n_failed > 0) {\n";
6246   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6247   pr "    exit (EXIT_FAILURE);\n";
6248   pr "  }\n";
6249   pr "\n";
6250
6251   pr "  exit (EXIT_SUCCESS);\n";
6252   pr "}\n"
6253
6254 and generate_one_test name flags i (init, prereq, test) =
6255   let test_name = sprintf "test_%s_%d" name i in
6256
6257   pr "\
6258 static int %s_skip (void)
6259 {
6260   const char *str;
6261
6262   str = getenv (\"TEST_ONLY\");
6263   if (str)
6264     return strstr (str, \"%s\") == NULL;
6265   str = getenv (\"SKIP_%s\");
6266   if (str && STREQ (str, \"1\")) return 1;
6267   str = getenv (\"SKIP_TEST_%s\");
6268   if (str && STREQ (str, \"1\")) return 1;
6269   return 0;
6270 }
6271
6272 " test_name name (String.uppercase test_name) (String.uppercase name);
6273
6274   (match prereq with
6275    | Disabled | Always -> ()
6276    | If code | Unless code ->
6277        pr "static int %s_prereq (void)\n" test_name;
6278        pr "{\n";
6279        pr "  %s\n" code;
6280        pr "}\n";
6281        pr "\n";
6282   );
6283
6284   pr "\
6285 static int %s (void)
6286 {
6287   if (%s_skip ()) {
6288     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6289     return 0;
6290   }
6291
6292 " test_name test_name test_name;
6293
6294   (* Optional functions should only be tested if the relevant
6295    * support is available in the daemon.
6296    *)
6297   List.iter (
6298     function
6299     | Optional group ->
6300         pr "  {\n";
6301         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6302         pr "    int r;\n";
6303         pr "    suppress_error = 1;\n";
6304         pr "    r = guestfs_available (g, (char **) groups);\n";
6305         pr "    suppress_error = 0;\n";
6306         pr "    if (r == -1) {\n";
6307         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6308         pr "      return 0;\n";
6309         pr "    }\n";
6310         pr "  }\n";
6311     | _ -> ()
6312   ) flags;
6313
6314   (match prereq with
6315    | Disabled ->
6316        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6317    | If _ ->
6318        pr "  if (! %s_prereq ()) {\n" test_name;
6319        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6320        pr "    return 0;\n";
6321        pr "  }\n";
6322        pr "\n";
6323        generate_one_test_body name i test_name init test;
6324    | Unless _ ->
6325        pr "  if (%s_prereq ()) {\n" test_name;
6326        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6327        pr "    return 0;\n";
6328        pr "  }\n";
6329        pr "\n";
6330        generate_one_test_body name i test_name init test;
6331    | Always ->
6332        generate_one_test_body name i test_name init test
6333   );
6334
6335   pr "  return 0;\n";
6336   pr "}\n";
6337   pr "\n";
6338   test_name
6339
6340 and generate_one_test_body name i test_name init test =
6341   (match init with
6342    | InitNone (* XXX at some point, InitNone and InitEmpty became
6343                * folded together as the same thing.  Really we should
6344                * make InitNone do nothing at all, but the tests may
6345                * need to be checked to make sure this is OK.
6346                *)
6347    | InitEmpty ->
6348        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6349        List.iter (generate_test_command_call test_name)
6350          [["blockdev_setrw"; "/dev/sda"];
6351           ["umount_all"];
6352           ["lvm_remove_all"]]
6353    | InitPartition ->
6354        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6355        List.iter (generate_test_command_call test_name)
6356          [["blockdev_setrw"; "/dev/sda"];
6357           ["umount_all"];
6358           ["lvm_remove_all"];
6359           ["part_disk"; "/dev/sda"; "mbr"]]
6360    | InitBasicFS ->
6361        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6362        List.iter (generate_test_command_call test_name)
6363          [["blockdev_setrw"; "/dev/sda"];
6364           ["umount_all"];
6365           ["lvm_remove_all"];
6366           ["part_disk"; "/dev/sda"; "mbr"];
6367           ["mkfs"; "ext2"; "/dev/sda1"];
6368           ["mount"; "/dev/sda1"; "/"]]
6369    | InitBasicFSonLVM ->
6370        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6371          test_name;
6372        List.iter (generate_test_command_call test_name)
6373          [["blockdev_setrw"; "/dev/sda"];
6374           ["umount_all"];
6375           ["lvm_remove_all"];
6376           ["part_disk"; "/dev/sda"; "mbr"];
6377           ["pvcreate"; "/dev/sda1"];
6378           ["vgcreate"; "VG"; "/dev/sda1"];
6379           ["lvcreate"; "LV"; "VG"; "8"];
6380           ["mkfs"; "ext2"; "/dev/VG/LV"];
6381           ["mount"; "/dev/VG/LV"; "/"]]
6382    | InitISOFS ->
6383        pr "  /* InitISOFS for %s */\n" test_name;
6384        List.iter (generate_test_command_call test_name)
6385          [["blockdev_setrw"; "/dev/sda"];
6386           ["umount_all"];
6387           ["lvm_remove_all"];
6388           ["mount_ro"; "/dev/sdd"; "/"]]
6389   );
6390
6391   let get_seq_last = function
6392     | [] ->
6393         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6394           test_name
6395     | seq ->
6396         let seq = List.rev seq in
6397         List.rev (List.tl seq), List.hd seq
6398   in
6399
6400   match test with
6401   | TestRun seq ->
6402       pr "  /* TestRun for %s (%d) */\n" name i;
6403       List.iter (generate_test_command_call test_name) seq
6404   | TestOutput (seq, expected) ->
6405       pr "  /* TestOutput for %s (%d) */\n" name i;
6406       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6407       let seq, last = get_seq_last seq in
6408       let test () =
6409         pr "    if (STRNEQ (r, expected)) {\n";
6410         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6411         pr "      return -1;\n";
6412         pr "    }\n"
6413       in
6414       List.iter (generate_test_command_call test_name) seq;
6415       generate_test_command_call ~test test_name last
6416   | TestOutputList (seq, expected) ->
6417       pr "  /* TestOutputList for %s (%d) */\n" name i;
6418       let seq, last = get_seq_last seq in
6419       let test () =
6420         iteri (
6421           fun i str ->
6422             pr "    if (!r[%d]) {\n" i;
6423             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6424             pr "      print_strings (r);\n";
6425             pr "      return -1;\n";
6426             pr "    }\n";
6427             pr "    {\n";
6428             pr "      const char *expected = \"%s\";\n" (c_quote str);
6429             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6430             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6431             pr "        return -1;\n";
6432             pr "      }\n";
6433             pr "    }\n"
6434         ) expected;
6435         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6436         pr "      fprintf (stderr, \"%s: extra elements returned from command\\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   | TestOutputListOfDevices (seq, expected) ->
6445       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6446       let seq, last = get_seq_last seq in
6447       let test () =
6448         iteri (
6449           fun i str ->
6450             pr "    if (!r[%d]) {\n" i;
6451             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6452             pr "      print_strings (r);\n";
6453             pr "      return -1;\n";
6454             pr "    }\n";
6455             pr "    {\n";
6456             pr "      const char *expected = \"%s\";\n" (c_quote str);
6457             pr "      r[%d][5] = 's';\n" i;
6458             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6459             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6460             pr "        return -1;\n";
6461             pr "      }\n";
6462             pr "    }\n"
6463         ) expected;
6464         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6465         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6466           test_name;
6467         pr "      print_strings (r);\n";
6468         pr "      return -1;\n";
6469         pr "    }\n"
6470       in
6471       List.iter (generate_test_command_call test_name) seq;
6472       generate_test_command_call ~test test_name last
6473   | TestOutputInt (seq, expected) ->
6474       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6475       let seq, last = get_seq_last seq in
6476       let test () =
6477         pr "    if (r != %d) {\n" expected;
6478         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6479           test_name expected;
6480         pr "               (int) r);\n";
6481         pr "      return -1;\n";
6482         pr "    }\n"
6483       in
6484       List.iter (generate_test_command_call test_name) seq;
6485       generate_test_command_call ~test test_name last
6486   | TestOutputIntOp (seq, op, expected) ->
6487       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6488       let seq, last = get_seq_last seq in
6489       let test () =
6490         pr "    if (! (r %s %d)) {\n" op expected;
6491         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6492           test_name op expected;
6493         pr "               (int) r);\n";
6494         pr "      return -1;\n";
6495         pr "    }\n"
6496       in
6497       List.iter (generate_test_command_call test_name) seq;
6498       generate_test_command_call ~test test_name last
6499   | TestOutputTrue seq ->
6500       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6501       let seq, last = get_seq_last seq in
6502       let test () =
6503         pr "    if (!r) {\n";
6504         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6505           test_name;
6506         pr "      return -1;\n";
6507         pr "    }\n"
6508       in
6509       List.iter (generate_test_command_call test_name) seq;
6510       generate_test_command_call ~test test_name last
6511   | TestOutputFalse seq ->
6512       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6513       let seq, last = get_seq_last seq in
6514       let test () =
6515         pr "    if (r) {\n";
6516         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6517           test_name;
6518         pr "      return -1;\n";
6519         pr "    }\n"
6520       in
6521       List.iter (generate_test_command_call test_name) seq;
6522       generate_test_command_call ~test test_name last
6523   | TestOutputLength (seq, expected) ->
6524       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6525       let seq, last = get_seq_last seq in
6526       let test () =
6527         pr "    int j;\n";
6528         pr "    for (j = 0; j < %d; ++j)\n" expected;
6529         pr "      if (r[j] == NULL) {\n";
6530         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6531           test_name;
6532         pr "        print_strings (r);\n";
6533         pr "        return -1;\n";
6534         pr "      }\n";
6535         pr "    if (r[j] != NULL) {\n";
6536         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6537           test_name;
6538         pr "      print_strings (r);\n";
6539         pr "      return -1;\n";
6540         pr "    }\n"
6541       in
6542       List.iter (generate_test_command_call test_name) seq;
6543       generate_test_command_call ~test test_name last
6544   | TestOutputBuffer (seq, expected) ->
6545       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6546       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6547       let seq, last = get_seq_last seq in
6548       let len = String.length expected in
6549       let test () =
6550         pr "    if (size != %d) {\n" len;
6551         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6552         pr "      return -1;\n";
6553         pr "    }\n";
6554         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6555         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6556         pr "      return -1;\n";
6557         pr "    }\n"
6558       in
6559       List.iter (generate_test_command_call test_name) seq;
6560       generate_test_command_call ~test test_name last
6561   | TestOutputStruct (seq, checks) ->
6562       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6563       let seq, last = get_seq_last seq in
6564       let test () =
6565         List.iter (
6566           function
6567           | CompareWithInt (field, expected) ->
6568               pr "    if (r->%s != %d) {\n" field expected;
6569               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6570                 test_name field expected;
6571               pr "               (int) r->%s);\n" field;
6572               pr "      return -1;\n";
6573               pr "    }\n"
6574           | CompareWithIntOp (field, op, expected) ->
6575               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6576               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6577                 test_name field op expected;
6578               pr "               (int) r->%s);\n" field;
6579               pr "      return -1;\n";
6580               pr "    }\n"
6581           | CompareWithString (field, expected) ->
6582               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6583               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6584                 test_name field expected;
6585               pr "               r->%s);\n" field;
6586               pr "      return -1;\n";
6587               pr "    }\n"
6588           | CompareFieldsIntEq (field1, field2) ->
6589               pr "    if (r->%s != r->%s) {\n" field1 field2;
6590               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6591                 test_name field1 field2;
6592               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6593               pr "      return -1;\n";
6594               pr "    }\n"
6595           | CompareFieldsStrEq (field1, field2) ->
6596               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6597               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6598                 test_name field1 field2;
6599               pr "               r->%s, r->%s);\n" field1 field2;
6600               pr "      return -1;\n";
6601               pr "    }\n"
6602         ) checks
6603       in
6604       List.iter (generate_test_command_call test_name) seq;
6605       generate_test_command_call ~test test_name last
6606   | TestLastFail seq ->
6607       pr "  /* TestLastFail for %s (%d) */\n" name i;
6608       let seq, last = get_seq_last seq in
6609       List.iter (generate_test_command_call test_name) seq;
6610       generate_test_command_call test_name ~expect_error:true last
6611
6612 (* Generate the code to run a command, leaving the result in 'r'.
6613  * If you expect to get an error then you should set expect_error:true.
6614  *)
6615 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6616   match cmd with
6617   | [] -> assert false
6618   | name :: args ->
6619       (* Look up the command to find out what args/ret it has. *)
6620       let style =
6621         try
6622           let _, style, _, _, _, _, _ =
6623             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6624           style
6625         with Not_found ->
6626           failwithf "%s: in test, command %s was not found" test_name name in
6627
6628       if List.length (snd style) <> List.length args then
6629         failwithf "%s: in test, wrong number of args given to %s"
6630           test_name name;
6631
6632       pr "  {\n";
6633
6634       List.iter (
6635         function
6636         | OptString n, "NULL" -> ()
6637         | Pathname n, arg
6638         | Device n, arg
6639         | Dev_or_Path n, arg
6640         | String n, arg
6641         | OptString n, arg ->
6642             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6643         | Int _, _
6644         | Int64 _, _
6645         | Bool _, _
6646         | FileIn _, _ | FileOut _, _ -> ()
6647         | StringList n, "" | DeviceList n, "" ->
6648             pr "    const char *const %s[1] = { NULL };\n" n
6649         | StringList n, arg | DeviceList n, arg ->
6650             let strs = string_split " " arg in
6651             iteri (
6652               fun i str ->
6653                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6654             ) strs;
6655             pr "    const char *const %s[] = {\n" n;
6656             iteri (
6657               fun i _ -> pr "      %s_%d,\n" n i
6658             ) strs;
6659             pr "      NULL\n";
6660             pr "    };\n";
6661       ) (List.combine (snd style) args);
6662
6663       let error_code =
6664         match fst style with
6665         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6666         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6667         | RConstString _ | RConstOptString _ ->
6668             pr "    const char *r;\n"; "NULL"
6669         | RString _ -> pr "    char *r;\n"; "NULL"
6670         | RStringList _ | RHashtable _ ->
6671             pr "    char **r;\n";
6672             pr "    int i;\n";
6673             "NULL"
6674         | RStruct (_, typ) ->
6675             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6676         | RStructList (_, typ) ->
6677             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6678         | RBufferOut _ ->
6679             pr "    char *r;\n";
6680             pr "    size_t size;\n";
6681             "NULL" in
6682
6683       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6684       pr "    r = guestfs_%s (g" name;
6685
6686       (* Generate the parameters. *)
6687       List.iter (
6688         function
6689         | OptString _, "NULL" -> pr ", NULL"
6690         | Pathname n, _
6691         | Device n, _ | Dev_or_Path n, _
6692         | String n, _
6693         | OptString n, _ ->
6694             pr ", %s" n
6695         | FileIn _, arg | FileOut _, arg ->
6696             pr ", \"%s\"" (c_quote arg)
6697         | StringList n, _ | DeviceList n, _ ->
6698             pr ", (char **) %s" n
6699         | Int _, arg ->
6700             let i =
6701               try int_of_string arg
6702               with Failure "int_of_string" ->
6703                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6704             pr ", %d" i
6705         | Int64 _, arg ->
6706             let i =
6707               try Int64.of_string arg
6708               with Failure "int_of_string" ->
6709                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6710             pr ", %Ld" i
6711         | Bool _, arg ->
6712             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6713       ) (List.combine (snd style) args);
6714
6715       (match fst style with
6716        | RBufferOut _ -> pr ", &size"
6717        | _ -> ()
6718       );
6719
6720       pr ");\n";
6721
6722       if not expect_error then
6723         pr "    if (r == %s)\n" error_code
6724       else
6725         pr "    if (r != %s)\n" error_code;
6726       pr "      return -1;\n";
6727
6728       (* Insert the test code. *)
6729       (match test with
6730        | None -> ()
6731        | Some f -> f ()
6732       );
6733
6734       (match fst style with
6735        | RErr | RInt _ | RInt64 _ | RBool _
6736        | RConstString _ | RConstOptString _ -> ()
6737        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6738        | RStringList _ | RHashtable _ ->
6739            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6740            pr "      free (r[i]);\n";
6741            pr "    free (r);\n"
6742        | RStruct (_, typ) ->
6743            pr "    guestfs_free_%s (r);\n" typ
6744        | RStructList (_, typ) ->
6745            pr "    guestfs_free_%s_list (r);\n" typ
6746       );
6747
6748       pr "  }\n"
6749
6750 and c_quote str =
6751   let str = replace_str str "\r" "\\r" in
6752   let str = replace_str str "\n" "\\n" in
6753   let str = replace_str str "\t" "\\t" in
6754   let str = replace_str str "\000" "\\0" in
6755   str
6756
6757 (* Generate a lot of different functions for guestfish. *)
6758 and generate_fish_cmds () =
6759   generate_header CStyle GPLv2;
6760
6761   let all_functions =
6762     List.filter (
6763       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6764     ) all_functions in
6765   let all_functions_sorted =
6766     List.filter (
6767       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6768     ) all_functions_sorted in
6769
6770   pr "#include <stdio.h>\n";
6771   pr "#include <stdlib.h>\n";
6772   pr "#include <string.h>\n";
6773   pr "#include <inttypes.h>\n";
6774   pr "\n";
6775   pr "#include <guestfs.h>\n";
6776   pr "#include \"c-ctype.h\"\n";
6777   pr "#include \"fish.h\"\n";
6778   pr "\n";
6779
6780   (* list_commands function, which implements guestfish -h *)
6781   pr "void list_commands (void)\n";
6782   pr "{\n";
6783   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6784   pr "  list_builtin_commands ();\n";
6785   List.iter (
6786     fun (name, _, _, flags, _, shortdesc, _) ->
6787       let name = replace_char name '_' '-' in
6788       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6789         name shortdesc
6790   ) all_functions_sorted;
6791   pr "  printf (\"    %%s\\n\",";
6792   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6793   pr "}\n";
6794   pr "\n";
6795
6796   (* display_command function, which implements guestfish -h cmd *)
6797   pr "void display_command (const char *cmd)\n";
6798   pr "{\n";
6799   List.iter (
6800     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6801       let name2 = replace_char name '_' '-' in
6802       let alias =
6803         try find_map (function FishAlias n -> Some n | _ -> None) flags
6804         with Not_found -> name in
6805       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6806       let synopsis =
6807         match snd style with
6808         | [] -> name2
6809         | args ->
6810             sprintf "%s %s"
6811               name2 (String.concat " " (List.map name_of_argt args)) in
6812
6813       let warnings =
6814         if List.mem ProtocolLimitWarning flags then
6815           ("\n\n" ^ protocol_limit_warning)
6816         else "" in
6817
6818       (* For DangerWillRobinson commands, we should probably have
6819        * guestfish prompt before allowing you to use them (especially
6820        * in interactive mode). XXX
6821        *)
6822       let warnings =
6823         warnings ^
6824           if List.mem DangerWillRobinson flags then
6825             ("\n\n" ^ danger_will_robinson)
6826           else "" in
6827
6828       let warnings =
6829         warnings ^
6830           match deprecation_notice flags with
6831           | None -> ""
6832           | Some txt -> "\n\n" ^ txt in
6833
6834       let describe_alias =
6835         if name <> alias then
6836           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6837         else "" in
6838
6839       pr "  if (";
6840       pr "STRCASEEQ (cmd, \"%s\")" name;
6841       if name <> name2 then
6842         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6843       if name <> alias then
6844         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6845       pr ")\n";
6846       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6847         name2 shortdesc
6848         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6849          "=head1 DESCRIPTION\n\n" ^
6850          longdesc ^ warnings ^ describe_alias);
6851       pr "  else\n"
6852   ) all_functions;
6853   pr "    display_builtin_command (cmd);\n";
6854   pr "}\n";
6855   pr "\n";
6856
6857   let emit_print_list_function typ =
6858     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6859       typ typ typ;
6860     pr "{\n";
6861     pr "  unsigned int i;\n";
6862     pr "\n";
6863     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6864     pr "    printf (\"[%%d] = {\\n\", i);\n";
6865     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6866     pr "    printf (\"}\\n\");\n";
6867     pr "  }\n";
6868     pr "}\n";
6869     pr "\n";
6870   in
6871
6872   (* print_* functions *)
6873   List.iter (
6874     fun (typ, cols) ->
6875       let needs_i =
6876         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6877
6878       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6879       pr "{\n";
6880       if needs_i then (
6881         pr "  unsigned int i;\n";
6882         pr "\n"
6883       );
6884       List.iter (
6885         function
6886         | name, FString ->
6887             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6888         | name, FUUID ->
6889             pr "  printf (\"%%s%s: \", indent);\n" name;
6890             pr "  for (i = 0; i < 32; ++i)\n";
6891             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6892             pr "  printf (\"\\n\");\n"
6893         | name, FBuffer ->
6894             pr "  printf (\"%%s%s: \", indent);\n" name;
6895             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6896             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6897             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6898             pr "    else\n";
6899             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6900             pr "  printf (\"\\n\");\n"
6901         | name, (FUInt64|FBytes) ->
6902             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6903               name typ name
6904         | name, FInt64 ->
6905             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6906               name typ name
6907         | name, FUInt32 ->
6908             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6909               name typ name
6910         | name, FInt32 ->
6911             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6912               name typ name
6913         | name, FChar ->
6914             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6915               name typ name
6916         | name, FOptPercent ->
6917             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6918               typ name name typ name;
6919             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6920       ) cols;
6921       pr "}\n";
6922       pr "\n";
6923   ) structs;
6924
6925   (* Emit a print_TYPE_list function definition only if that function is used. *)
6926   List.iter (
6927     function
6928     | typ, (RStructListOnly | RStructAndList) ->
6929         (* generate the function for typ *)
6930         emit_print_list_function typ
6931     | typ, _ -> () (* empty *)
6932   ) (rstructs_used_by all_functions);
6933
6934   (* Emit a print_TYPE function definition only if that function is used. *)
6935   List.iter (
6936     function
6937     | typ, (RStructOnly | RStructAndList) ->
6938         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6939         pr "{\n";
6940         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6941         pr "}\n";
6942         pr "\n";
6943     | typ, _ -> () (* empty *)
6944   ) (rstructs_used_by all_functions);
6945
6946   (* run_<action> actions *)
6947   List.iter (
6948     fun (name, style, _, flags, _, _, _) ->
6949       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6950       pr "{\n";
6951       (match fst style with
6952        | RErr
6953        | RInt _
6954        | RBool _ -> pr "  int r;\n"
6955        | RInt64 _ -> pr "  int64_t r;\n"
6956        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6957        | RString _ -> pr "  char *r;\n"
6958        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6959        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6960        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6961        | RBufferOut _ ->
6962            pr "  char *r;\n";
6963            pr "  size_t size;\n";
6964       );
6965       List.iter (
6966         function
6967         | Device n
6968         | String n
6969         | OptString n
6970         | FileIn n
6971         | FileOut n -> pr "  const char *%s;\n" n
6972         | Pathname n
6973         | Dev_or_Path n -> pr "  char *%s;\n" n
6974         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6975         | Bool n -> pr "  int %s;\n" n
6976         | Int n -> pr "  int %s;\n" n
6977         | Int64 n -> pr "  int64_t %s;\n" n
6978       ) (snd style);
6979
6980       (* Check and convert parameters. *)
6981       let argc_expected = List.length (snd style) in
6982       pr "  if (argc != %d) {\n" argc_expected;
6983       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6984         argc_expected;
6985       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6986       pr "    return -1;\n";
6987       pr "  }\n";
6988       iteri (
6989         fun i ->
6990           function
6991           | Device name
6992           | String name ->
6993               pr "  %s = argv[%d];\n" name i
6994           | Pathname name
6995           | Dev_or_Path name ->
6996               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6997               pr "  if (%s == NULL) return -1;\n" name
6998           | OptString name ->
6999               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7000                 name i i
7001           | FileIn name ->
7002               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7003                 name i i
7004           | FileOut name ->
7005               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7006                 name i i
7007           | StringList name | DeviceList name ->
7008               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7009               pr "  if (%s == NULL) return -1;\n" name;
7010           | Bool name ->
7011               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7012           | Int name ->
7013               pr "  %s = atoi (argv[%d]);\n" name i
7014           | Int64 name ->
7015               pr "  %s = atoll (argv[%d]);\n" name i
7016       ) (snd style);
7017
7018       (* Call C API function. *)
7019       let fn =
7020         try find_map (function FishAction n -> Some n | _ -> None) flags
7021         with Not_found -> sprintf "guestfs_%s" name in
7022       pr "  r = %s " fn;
7023       generate_c_call_args ~handle:"g" style;
7024       pr ";\n";
7025
7026       List.iter (
7027         function
7028         | Device name | String name
7029         | OptString name | FileIn name | FileOut name | Bool name
7030         | Int name | Int64 name -> ()
7031         | Pathname name | Dev_or_Path name ->
7032             pr "  free (%s);\n" name
7033         | StringList name | DeviceList name ->
7034             pr "  free_strings (%s);\n" name
7035       ) (snd style);
7036
7037       (* Check return value for errors and display command results. *)
7038       (match fst style with
7039        | RErr -> pr "  return r;\n"
7040        | RInt _ ->
7041            pr "  if (r == -1) return -1;\n";
7042            pr "  printf (\"%%d\\n\", r);\n";
7043            pr "  return 0;\n"
7044        | RInt64 _ ->
7045            pr "  if (r == -1) return -1;\n";
7046            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7047            pr "  return 0;\n"
7048        | RBool _ ->
7049            pr "  if (r == -1) return -1;\n";
7050            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7051            pr "  return 0;\n"
7052        | RConstString _ ->
7053            pr "  if (r == NULL) return -1;\n";
7054            pr "  printf (\"%%s\\n\", r);\n";
7055            pr "  return 0;\n"
7056        | RConstOptString _ ->
7057            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7058            pr "  return 0;\n"
7059        | RString _ ->
7060            pr "  if (r == NULL) return -1;\n";
7061            pr "  printf (\"%%s\\n\", r);\n";
7062            pr "  free (r);\n";
7063            pr "  return 0;\n"
7064        | RStringList _ ->
7065            pr "  if (r == NULL) return -1;\n";
7066            pr "  print_strings (r);\n";
7067            pr "  free_strings (r);\n";
7068            pr "  return 0;\n"
7069        | RStruct (_, typ) ->
7070            pr "  if (r == NULL) return -1;\n";
7071            pr "  print_%s (r);\n" typ;
7072            pr "  guestfs_free_%s (r);\n" typ;
7073            pr "  return 0;\n"
7074        | RStructList (_, typ) ->
7075            pr "  if (r == NULL) return -1;\n";
7076            pr "  print_%s_list (r);\n" typ;
7077            pr "  guestfs_free_%s_list (r);\n" typ;
7078            pr "  return 0;\n"
7079        | RHashtable _ ->
7080            pr "  if (r == NULL) return -1;\n";
7081            pr "  print_table (r);\n";
7082            pr "  free_strings (r);\n";
7083            pr "  return 0;\n"
7084        | RBufferOut _ ->
7085            pr "  if (r == NULL) return -1;\n";
7086            pr "  fwrite (r, size, 1, stdout);\n";
7087            pr "  free (r);\n";
7088            pr "  return 0;\n"
7089       );
7090       pr "}\n";
7091       pr "\n"
7092   ) all_functions;
7093
7094   (* run_action function *)
7095   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7096   pr "{\n";
7097   List.iter (
7098     fun (name, _, _, flags, _, _, _) ->
7099       let name2 = replace_char name '_' '-' in
7100       let alias =
7101         try find_map (function FishAlias n -> Some n | _ -> None) flags
7102         with Not_found -> name in
7103       pr "  if (";
7104       pr "STRCASEEQ (cmd, \"%s\")" name;
7105       if name <> name2 then
7106         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7107       if name <> alias then
7108         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7109       pr ")\n";
7110       pr "    return run_%s (cmd, argc, argv);\n" name;
7111       pr "  else\n";
7112   ) all_functions;
7113   pr "    {\n";
7114   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7115   pr "      return -1;\n";
7116   pr "    }\n";
7117   pr "  return 0;\n";
7118   pr "}\n";
7119   pr "\n"
7120
7121 (* Readline completion for guestfish. *)
7122 and generate_fish_completion () =
7123   generate_header CStyle GPLv2;
7124
7125   let all_functions =
7126     List.filter (
7127       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7128     ) all_functions in
7129
7130   pr "\
7131 #include <config.h>
7132
7133 #include <stdio.h>
7134 #include <stdlib.h>
7135 #include <string.h>
7136
7137 #ifdef HAVE_LIBREADLINE
7138 #include <readline/readline.h>
7139 #endif
7140
7141 #include \"fish.h\"
7142
7143 #ifdef HAVE_LIBREADLINE
7144
7145 static const char *const commands[] = {
7146   BUILTIN_COMMANDS_FOR_COMPLETION,
7147 ";
7148
7149   (* Get the commands, including the aliases.  They don't need to be
7150    * sorted - the generator() function just does a dumb linear search.
7151    *)
7152   let commands =
7153     List.map (
7154       fun (name, _, _, flags, _, _, _) ->
7155         let name2 = replace_char name '_' '-' in
7156         let alias =
7157           try find_map (function FishAlias n -> Some n | _ -> None) flags
7158           with Not_found -> name in
7159
7160         if name <> alias then [name2; alias] else [name2]
7161     ) all_functions in
7162   let commands = List.flatten commands in
7163
7164   List.iter (pr "  \"%s\",\n") commands;
7165
7166   pr "  NULL
7167 };
7168
7169 static char *
7170 generator (const char *text, int state)
7171 {
7172   static int index, len;
7173   const char *name;
7174
7175   if (!state) {
7176     index = 0;
7177     len = strlen (text);
7178   }
7179
7180   rl_attempted_completion_over = 1;
7181
7182   while ((name = commands[index]) != NULL) {
7183     index++;
7184     if (STRCASEEQLEN (name, text, len))
7185       return strdup (name);
7186   }
7187
7188   return NULL;
7189 }
7190
7191 #endif /* HAVE_LIBREADLINE */
7192
7193 char **do_completion (const char *text, int start, int end)
7194 {
7195   char **matches = NULL;
7196
7197 #ifdef HAVE_LIBREADLINE
7198   rl_completion_append_character = ' ';
7199
7200   if (start == 0)
7201     matches = rl_completion_matches (text, generator);
7202   else if (complete_dest_paths)
7203     matches = rl_completion_matches (text, complete_dest_paths_generator);
7204 #endif
7205
7206   return matches;
7207 }
7208 ";
7209
7210 (* Generate the POD documentation for guestfish. *)
7211 and generate_fish_actions_pod () =
7212   let all_functions_sorted =
7213     List.filter (
7214       fun (_, _, _, flags, _, _, _) ->
7215         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7216     ) all_functions_sorted in
7217
7218   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7219
7220   List.iter (
7221     fun (name, style, _, flags, _, _, longdesc) ->
7222       let longdesc =
7223         Str.global_substitute rex (
7224           fun s ->
7225             let sub =
7226               try Str.matched_group 1 s
7227               with Not_found ->
7228                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7229             "C<" ^ replace_char sub '_' '-' ^ ">"
7230         ) longdesc in
7231       let name = replace_char name '_' '-' in
7232       let alias =
7233         try find_map (function FishAlias n -> Some n | _ -> None) flags
7234         with Not_found -> name in
7235
7236       pr "=head2 %s" name;
7237       if name <> alias then
7238         pr " | %s" alias;
7239       pr "\n";
7240       pr "\n";
7241       pr " %s" name;
7242       List.iter (
7243         function
7244         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7245         | OptString n -> pr " %s" n
7246         | StringList n | DeviceList n -> pr " '%s ...'" n
7247         | Bool _ -> pr " true|false"
7248         | Int n -> pr " %s" n
7249         | Int64 n -> pr " %s" n
7250         | FileIn n | FileOut n -> pr " (%s|-)" n
7251       ) (snd style);
7252       pr "\n";
7253       pr "\n";
7254       pr "%s\n\n" longdesc;
7255
7256       if List.exists (function FileIn _ | FileOut _ -> true
7257                       | _ -> false) (snd style) then
7258         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7259
7260       if List.mem ProtocolLimitWarning flags then
7261         pr "%s\n\n" protocol_limit_warning;
7262
7263       if List.mem DangerWillRobinson flags then
7264         pr "%s\n\n" danger_will_robinson;
7265
7266       match deprecation_notice flags with
7267       | None -> ()
7268       | Some txt -> pr "%s\n\n" txt
7269   ) all_functions_sorted
7270
7271 (* Generate a C function prototype. *)
7272 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7273     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7274     ?(prefix = "")
7275     ?handle name style =
7276   if extern then pr "extern ";
7277   if static then pr "static ";
7278   (match fst style with
7279    | RErr -> pr "int "
7280    | RInt _ -> pr "int "
7281    | RInt64 _ -> pr "int64_t "
7282    | RBool _ -> pr "int "
7283    | RConstString _ | RConstOptString _ -> pr "const char *"
7284    | RString _ | RBufferOut _ -> pr "char *"
7285    | RStringList _ | RHashtable _ -> pr "char **"
7286    | RStruct (_, typ) ->
7287        if not in_daemon then pr "struct guestfs_%s *" typ
7288        else pr "guestfs_int_%s *" typ
7289    | RStructList (_, typ) ->
7290        if not in_daemon then pr "struct guestfs_%s_list *" typ
7291        else pr "guestfs_int_%s_list *" typ
7292   );
7293   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7294   pr "%s%s (" prefix name;
7295   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7296     pr "void"
7297   else (
7298     let comma = ref false in
7299     (match handle with
7300      | None -> ()
7301      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7302     );
7303     let next () =
7304       if !comma then (
7305         if single_line then pr ", " else pr ",\n\t\t"
7306       );
7307       comma := true
7308     in
7309     List.iter (
7310       function
7311       | Pathname n
7312       | Device n | Dev_or_Path n
7313       | String n
7314       | OptString n ->
7315           next ();
7316           pr "const char *%s" n
7317       | StringList n | DeviceList n ->
7318           next ();
7319           pr "char *const *%s" n
7320       | Bool n -> next (); pr "int %s" n
7321       | Int n -> next (); pr "int %s" n
7322       | Int64 n -> next (); pr "int64_t %s" n
7323       | FileIn n
7324       | FileOut n ->
7325           if not in_daemon then (next (); pr "const char *%s" n)
7326     ) (snd style);
7327     if is_RBufferOut then (next (); pr "size_t *size_r");
7328   );
7329   pr ")";
7330   if semicolon then pr ";";
7331   if newline then pr "\n"
7332
7333 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7334 and generate_c_call_args ?handle ?(decl = false) style =
7335   pr "(";
7336   let comma = ref false in
7337   let next () =
7338     if !comma then pr ", ";
7339     comma := true
7340   in
7341   (match handle with
7342    | None -> ()
7343    | Some handle -> pr "%s" handle; comma := true
7344   );
7345   List.iter (
7346     fun arg ->
7347       next ();
7348       pr "%s" (name_of_argt arg)
7349   ) (snd style);
7350   (* For RBufferOut calls, add implicit &size parameter. *)
7351   if not decl then (
7352     match fst style with
7353     | RBufferOut _ ->
7354         next ();
7355         pr "&size"
7356     | _ -> ()
7357   );
7358   pr ")"
7359
7360 (* Generate the OCaml bindings interface. *)
7361 and generate_ocaml_mli () =
7362   generate_header OCamlStyle LGPLv2;
7363
7364   pr "\
7365 (** For API documentation you should refer to the C API
7366     in the guestfs(3) manual page.  The OCaml API uses almost
7367     exactly the same calls. *)
7368
7369 type t
7370 (** A [guestfs_h] handle. *)
7371
7372 exception Error of string
7373 (** This exception is raised when there is an error. *)
7374
7375 exception Handle_closed of string
7376 (** This exception is raised if you use a {!Guestfs.t} handle
7377     after calling {!close} on it.  The string is the name of
7378     the function. *)
7379
7380 val create : unit -> t
7381 (** Create a {!Guestfs.t} handle. *)
7382
7383 val close : t -> unit
7384 (** Close the {!Guestfs.t} handle and free up all resources used
7385     by it immediately.
7386
7387     Handles are closed by the garbage collector when they become
7388     unreferenced, but callers can call this in order to provide
7389     predictable cleanup. *)
7390
7391 ";
7392   generate_ocaml_structure_decls ();
7393
7394   (* The actions. *)
7395   List.iter (
7396     fun (name, style, _, _, _, shortdesc, _) ->
7397       generate_ocaml_prototype name style;
7398       pr "(** %s *)\n" shortdesc;
7399       pr "\n"
7400   ) all_functions_sorted
7401
7402 (* Generate the OCaml bindings implementation. *)
7403 and generate_ocaml_ml () =
7404   generate_header OCamlStyle LGPLv2;
7405
7406   pr "\
7407 type t
7408
7409 exception Error of string
7410 exception Handle_closed of string
7411
7412 external create : unit -> t = \"ocaml_guestfs_create\"
7413 external close : t -> unit = \"ocaml_guestfs_close\"
7414
7415 (* Give the exceptions names, so they can be raised from the C code. *)
7416 let () =
7417   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7418   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7419
7420 ";
7421
7422   generate_ocaml_structure_decls ();
7423
7424   (* The actions. *)
7425   List.iter (
7426     fun (name, style, _, _, _, shortdesc, _) ->
7427       generate_ocaml_prototype ~is_external:true name style;
7428   ) all_functions_sorted
7429
7430 (* Generate the OCaml bindings C implementation. *)
7431 and generate_ocaml_c () =
7432   generate_header CStyle LGPLv2;
7433
7434   pr "\
7435 #include <stdio.h>
7436 #include <stdlib.h>
7437 #include <string.h>
7438
7439 #include <caml/config.h>
7440 #include <caml/alloc.h>
7441 #include <caml/callback.h>
7442 #include <caml/fail.h>
7443 #include <caml/memory.h>
7444 #include <caml/mlvalues.h>
7445 #include <caml/signals.h>
7446
7447 #include <guestfs.h>
7448
7449 #include \"guestfs_c.h\"
7450
7451 /* Copy a hashtable of string pairs into an assoc-list.  We return
7452  * the list in reverse order, but hashtables aren't supposed to be
7453  * ordered anyway.
7454  */
7455 static CAMLprim value
7456 copy_table (char * const * argv)
7457 {
7458   CAMLparam0 ();
7459   CAMLlocal5 (rv, pairv, kv, vv, cons);
7460   int i;
7461
7462   rv = Val_int (0);
7463   for (i = 0; argv[i] != NULL; i += 2) {
7464     kv = caml_copy_string (argv[i]);
7465     vv = caml_copy_string (argv[i+1]);
7466     pairv = caml_alloc (2, 0);
7467     Store_field (pairv, 0, kv);
7468     Store_field (pairv, 1, vv);
7469     cons = caml_alloc (2, 0);
7470     Store_field (cons, 1, rv);
7471     rv = cons;
7472     Store_field (cons, 0, pairv);
7473   }
7474
7475   CAMLreturn (rv);
7476 }
7477
7478 ";
7479
7480   (* Struct copy functions. *)
7481
7482   let emit_ocaml_copy_list_function typ =
7483     pr "static CAMLprim value\n";
7484     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7485     pr "{\n";
7486     pr "  CAMLparam0 ();\n";
7487     pr "  CAMLlocal2 (rv, v);\n";
7488     pr "  unsigned int i;\n";
7489     pr "\n";
7490     pr "  if (%ss->len == 0)\n" typ;
7491     pr "    CAMLreturn (Atom (0));\n";
7492     pr "  else {\n";
7493     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7494     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7495     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7496     pr "      caml_modify (&Field (rv, i), v);\n";
7497     pr "    }\n";
7498     pr "    CAMLreturn (rv);\n";
7499     pr "  }\n";
7500     pr "}\n";
7501     pr "\n";
7502   in
7503
7504   List.iter (
7505     fun (typ, cols) ->
7506       let has_optpercent_col =
7507         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7508
7509       pr "static CAMLprim value\n";
7510       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7511       pr "{\n";
7512       pr "  CAMLparam0 ();\n";
7513       if has_optpercent_col then
7514         pr "  CAMLlocal3 (rv, v, v2);\n"
7515       else
7516         pr "  CAMLlocal2 (rv, v);\n";
7517       pr "\n";
7518       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7519       iteri (
7520         fun i col ->
7521           (match col with
7522            | name, FString ->
7523                pr "  v = caml_copy_string (%s->%s);\n" typ name
7524            | name, FBuffer ->
7525                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7526                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7527                  typ name typ name
7528            | name, FUUID ->
7529                pr "  v = caml_alloc_string (32);\n";
7530                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7531            | name, (FBytes|FInt64|FUInt64) ->
7532                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7533            | name, (FInt32|FUInt32) ->
7534                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7535            | name, FOptPercent ->
7536                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7537                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7538                pr "    v = caml_alloc (1, 0);\n";
7539                pr "    Store_field (v, 0, v2);\n";
7540                pr "  } else /* None */\n";
7541                pr "    v = Val_int (0);\n";
7542            | name, FChar ->
7543                pr "  v = Val_int (%s->%s);\n" typ name
7544           );
7545           pr "  Store_field (rv, %d, v);\n" i
7546       ) cols;
7547       pr "  CAMLreturn (rv);\n";
7548       pr "}\n";
7549       pr "\n";
7550   ) structs;
7551
7552   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7553   List.iter (
7554     function
7555     | typ, (RStructListOnly | RStructAndList) ->
7556         (* generate the function for typ *)
7557         emit_ocaml_copy_list_function typ
7558     | typ, _ -> () (* empty *)
7559   ) (rstructs_used_by all_functions);
7560
7561   (* The wrappers. *)
7562   List.iter (
7563     fun (name, style, _, _, _, _, _) ->
7564       pr "/* Automatically generated wrapper for function\n";
7565       pr " * ";
7566       generate_ocaml_prototype name style;
7567       pr " */\n";
7568       pr "\n";
7569
7570       let params =
7571         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7572
7573       let needs_extra_vs =
7574         match fst style with RConstOptString _ -> true | _ -> false in
7575
7576       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7577       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7578       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7579       pr "\n";
7580
7581       pr "CAMLprim value\n";
7582       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7583       List.iter (pr ", value %s") (List.tl params);
7584       pr ")\n";
7585       pr "{\n";
7586
7587       (match params with
7588        | [p1; p2; p3; p4; p5] ->
7589            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7590        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7591            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7592            pr "  CAMLxparam%d (%s);\n"
7593              (List.length rest) (String.concat ", " rest)
7594        | ps ->
7595            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7596       );
7597       if not needs_extra_vs then
7598         pr "  CAMLlocal1 (rv);\n"
7599       else
7600         pr "  CAMLlocal3 (rv, v, v2);\n";
7601       pr "\n";
7602
7603       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7604       pr "  if (g == NULL)\n";
7605       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7606       pr "\n";
7607
7608       List.iter (
7609         function
7610         | Pathname n
7611         | Device n | Dev_or_Path n
7612         | String n
7613         | FileIn n
7614         | FileOut n ->
7615             pr "  const char *%s = String_val (%sv);\n" n n
7616         | OptString n ->
7617             pr "  const char *%s =\n" n;
7618             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7619               n n
7620         | StringList n | DeviceList n ->
7621             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7622         | Bool n ->
7623             pr "  int %s = Bool_val (%sv);\n" n n
7624         | Int n ->
7625             pr "  int %s = Int_val (%sv);\n" n n
7626         | Int64 n ->
7627             pr "  int64_t %s = Int64_val (%sv);\n" n n
7628       ) (snd style);
7629       let error_code =
7630         match fst style with
7631         | RErr -> pr "  int r;\n"; "-1"
7632         | RInt _ -> pr "  int r;\n"; "-1"
7633         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7634         | RBool _ -> pr "  int r;\n"; "-1"
7635         | RConstString _ | RConstOptString _ ->
7636             pr "  const char *r;\n"; "NULL"
7637         | RString _ -> pr "  char *r;\n"; "NULL"
7638         | RStringList _ ->
7639             pr "  int i;\n";
7640             pr "  char **r;\n";
7641             "NULL"
7642         | RStruct (_, typ) ->
7643             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7644         | RStructList (_, typ) ->
7645             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7646         | RHashtable _ ->
7647             pr "  int i;\n";
7648             pr "  char **r;\n";
7649             "NULL"
7650         | RBufferOut _ ->
7651             pr "  char *r;\n";
7652             pr "  size_t size;\n";
7653             "NULL" in
7654       pr "\n";
7655
7656       pr "  caml_enter_blocking_section ();\n";
7657       pr "  r = guestfs_%s " name;
7658       generate_c_call_args ~handle:"g" style;
7659       pr ";\n";
7660       pr "  caml_leave_blocking_section ();\n";
7661
7662       List.iter (
7663         function
7664         | StringList n | DeviceList n ->
7665             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7666         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7667         | Bool _ | Int _ | Int64 _
7668         | FileIn _ | FileOut _ -> ()
7669       ) (snd style);
7670
7671       pr "  if (r == %s)\n" error_code;
7672       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7673       pr "\n";
7674
7675       (match fst style with
7676        | RErr -> pr "  rv = Val_unit;\n"
7677        | RInt _ -> pr "  rv = Val_int (r);\n"
7678        | RInt64 _ ->
7679            pr "  rv = caml_copy_int64 (r);\n"
7680        | RBool _ -> pr "  rv = Val_bool (r);\n"
7681        | RConstString _ ->
7682            pr "  rv = caml_copy_string (r);\n"
7683        | RConstOptString _ ->
7684            pr "  if (r) { /* Some string */\n";
7685            pr "    v = caml_alloc (1, 0);\n";
7686            pr "    v2 = caml_copy_string (r);\n";
7687            pr "    Store_field (v, 0, v2);\n";
7688            pr "  } else /* None */\n";
7689            pr "    v = Val_int (0);\n";
7690        | RString _ ->
7691            pr "  rv = caml_copy_string (r);\n";
7692            pr "  free (r);\n"
7693        | RStringList _ ->
7694            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7695            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7696            pr "  free (r);\n"
7697        | RStruct (_, typ) ->
7698            pr "  rv = copy_%s (r);\n" typ;
7699            pr "  guestfs_free_%s (r);\n" typ;
7700        | RStructList (_, typ) ->
7701            pr "  rv = copy_%s_list (r);\n" typ;
7702            pr "  guestfs_free_%s_list (r);\n" typ;
7703        | RHashtable _ ->
7704            pr "  rv = copy_table (r);\n";
7705            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7706            pr "  free (r);\n";
7707        | RBufferOut _ ->
7708            pr "  rv = caml_alloc_string (size);\n";
7709            pr "  memcpy (String_val (rv), r, size);\n";
7710       );
7711
7712       pr "  CAMLreturn (rv);\n";
7713       pr "}\n";
7714       pr "\n";
7715
7716       if List.length params > 5 then (
7717         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7718         pr "CAMLprim value ";
7719         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7720         pr "CAMLprim value\n";
7721         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7722         pr "{\n";
7723         pr "  return ocaml_guestfs_%s (argv[0]" name;
7724         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7725         pr ");\n";
7726         pr "}\n";
7727         pr "\n"
7728       )
7729   ) all_functions_sorted
7730
7731 and generate_ocaml_structure_decls () =
7732   List.iter (
7733     fun (typ, cols) ->
7734       pr "type %s = {\n" typ;
7735       List.iter (
7736         function
7737         | name, FString -> pr "  %s : string;\n" name
7738         | name, FBuffer -> pr "  %s : string;\n" name
7739         | name, FUUID -> pr "  %s : string;\n" name
7740         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7741         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7742         | name, FChar -> pr "  %s : char;\n" name
7743         | name, FOptPercent -> pr "  %s : float option;\n" name
7744       ) cols;
7745       pr "}\n";
7746       pr "\n"
7747   ) structs
7748
7749 and generate_ocaml_prototype ?(is_external = false) name style =
7750   if is_external then pr "external " else pr "val ";
7751   pr "%s : t -> " name;
7752   List.iter (
7753     function
7754     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7755     | OptString _ -> pr "string option -> "
7756     | StringList _ | DeviceList _ -> pr "string array -> "
7757     | Bool _ -> pr "bool -> "
7758     | Int _ -> pr "int -> "
7759     | Int64 _ -> pr "int64 -> "
7760   ) (snd style);
7761   (match fst style with
7762    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7763    | RInt _ -> pr "int"
7764    | RInt64 _ -> pr "int64"
7765    | RBool _ -> pr "bool"
7766    | RConstString _ -> pr "string"
7767    | RConstOptString _ -> pr "string option"
7768    | RString _ | RBufferOut _ -> pr "string"
7769    | RStringList _ -> pr "string array"
7770    | RStruct (_, typ) -> pr "%s" typ
7771    | RStructList (_, typ) -> pr "%s array" typ
7772    | RHashtable _ -> pr "(string * string) list"
7773   );
7774   if is_external then (
7775     pr " = ";
7776     if List.length (snd style) + 1 > 5 then
7777       pr "\"ocaml_guestfs_%s_byte\" " name;
7778     pr "\"ocaml_guestfs_%s\"" name
7779   );
7780   pr "\n"
7781
7782 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7783 and generate_perl_xs () =
7784   generate_header CStyle LGPLv2;
7785
7786   pr "\
7787 #include \"EXTERN.h\"
7788 #include \"perl.h\"
7789 #include \"XSUB.h\"
7790
7791 #include <guestfs.h>
7792
7793 #ifndef PRId64
7794 #define PRId64 \"lld\"
7795 #endif
7796
7797 static SV *
7798 my_newSVll(long long val) {
7799 #ifdef USE_64_BIT_ALL
7800   return newSViv(val);
7801 #else
7802   char buf[100];
7803   int len;
7804   len = snprintf(buf, 100, \"%%\" PRId64, val);
7805   return newSVpv(buf, len);
7806 #endif
7807 }
7808
7809 #ifndef PRIu64
7810 #define PRIu64 \"llu\"
7811 #endif
7812
7813 static SV *
7814 my_newSVull(unsigned long long val) {
7815 #ifdef USE_64_BIT_ALL
7816   return newSVuv(val);
7817 #else
7818   char buf[100];
7819   int len;
7820   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7821   return newSVpv(buf, len);
7822 #endif
7823 }
7824
7825 /* http://www.perlmonks.org/?node_id=680842 */
7826 static char **
7827 XS_unpack_charPtrPtr (SV *arg) {
7828   char **ret;
7829   AV *av;
7830   I32 i;
7831
7832   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7833     croak (\"array reference expected\");
7834
7835   av = (AV *)SvRV (arg);
7836   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7837   if (!ret)
7838     croak (\"malloc failed\");
7839
7840   for (i = 0; i <= av_len (av); i++) {
7841     SV **elem = av_fetch (av, i, 0);
7842
7843     if (!elem || !*elem)
7844       croak (\"missing element in list\");
7845
7846     ret[i] = SvPV_nolen (*elem);
7847   }
7848
7849   ret[i] = NULL;
7850
7851   return ret;
7852 }
7853
7854 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7855
7856 PROTOTYPES: ENABLE
7857
7858 guestfs_h *
7859 _create ()
7860    CODE:
7861       RETVAL = guestfs_create ();
7862       if (!RETVAL)
7863         croak (\"could not create guestfs handle\");
7864       guestfs_set_error_handler (RETVAL, NULL, NULL);
7865  OUTPUT:
7866       RETVAL
7867
7868 void
7869 DESTROY (g)
7870       guestfs_h *g;
7871  PPCODE:
7872       guestfs_close (g);
7873
7874 ";
7875
7876   List.iter (
7877     fun (name, style, _, _, _, _, _) ->
7878       (match fst style with
7879        | RErr -> pr "void\n"
7880        | RInt _ -> pr "SV *\n"
7881        | RInt64 _ -> pr "SV *\n"
7882        | RBool _ -> pr "SV *\n"
7883        | RConstString _ -> pr "SV *\n"
7884        | RConstOptString _ -> pr "SV *\n"
7885        | RString _ -> pr "SV *\n"
7886        | RBufferOut _ -> pr "SV *\n"
7887        | RStringList _
7888        | RStruct _ | RStructList _
7889        | RHashtable _ ->
7890            pr "void\n" (* all lists returned implictly on the stack *)
7891       );
7892       (* Call and arguments. *)
7893       pr "%s " name;
7894       generate_c_call_args ~handle:"g" ~decl:true style;
7895       pr "\n";
7896       pr "      guestfs_h *g;\n";
7897       iteri (
7898         fun i ->
7899           function
7900           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7901               pr "      char *%s;\n" n
7902           | OptString n ->
7903               (* http://www.perlmonks.org/?node_id=554277
7904                * Note that the implicit handle argument means we have
7905                * to add 1 to the ST(x) operator.
7906                *)
7907               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7908           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7909           | Bool n -> pr "      int %s;\n" n
7910           | Int n -> pr "      int %s;\n" n
7911           | Int64 n -> pr "      int64_t %s;\n" n
7912       ) (snd style);
7913
7914       let do_cleanups () =
7915         List.iter (
7916           function
7917           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7918           | Bool _ | Int _ | Int64 _
7919           | FileIn _ | FileOut _ -> ()
7920           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7921         ) (snd style)
7922       in
7923
7924       (* Code. *)
7925       (match fst style with
7926        | RErr ->
7927            pr "PREINIT:\n";
7928            pr "      int r;\n";
7929            pr " PPCODE:\n";
7930            pr "      r = guestfs_%s " name;
7931            generate_c_call_args ~handle:"g" style;
7932            pr ";\n";
7933            do_cleanups ();
7934            pr "      if (r == -1)\n";
7935            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7936        | RInt n
7937        | RBool n ->
7938            pr "PREINIT:\n";
7939            pr "      int %s;\n" n;
7940            pr "   CODE:\n";
7941            pr "      %s = guestfs_%s " n name;
7942            generate_c_call_args ~handle:"g" style;
7943            pr ";\n";
7944            do_cleanups ();
7945            pr "      if (%s == -1)\n" n;
7946            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7947            pr "      RETVAL = newSViv (%s);\n" n;
7948            pr " OUTPUT:\n";
7949            pr "      RETVAL\n"
7950        | RInt64 n ->
7951            pr "PREINIT:\n";
7952            pr "      int64_t %s;\n" n;
7953            pr "   CODE:\n";
7954            pr "      %s = guestfs_%s " n name;
7955            generate_c_call_args ~handle:"g" style;
7956            pr ";\n";
7957            do_cleanups ();
7958            pr "      if (%s == -1)\n" n;
7959            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7960            pr "      RETVAL = my_newSVll (%s);\n" n;
7961            pr " OUTPUT:\n";
7962            pr "      RETVAL\n"
7963        | RConstString n ->
7964            pr "PREINIT:\n";
7965            pr "      const char *%s;\n" n;
7966            pr "   CODE:\n";
7967            pr "      %s = guestfs_%s " n name;
7968            generate_c_call_args ~handle:"g" style;
7969            pr ";\n";
7970            do_cleanups ();
7971            pr "      if (%s == NULL)\n" n;
7972            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7973            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7974            pr " OUTPUT:\n";
7975            pr "      RETVAL\n"
7976        | RConstOptString n ->
7977            pr "PREINIT:\n";
7978            pr "      const char *%s;\n" n;
7979            pr "   CODE:\n";
7980            pr "      %s = guestfs_%s " n name;
7981            generate_c_call_args ~handle:"g" style;
7982            pr ";\n";
7983            do_cleanups ();
7984            pr "      if (%s == NULL)\n" n;
7985            pr "        RETVAL = &PL_sv_undef;\n";
7986            pr "      else\n";
7987            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7988            pr " OUTPUT:\n";
7989            pr "      RETVAL\n"
7990        | RString n ->
7991            pr "PREINIT:\n";
7992            pr "      char *%s;\n" n;
7993            pr "   CODE:\n";
7994            pr "      %s = guestfs_%s " n name;
7995            generate_c_call_args ~handle:"g" style;
7996            pr ";\n";
7997            do_cleanups ();
7998            pr "      if (%s == NULL)\n" n;
7999            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8000            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8001            pr "      free (%s);\n" n;
8002            pr " OUTPUT:\n";
8003            pr "      RETVAL\n"
8004        | RStringList n | RHashtable n ->
8005            pr "PREINIT:\n";
8006            pr "      char **%s;\n" n;
8007            pr "      int i, n;\n";
8008            pr " PPCODE:\n";
8009            pr "      %s = guestfs_%s " n name;
8010            generate_c_call_args ~handle:"g" style;
8011            pr ";\n";
8012            do_cleanups ();
8013            pr "      if (%s == NULL)\n" n;
8014            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8015            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8016            pr "      EXTEND (SP, n);\n";
8017            pr "      for (i = 0; i < n; ++i) {\n";
8018            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8019            pr "        free (%s[i]);\n" n;
8020            pr "      }\n";
8021            pr "      free (%s);\n" n;
8022        | RStruct (n, typ) ->
8023            let cols = cols_of_struct typ in
8024            generate_perl_struct_code typ cols name style n do_cleanups
8025        | RStructList (n, typ) ->
8026            let cols = cols_of_struct typ in
8027            generate_perl_struct_list_code typ cols name style n do_cleanups
8028        | RBufferOut n ->
8029            pr "PREINIT:\n";
8030            pr "      char *%s;\n" n;
8031            pr "      size_t size;\n";
8032            pr "   CODE:\n";
8033            pr "      %s = guestfs_%s " n name;
8034            generate_c_call_args ~handle:"g" style;
8035            pr ";\n";
8036            do_cleanups ();
8037            pr "      if (%s == NULL)\n" n;
8038            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8039            pr "      RETVAL = newSVpv (%s, size);\n" n;
8040            pr "      free (%s);\n" n;
8041            pr " OUTPUT:\n";
8042            pr "      RETVAL\n"
8043       );
8044
8045       pr "\n"
8046   ) all_functions
8047
8048 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8049   pr "PREINIT:\n";
8050   pr "      struct guestfs_%s_list *%s;\n" typ n;
8051   pr "      int i;\n";
8052   pr "      HV *hv;\n";
8053   pr " PPCODE:\n";
8054   pr "      %s = guestfs_%s " n name;
8055   generate_c_call_args ~handle:"g" style;
8056   pr ";\n";
8057   do_cleanups ();
8058   pr "      if (%s == NULL)\n" n;
8059   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8060   pr "      EXTEND (SP, %s->len);\n" n;
8061   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8062   pr "        hv = newHV ();\n";
8063   List.iter (
8064     function
8065     | name, FString ->
8066         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8067           name (String.length name) n name
8068     | name, FUUID ->
8069         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8070           name (String.length name) n name
8071     | name, FBuffer ->
8072         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8073           name (String.length name) n name n name
8074     | name, (FBytes|FUInt64) ->
8075         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8076           name (String.length name) n name
8077     | name, FInt64 ->
8078         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8079           name (String.length name) n name
8080     | name, (FInt32|FUInt32) ->
8081         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8082           name (String.length name) n name
8083     | name, FChar ->
8084         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8085           name (String.length name) n name
8086     | name, FOptPercent ->
8087         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8088           name (String.length name) n name
8089   ) cols;
8090   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8091   pr "      }\n";
8092   pr "      guestfs_free_%s_list (%s);\n" typ n
8093
8094 and generate_perl_struct_code typ cols name style n do_cleanups =
8095   pr "PREINIT:\n";
8096   pr "      struct guestfs_%s *%s;\n" typ n;
8097   pr " PPCODE:\n";
8098   pr "      %s = guestfs_%s " n name;
8099   generate_c_call_args ~handle:"g" style;
8100   pr ";\n";
8101   do_cleanups ();
8102   pr "      if (%s == NULL)\n" n;
8103   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8104   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8105   List.iter (
8106     fun ((name, _) as col) ->
8107       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8108
8109       match col with
8110       | name, FString ->
8111           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8112             n name
8113       | name, FBuffer ->
8114           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8115             n name n name
8116       | name, FUUID ->
8117           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8118             n name
8119       | name, (FBytes|FUInt64) ->
8120           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8121             n name
8122       | name, FInt64 ->
8123           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8124             n name
8125       | name, (FInt32|FUInt32) ->
8126           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8127             n name
8128       | name, FChar ->
8129           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8130             n name
8131       | name, FOptPercent ->
8132           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8133             n name
8134   ) cols;
8135   pr "      free (%s);\n" n
8136
8137 (* Generate Sys/Guestfs.pm. *)
8138 and generate_perl_pm () =
8139   generate_header HashStyle LGPLv2;
8140
8141   pr "\
8142 =pod
8143
8144 =head1 NAME
8145
8146 Sys::Guestfs - Perl bindings for libguestfs
8147
8148 =head1 SYNOPSIS
8149
8150  use Sys::Guestfs;
8151
8152  my $h = Sys::Guestfs->new ();
8153  $h->add_drive ('guest.img');
8154  $h->launch ();
8155  $h->mount ('/dev/sda1', '/');
8156  $h->touch ('/hello');
8157  $h->sync ();
8158
8159 =head1 DESCRIPTION
8160
8161 The C<Sys::Guestfs> module provides a Perl XS binding to the
8162 libguestfs API for examining and modifying virtual machine
8163 disk images.
8164
8165 Amongst the things this is good for: making batch configuration
8166 changes to guests, getting disk used/free statistics (see also:
8167 virt-df), migrating between virtualization systems (see also:
8168 virt-p2v), performing partial backups, performing partial guest
8169 clones, cloning guests and changing registry/UUID/hostname info, and
8170 much else besides.
8171
8172 Libguestfs uses Linux kernel and qemu code, and can access any type of
8173 guest filesystem that Linux and qemu can, including but not limited
8174 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8175 schemes, qcow, qcow2, vmdk.
8176
8177 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8178 LVs, what filesystem is in each LV, etc.).  It can also run commands
8179 in the context of the guest.  Also you can access filesystems over FTP.
8180
8181 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8182 functions for using libguestfs from Perl, including integration
8183 with libvirt.
8184
8185 =head1 ERRORS
8186
8187 All errors turn into calls to C<croak> (see L<Carp(3)>).
8188
8189 =head1 METHODS
8190
8191 =over 4
8192
8193 =cut
8194
8195 package Sys::Guestfs;
8196
8197 use strict;
8198 use warnings;
8199
8200 require XSLoader;
8201 XSLoader::load ('Sys::Guestfs');
8202
8203 =item $h = Sys::Guestfs->new ();
8204
8205 Create a new guestfs handle.
8206
8207 =cut
8208
8209 sub new {
8210   my $proto = shift;
8211   my $class = ref ($proto) || $proto;
8212
8213   my $self = Sys::Guestfs::_create ();
8214   bless $self, $class;
8215   return $self;
8216 }
8217
8218 ";
8219
8220   (* Actions.  We only need to print documentation for these as
8221    * they are pulled in from the XS code automatically.
8222    *)
8223   List.iter (
8224     fun (name, style, _, flags, _, _, longdesc) ->
8225       if not (List.mem NotInDocs flags) then (
8226         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8227         pr "=item ";
8228         generate_perl_prototype name style;
8229         pr "\n\n";
8230         pr "%s\n\n" longdesc;
8231         if List.mem ProtocolLimitWarning flags then
8232           pr "%s\n\n" protocol_limit_warning;
8233         if List.mem DangerWillRobinson flags then
8234           pr "%s\n\n" danger_will_robinson;
8235         match deprecation_notice flags with
8236         | None -> ()
8237         | Some txt -> pr "%s\n\n" txt
8238       )
8239   ) all_functions_sorted;
8240
8241   (* End of file. *)
8242   pr "\
8243 =cut
8244
8245 1;
8246
8247 =back
8248
8249 =head1 COPYRIGHT
8250
8251 Copyright (C) 2009 Red Hat Inc.
8252
8253 =head1 LICENSE
8254
8255 Please see the file COPYING.LIB for the full license.
8256
8257 =head1 SEE ALSO
8258
8259 L<guestfs(3)>,
8260 L<guestfish(1)>,
8261 L<http://libguestfs.org>,
8262 L<Sys::Guestfs::Lib(3)>.
8263
8264 =cut
8265 "
8266
8267 and generate_perl_prototype name style =
8268   (match fst style with
8269    | RErr -> ()
8270    | RBool n
8271    | RInt n
8272    | RInt64 n
8273    | RConstString n
8274    | RConstOptString n
8275    | RString n
8276    | RBufferOut n -> pr "$%s = " n
8277    | RStruct (n,_)
8278    | RHashtable n -> pr "%%%s = " n
8279    | RStringList n
8280    | RStructList (n,_) -> pr "@%s = " n
8281   );
8282   pr "$h->%s (" name;
8283   let comma = ref false in
8284   List.iter (
8285     fun arg ->
8286       if !comma then pr ", ";
8287       comma := true;
8288       match arg with
8289       | Pathname n | Device n | Dev_or_Path n | String n
8290       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8291           pr "$%s" n
8292       | StringList n | DeviceList n ->
8293           pr "\\@%s" n
8294   ) (snd style);
8295   pr ");"
8296
8297 (* Generate Python C module. *)
8298 and generate_python_c () =
8299   generate_header CStyle LGPLv2;
8300
8301   pr "\
8302 #include <Python.h>
8303
8304 #include <stdio.h>
8305 #include <stdlib.h>
8306 #include <assert.h>
8307
8308 #include \"guestfs.h\"
8309
8310 typedef struct {
8311   PyObject_HEAD
8312   guestfs_h *g;
8313 } Pyguestfs_Object;
8314
8315 static guestfs_h *
8316 get_handle (PyObject *obj)
8317 {
8318   assert (obj);
8319   assert (obj != Py_None);
8320   return ((Pyguestfs_Object *) obj)->g;
8321 }
8322
8323 static PyObject *
8324 put_handle (guestfs_h *g)
8325 {
8326   assert (g);
8327   return
8328     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8329 }
8330
8331 /* This list should be freed (but not the strings) after use. */
8332 static char **
8333 get_string_list (PyObject *obj)
8334 {
8335   int i, len;
8336   char **r;
8337
8338   assert (obj);
8339
8340   if (!PyList_Check (obj)) {
8341     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8342     return NULL;
8343   }
8344
8345   len = PyList_Size (obj);
8346   r = malloc (sizeof (char *) * (len+1));
8347   if (r == NULL) {
8348     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8349     return NULL;
8350   }
8351
8352   for (i = 0; i < len; ++i)
8353     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8354   r[len] = NULL;
8355
8356   return r;
8357 }
8358
8359 static PyObject *
8360 put_string_list (char * const * const argv)
8361 {
8362   PyObject *list;
8363   int argc, i;
8364
8365   for (argc = 0; argv[argc] != NULL; ++argc)
8366     ;
8367
8368   list = PyList_New (argc);
8369   for (i = 0; i < argc; ++i)
8370     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8371
8372   return list;
8373 }
8374
8375 static PyObject *
8376 put_table (char * const * const argv)
8377 {
8378   PyObject *list, *item;
8379   int argc, i;
8380
8381   for (argc = 0; argv[argc] != NULL; ++argc)
8382     ;
8383
8384   list = PyList_New (argc >> 1);
8385   for (i = 0; i < argc; i += 2) {
8386     item = PyTuple_New (2);
8387     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8388     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8389     PyList_SetItem (list, i >> 1, item);
8390   }
8391
8392   return list;
8393 }
8394
8395 static void
8396 free_strings (char **argv)
8397 {
8398   int argc;
8399
8400   for (argc = 0; argv[argc] != NULL; ++argc)
8401     free (argv[argc]);
8402   free (argv);
8403 }
8404
8405 static PyObject *
8406 py_guestfs_create (PyObject *self, PyObject *args)
8407 {
8408   guestfs_h *g;
8409
8410   g = guestfs_create ();
8411   if (g == NULL) {
8412     PyErr_SetString (PyExc_RuntimeError,
8413                      \"guestfs.create: failed to allocate handle\");
8414     return NULL;
8415   }
8416   guestfs_set_error_handler (g, NULL, NULL);
8417   return put_handle (g);
8418 }
8419
8420 static PyObject *
8421 py_guestfs_close (PyObject *self, PyObject *args)
8422 {
8423   PyObject *py_g;
8424   guestfs_h *g;
8425
8426   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8427     return NULL;
8428   g = get_handle (py_g);
8429
8430   guestfs_close (g);
8431
8432   Py_INCREF (Py_None);
8433   return Py_None;
8434 }
8435
8436 ";
8437
8438   let emit_put_list_function typ =
8439     pr "static PyObject *\n";
8440     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8441     pr "{\n";
8442     pr "  PyObject *list;\n";
8443     pr "  int i;\n";
8444     pr "\n";
8445     pr "  list = PyList_New (%ss->len);\n" typ;
8446     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8447     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8448     pr "  return list;\n";
8449     pr "};\n";
8450     pr "\n"
8451   in
8452
8453   (* Structures, turned into Python dictionaries. *)
8454   List.iter (
8455     fun (typ, cols) ->
8456       pr "static PyObject *\n";
8457       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8458       pr "{\n";
8459       pr "  PyObject *dict;\n";
8460       pr "\n";
8461       pr "  dict = PyDict_New ();\n";
8462       List.iter (
8463         function
8464         | name, FString ->
8465             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8466             pr "                        PyString_FromString (%s->%s));\n"
8467               typ name
8468         | name, FBuffer ->
8469             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8470             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8471               typ name typ name
8472         | name, FUUID ->
8473             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8474             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8475               typ name
8476         | name, (FBytes|FUInt64) ->
8477             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8478             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8479               typ name
8480         | name, FInt64 ->
8481             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8482             pr "                        PyLong_FromLongLong (%s->%s));\n"
8483               typ name
8484         | name, FUInt32 ->
8485             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8486             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8487               typ name
8488         | name, FInt32 ->
8489             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8490             pr "                        PyLong_FromLong (%s->%s));\n"
8491               typ name
8492         | name, FOptPercent ->
8493             pr "  if (%s->%s >= 0)\n" typ name;
8494             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8495             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8496               typ name;
8497             pr "  else {\n";
8498             pr "    Py_INCREF (Py_None);\n";
8499             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8500             pr "  }\n"
8501         | name, FChar ->
8502             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8503             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8504       ) cols;
8505       pr "  return dict;\n";
8506       pr "};\n";
8507       pr "\n";
8508
8509   ) structs;
8510
8511   (* Emit a put_TYPE_list function definition only if that function is used. *)
8512   List.iter (
8513     function
8514     | typ, (RStructListOnly | RStructAndList) ->
8515         (* generate the function for typ *)
8516         emit_put_list_function typ
8517     | typ, _ -> () (* empty *)
8518   ) (rstructs_used_by all_functions);
8519
8520   (* Python wrapper functions. *)
8521   List.iter (
8522     fun (name, style, _, _, _, _, _) ->
8523       pr "static PyObject *\n";
8524       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8525       pr "{\n";
8526
8527       pr "  PyObject *py_g;\n";
8528       pr "  guestfs_h *g;\n";
8529       pr "  PyObject *py_r;\n";
8530
8531       let error_code =
8532         match fst style with
8533         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8534         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8535         | RConstString _ | RConstOptString _ ->
8536             pr "  const char *r;\n"; "NULL"
8537         | RString _ -> pr "  char *r;\n"; "NULL"
8538         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8539         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8540         | RStructList (_, typ) ->
8541             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8542         | RBufferOut _ ->
8543             pr "  char *r;\n";
8544             pr "  size_t size;\n";
8545             "NULL" in
8546
8547       List.iter (
8548         function
8549         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8550             pr "  const char *%s;\n" n
8551         | OptString n -> pr "  const char *%s;\n" n
8552         | StringList n | DeviceList n ->
8553             pr "  PyObject *py_%s;\n" n;
8554             pr "  char **%s;\n" n
8555         | Bool n -> pr "  int %s;\n" n
8556         | Int n -> pr "  int %s;\n" n
8557         | Int64 n -> pr "  long long %s;\n" n
8558       ) (snd style);
8559
8560       pr "\n";
8561
8562       (* Convert the parameters. *)
8563       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8564       List.iter (
8565         function
8566         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8567         | OptString _ -> pr "z"
8568         | StringList _ | DeviceList _ -> pr "O"
8569         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8570         | Int _ -> pr "i"
8571         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8572                              * emulate C's int/long/long long in Python?
8573                              *)
8574       ) (snd style);
8575       pr ":guestfs_%s\",\n" name;
8576       pr "                         &py_g";
8577       List.iter (
8578         function
8579         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8580         | OptString n -> pr ", &%s" n
8581         | StringList n | DeviceList n -> pr ", &py_%s" n
8582         | Bool n -> pr ", &%s" n
8583         | Int n -> pr ", &%s" n
8584         | Int64 n -> pr ", &%s" n
8585       ) (snd style);
8586
8587       pr "))\n";
8588       pr "    return NULL;\n";
8589
8590       pr "  g = get_handle (py_g);\n";
8591       List.iter (
8592         function
8593         | Pathname _ | Device _ | Dev_or_Path _ | String _
8594         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8595         | StringList n | DeviceList n ->
8596             pr "  %s = get_string_list (py_%s);\n" n n;
8597             pr "  if (!%s) return NULL;\n" n
8598       ) (snd style);
8599
8600       pr "\n";
8601
8602       pr "  r = guestfs_%s " name;
8603       generate_c_call_args ~handle:"g" style;
8604       pr ";\n";
8605
8606       List.iter (
8607         function
8608         | Pathname _ | Device _ | Dev_or_Path _ | String _
8609         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8610         | StringList n | DeviceList n ->
8611             pr "  free (%s);\n" n
8612       ) (snd style);
8613
8614       pr "  if (r == %s) {\n" error_code;
8615       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8616       pr "    return NULL;\n";
8617       pr "  }\n";
8618       pr "\n";
8619
8620       (match fst style with
8621        | RErr ->
8622            pr "  Py_INCREF (Py_None);\n";
8623            pr "  py_r = Py_None;\n"
8624        | RInt _
8625        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8626        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8627        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8628        | RConstOptString _ ->
8629            pr "  if (r)\n";
8630            pr "    py_r = PyString_FromString (r);\n";
8631            pr "  else {\n";
8632            pr "    Py_INCREF (Py_None);\n";
8633            pr "    py_r = Py_None;\n";
8634            pr "  }\n"
8635        | RString _ ->
8636            pr "  py_r = PyString_FromString (r);\n";
8637            pr "  free (r);\n"
8638        | RStringList _ ->
8639            pr "  py_r = put_string_list (r);\n";
8640            pr "  free_strings (r);\n"
8641        | RStruct (_, typ) ->
8642            pr "  py_r = put_%s (r);\n" typ;
8643            pr "  guestfs_free_%s (r);\n" typ
8644        | RStructList (_, typ) ->
8645            pr "  py_r = put_%s_list (r);\n" typ;
8646            pr "  guestfs_free_%s_list (r);\n" typ
8647        | RHashtable n ->
8648            pr "  py_r = put_table (r);\n";
8649            pr "  free_strings (r);\n"
8650        | RBufferOut _ ->
8651            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8652            pr "  free (r);\n"
8653       );
8654
8655       pr "  return py_r;\n";
8656       pr "}\n";
8657       pr "\n"
8658   ) all_functions;
8659
8660   (* Table of functions. *)
8661   pr "static PyMethodDef methods[] = {\n";
8662   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8663   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8664   List.iter (
8665     fun (name, _, _, _, _, _, _) ->
8666       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8667         name name
8668   ) all_functions;
8669   pr "  { NULL, NULL, 0, NULL }\n";
8670   pr "};\n";
8671   pr "\n";
8672
8673   (* Init function. *)
8674   pr "\
8675 void
8676 initlibguestfsmod (void)
8677 {
8678   static int initialized = 0;
8679
8680   if (initialized) return;
8681   Py_InitModule ((char *) \"libguestfsmod\", methods);
8682   initialized = 1;
8683 }
8684 "
8685
8686 (* Generate Python module. *)
8687 and generate_python_py () =
8688   generate_header HashStyle LGPLv2;
8689
8690   pr "\
8691 u\"\"\"Python bindings for libguestfs
8692
8693 import guestfs
8694 g = guestfs.GuestFS ()
8695 g.add_drive (\"guest.img\")
8696 g.launch ()
8697 parts = g.list_partitions ()
8698
8699 The guestfs module provides a Python binding to the libguestfs API
8700 for examining and modifying virtual machine disk images.
8701
8702 Amongst the things this is good for: making batch configuration
8703 changes to guests, getting disk used/free statistics (see also:
8704 virt-df), migrating between virtualization systems (see also:
8705 virt-p2v), performing partial backups, performing partial guest
8706 clones, cloning guests and changing registry/UUID/hostname info, and
8707 much else besides.
8708
8709 Libguestfs uses Linux kernel and qemu code, and can access any type of
8710 guest filesystem that Linux and qemu can, including but not limited
8711 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8712 schemes, qcow, qcow2, vmdk.
8713
8714 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8715 LVs, what filesystem is in each LV, etc.).  It can also run commands
8716 in the context of the guest.  Also you can access filesystems over FTP.
8717
8718 Errors which happen while using the API are turned into Python
8719 RuntimeError exceptions.
8720
8721 To create a guestfs handle you usually have to perform the following
8722 sequence of calls:
8723
8724 # Create the handle, call add_drive at least once, and possibly
8725 # several times if the guest has multiple block devices:
8726 g = guestfs.GuestFS ()
8727 g.add_drive (\"guest.img\")
8728
8729 # Launch the qemu subprocess and wait for it to become ready:
8730 g.launch ()
8731
8732 # Now you can issue commands, for example:
8733 logvols = g.lvs ()
8734
8735 \"\"\"
8736
8737 import libguestfsmod
8738
8739 class GuestFS:
8740     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8741
8742     def __init__ (self):
8743         \"\"\"Create a new libguestfs handle.\"\"\"
8744         self._o = libguestfsmod.create ()
8745
8746     def __del__ (self):
8747         libguestfsmod.close (self._o)
8748
8749 ";
8750
8751   List.iter (
8752     fun (name, style, _, flags, _, _, longdesc) ->
8753       pr "    def %s " name;
8754       generate_py_call_args ~handle:"self" (snd style);
8755       pr ":\n";
8756
8757       if not (List.mem NotInDocs flags) then (
8758         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8759         let doc =
8760           match fst style with
8761           | RErr | RInt _ | RInt64 _ | RBool _
8762           | RConstOptString _ | RConstString _
8763           | RString _ | RBufferOut _ -> doc
8764           | RStringList _ ->
8765               doc ^ "\n\nThis function returns a list of strings."
8766           | RStruct (_, typ) ->
8767               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8768           | RStructList (_, typ) ->
8769               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8770           | RHashtable _ ->
8771               doc ^ "\n\nThis function returns a dictionary." in
8772         let doc =
8773           if List.mem ProtocolLimitWarning flags then
8774             doc ^ "\n\n" ^ protocol_limit_warning
8775           else doc in
8776         let doc =
8777           if List.mem DangerWillRobinson flags then
8778             doc ^ "\n\n" ^ danger_will_robinson
8779           else doc in
8780         let doc =
8781           match deprecation_notice flags with
8782           | None -> doc
8783           | Some txt -> doc ^ "\n\n" ^ txt in
8784         let doc = pod2text ~width:60 name doc in
8785         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8786         let doc = String.concat "\n        " doc in
8787         pr "        u\"\"\"%s\"\"\"\n" doc;
8788       );
8789       pr "        return libguestfsmod.%s " name;
8790       generate_py_call_args ~handle:"self._o" (snd style);
8791       pr "\n";
8792       pr "\n";
8793   ) all_functions
8794
8795 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8796 and generate_py_call_args ~handle args =
8797   pr "(%s" handle;
8798   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8799   pr ")"
8800
8801 (* Useful if you need the longdesc POD text as plain text.  Returns a
8802  * list of lines.
8803  *
8804  * Because this is very slow (the slowest part of autogeneration),
8805  * we memoize the results.
8806  *)
8807 and pod2text ~width name longdesc =
8808   let key = width, name, longdesc in
8809   try Hashtbl.find pod2text_memo key
8810   with Not_found ->
8811     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8812     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8813     close_out chan;
8814     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8815     let chan = open_process_in cmd in
8816     let lines = ref [] in
8817     let rec loop i =
8818       let line = input_line chan in
8819       if i = 1 then             (* discard the first line of output *)
8820         loop (i+1)
8821       else (
8822         let line = triml line in
8823         lines := line :: !lines;
8824         loop (i+1)
8825       ) in
8826     let lines = try loop 1 with End_of_file -> List.rev !lines in
8827     unlink filename;
8828     (match close_process_in chan with
8829      | WEXITED 0 -> ()
8830      | WEXITED i ->
8831          failwithf "pod2text: process exited with non-zero status (%d)" i
8832      | WSIGNALED i | WSTOPPED i ->
8833          failwithf "pod2text: process signalled or stopped by signal %d" i
8834     );
8835     Hashtbl.add pod2text_memo key lines;
8836     pod2text_memo_updated ();
8837     lines
8838
8839 (* Generate ruby bindings. *)
8840 and generate_ruby_c () =
8841   generate_header CStyle LGPLv2;
8842
8843   pr "\
8844 #include <stdio.h>
8845 #include <stdlib.h>
8846
8847 #include <ruby.h>
8848
8849 #include \"guestfs.h\"
8850
8851 #include \"extconf.h\"
8852
8853 /* For Ruby < 1.9 */
8854 #ifndef RARRAY_LEN
8855 #define RARRAY_LEN(r) (RARRAY((r))->len)
8856 #endif
8857
8858 static VALUE m_guestfs;                 /* guestfs module */
8859 static VALUE c_guestfs;                 /* guestfs_h handle */
8860 static VALUE e_Error;                   /* used for all errors */
8861
8862 static void ruby_guestfs_free (void *p)
8863 {
8864   if (!p) return;
8865   guestfs_close ((guestfs_h *) p);
8866 }
8867
8868 static VALUE ruby_guestfs_create (VALUE m)
8869 {
8870   guestfs_h *g;
8871
8872   g = guestfs_create ();
8873   if (!g)
8874     rb_raise (e_Error, \"failed to create guestfs handle\");
8875
8876   /* Don't print error messages to stderr by default. */
8877   guestfs_set_error_handler (g, NULL, NULL);
8878
8879   /* Wrap it, and make sure the close function is called when the
8880    * handle goes away.
8881    */
8882   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8883 }
8884
8885 static VALUE ruby_guestfs_close (VALUE gv)
8886 {
8887   guestfs_h *g;
8888   Data_Get_Struct (gv, guestfs_h, g);
8889
8890   ruby_guestfs_free (g);
8891   DATA_PTR (gv) = NULL;
8892
8893   return Qnil;
8894 }
8895
8896 ";
8897
8898   List.iter (
8899     fun (name, style, _, _, _, _, _) ->
8900       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8901       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8902       pr ")\n";
8903       pr "{\n";
8904       pr "  guestfs_h *g;\n";
8905       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8906       pr "  if (!g)\n";
8907       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8908         name;
8909       pr "\n";
8910
8911       List.iter (
8912         function
8913         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8914             pr "  Check_Type (%sv, T_STRING);\n" n;
8915             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8916             pr "  if (!%s)\n" n;
8917             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8918             pr "              \"%s\", \"%s\");\n" n name
8919         | OptString n ->
8920             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8921         | StringList n | DeviceList n ->
8922             pr "  char **%s;\n" n;
8923             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8924             pr "  {\n";
8925             pr "    int i, len;\n";
8926             pr "    len = RARRAY_LEN (%sv);\n" n;
8927             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8928               n;
8929             pr "    for (i = 0; i < len; ++i) {\n";
8930             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8931             pr "      %s[i] = StringValueCStr (v);\n" n;
8932             pr "    }\n";
8933             pr "    %s[len] = NULL;\n" n;
8934             pr "  }\n";
8935         | Bool n ->
8936             pr "  int %s = RTEST (%sv);\n" n n
8937         | Int n ->
8938             pr "  int %s = NUM2INT (%sv);\n" n n
8939         | Int64 n ->
8940             pr "  long long %s = NUM2LL (%sv);\n" n n
8941       ) (snd style);
8942       pr "\n";
8943
8944       let error_code =
8945         match fst style with
8946         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8947         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8948         | RConstString _ | RConstOptString _ ->
8949             pr "  const char *r;\n"; "NULL"
8950         | RString _ -> pr "  char *r;\n"; "NULL"
8951         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8952         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8953         | RStructList (_, typ) ->
8954             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8955         | RBufferOut _ ->
8956             pr "  char *r;\n";
8957             pr "  size_t size;\n";
8958             "NULL" in
8959       pr "\n";
8960
8961       pr "  r = guestfs_%s " name;
8962       generate_c_call_args ~handle:"g" style;
8963       pr ";\n";
8964
8965       List.iter (
8966         function
8967         | Pathname _ | Device _ | Dev_or_Path _ | String _
8968         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8969         | StringList n | DeviceList n ->
8970             pr "  free (%s);\n" n
8971       ) (snd style);
8972
8973       pr "  if (r == %s)\n" error_code;
8974       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8975       pr "\n";
8976
8977       (match fst style with
8978        | RErr ->
8979            pr "  return Qnil;\n"
8980        | RInt _ | RBool _ ->
8981            pr "  return INT2NUM (r);\n"
8982        | RInt64 _ ->
8983            pr "  return ULL2NUM (r);\n"
8984        | RConstString _ ->
8985            pr "  return rb_str_new2 (r);\n";
8986        | RConstOptString _ ->
8987            pr "  if (r)\n";
8988            pr "    return rb_str_new2 (r);\n";
8989            pr "  else\n";
8990            pr "    return Qnil;\n";
8991        | RString _ ->
8992            pr "  VALUE rv = rb_str_new2 (r);\n";
8993            pr "  free (r);\n";
8994            pr "  return rv;\n";
8995        | RStringList _ ->
8996            pr "  int i, len = 0;\n";
8997            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8998            pr "  VALUE rv = rb_ary_new2 (len);\n";
8999            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9000            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9001            pr "    free (r[i]);\n";
9002            pr "  }\n";
9003            pr "  free (r);\n";
9004            pr "  return rv;\n"
9005        | RStruct (_, typ) ->
9006            let cols = cols_of_struct typ in
9007            generate_ruby_struct_code typ cols
9008        | RStructList (_, typ) ->
9009            let cols = cols_of_struct typ in
9010            generate_ruby_struct_list_code typ cols
9011        | RHashtable _ ->
9012            pr "  VALUE rv = rb_hash_new ();\n";
9013            pr "  int i;\n";
9014            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9015            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9016            pr "    free (r[i]);\n";
9017            pr "    free (r[i+1]);\n";
9018            pr "  }\n";
9019            pr "  free (r);\n";
9020            pr "  return rv;\n"
9021        | RBufferOut _ ->
9022            pr "  VALUE rv = rb_str_new (r, size);\n";
9023            pr "  free (r);\n";
9024            pr "  return rv;\n";
9025       );
9026
9027       pr "}\n";
9028       pr "\n"
9029   ) all_functions;
9030
9031   pr "\
9032 /* Initialize the module. */
9033 void Init__guestfs ()
9034 {
9035   m_guestfs = rb_define_module (\"Guestfs\");
9036   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9037   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9038
9039   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9040   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9041
9042 ";
9043   (* Define the rest of the methods. *)
9044   List.iter (
9045     fun (name, style, _, _, _, _, _) ->
9046       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9047       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9048   ) all_functions;
9049
9050   pr "}\n"
9051
9052 (* Ruby code to return a struct. *)
9053 and generate_ruby_struct_code typ cols =
9054   pr "  VALUE rv = rb_hash_new ();\n";
9055   List.iter (
9056     function
9057     | name, FString ->
9058         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9059     | name, FBuffer ->
9060         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9061     | name, FUUID ->
9062         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9063     | name, (FBytes|FUInt64) ->
9064         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9065     | name, FInt64 ->
9066         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9067     | name, FUInt32 ->
9068         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9069     | name, FInt32 ->
9070         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9071     | name, FOptPercent ->
9072         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9073     | name, FChar -> (* XXX wrong? *)
9074         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9075   ) cols;
9076   pr "  guestfs_free_%s (r);\n" typ;
9077   pr "  return rv;\n"
9078
9079 (* Ruby code to return a struct list. *)
9080 and generate_ruby_struct_list_code typ cols =
9081   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9082   pr "  int i;\n";
9083   pr "  for (i = 0; i < r->len; ++i) {\n";
9084   pr "    VALUE hv = rb_hash_new ();\n";
9085   List.iter (
9086     function
9087     | name, FString ->
9088         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9089     | name, FBuffer ->
9090         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
9091     | name, FUUID ->
9092         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9093     | name, (FBytes|FUInt64) ->
9094         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9095     | name, FInt64 ->
9096         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9097     | name, FUInt32 ->
9098         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9099     | name, FInt32 ->
9100         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9101     | name, FOptPercent ->
9102         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9103     | name, FChar -> (* XXX wrong? *)
9104         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9105   ) cols;
9106   pr "    rb_ary_push (rv, hv);\n";
9107   pr "  }\n";
9108   pr "  guestfs_free_%s_list (r);\n" typ;
9109   pr "  return rv;\n"
9110
9111 (* Generate Java bindings GuestFS.java file. *)
9112 and generate_java_java () =
9113   generate_header CStyle LGPLv2;
9114
9115   pr "\
9116 package com.redhat.et.libguestfs;
9117
9118 import java.util.HashMap;
9119 import com.redhat.et.libguestfs.LibGuestFSException;
9120 import com.redhat.et.libguestfs.PV;
9121 import com.redhat.et.libguestfs.VG;
9122 import com.redhat.et.libguestfs.LV;
9123 import com.redhat.et.libguestfs.Stat;
9124 import com.redhat.et.libguestfs.StatVFS;
9125 import com.redhat.et.libguestfs.IntBool;
9126 import com.redhat.et.libguestfs.Dirent;
9127
9128 /**
9129  * The GuestFS object is a libguestfs handle.
9130  *
9131  * @author rjones
9132  */
9133 public class GuestFS {
9134   // Load the native code.
9135   static {
9136     System.loadLibrary (\"guestfs_jni\");
9137   }
9138
9139   /**
9140    * The native guestfs_h pointer.
9141    */
9142   long g;
9143
9144   /**
9145    * Create a libguestfs handle.
9146    *
9147    * @throws LibGuestFSException
9148    */
9149   public GuestFS () throws LibGuestFSException
9150   {
9151     g = _create ();
9152   }
9153   private native long _create () throws LibGuestFSException;
9154
9155   /**
9156    * Close a libguestfs handle.
9157    *
9158    * You can also leave handles to be collected by the garbage
9159    * collector, but this method ensures that the resources used
9160    * by the handle are freed up immediately.  If you call any
9161    * other methods after closing the handle, you will get an
9162    * exception.
9163    *
9164    * @throws LibGuestFSException
9165    */
9166   public void close () throws LibGuestFSException
9167   {
9168     if (g != 0)
9169       _close (g);
9170     g = 0;
9171   }
9172   private native void _close (long g) throws LibGuestFSException;
9173
9174   public void finalize () throws LibGuestFSException
9175   {
9176     close ();
9177   }
9178
9179 ";
9180
9181   List.iter (
9182     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9183       if not (List.mem NotInDocs flags); then (
9184         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9185         let doc =
9186           if List.mem ProtocolLimitWarning flags then
9187             doc ^ "\n\n" ^ protocol_limit_warning
9188           else doc in
9189         let doc =
9190           if List.mem DangerWillRobinson flags then
9191             doc ^ "\n\n" ^ danger_will_robinson
9192           else doc in
9193         let doc =
9194           match deprecation_notice flags with
9195           | None -> doc
9196           | Some txt -> doc ^ "\n\n" ^ txt in
9197         let doc = pod2text ~width:60 name doc in
9198         let doc = List.map (            (* RHBZ#501883 *)
9199           function
9200           | "" -> "<p>"
9201           | nonempty -> nonempty
9202         ) doc in
9203         let doc = String.concat "\n   * " doc in
9204
9205         pr "  /**\n";
9206         pr "   * %s\n" shortdesc;
9207         pr "   * <p>\n";
9208         pr "   * %s\n" doc;
9209         pr "   * @throws LibGuestFSException\n";
9210         pr "   */\n";
9211         pr "  ";
9212       );
9213       generate_java_prototype ~public:true ~semicolon:false name style;
9214       pr "\n";
9215       pr "  {\n";
9216       pr "    if (g == 0)\n";
9217       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9218         name;
9219       pr "    ";
9220       if fst style <> RErr then pr "return ";
9221       pr "_%s " name;
9222       generate_java_call_args ~handle:"g" (snd style);
9223       pr ";\n";
9224       pr "  }\n";
9225       pr "  ";
9226       generate_java_prototype ~privat:true ~native:true name style;
9227       pr "\n";
9228       pr "\n";
9229   ) all_functions;
9230
9231   pr "}\n"
9232
9233 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9234 and generate_java_call_args ~handle args =
9235   pr "(%s" handle;
9236   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9237   pr ")"
9238
9239 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9240     ?(semicolon=true) name style =
9241   if privat then pr "private ";
9242   if public then pr "public ";
9243   if native then pr "native ";
9244
9245   (* return type *)
9246   (match fst style with
9247    | RErr -> pr "void ";
9248    | RInt _ -> pr "int ";
9249    | RInt64 _ -> pr "long ";
9250    | RBool _ -> pr "boolean ";
9251    | RConstString _ | RConstOptString _ | RString _
9252    | RBufferOut _ -> pr "String ";
9253    | RStringList _ -> pr "String[] ";
9254    | RStruct (_, typ) ->
9255        let name = java_name_of_struct typ in
9256        pr "%s " name;
9257    | RStructList (_, typ) ->
9258        let name = java_name_of_struct typ in
9259        pr "%s[] " name;
9260    | RHashtable _ -> pr "HashMap<String,String> ";
9261   );
9262
9263   if native then pr "_%s " name else pr "%s " name;
9264   pr "(";
9265   let needs_comma = ref false in
9266   if native then (
9267     pr "long g";
9268     needs_comma := true
9269   );
9270
9271   (* args *)
9272   List.iter (
9273     fun arg ->
9274       if !needs_comma then pr ", ";
9275       needs_comma := true;
9276
9277       match arg with
9278       | Pathname n
9279       | Device n | Dev_or_Path n
9280       | String n
9281       | OptString n
9282       | FileIn n
9283       | FileOut n ->
9284           pr "String %s" n
9285       | StringList n | DeviceList n ->
9286           pr "String[] %s" n
9287       | Bool n ->
9288           pr "boolean %s" n
9289       | Int n ->
9290           pr "int %s" n
9291       | Int64 n ->
9292           pr "long %s" n
9293   ) (snd style);
9294
9295   pr ")\n";
9296   pr "    throws LibGuestFSException";
9297   if semicolon then pr ";"
9298
9299 and generate_java_struct jtyp cols =
9300   generate_header CStyle LGPLv2;
9301
9302   pr "\
9303 package com.redhat.et.libguestfs;
9304
9305 /**
9306  * Libguestfs %s structure.
9307  *
9308  * @author rjones
9309  * @see GuestFS
9310  */
9311 public class %s {
9312 " jtyp jtyp;
9313
9314   List.iter (
9315     function
9316     | name, FString
9317     | name, FUUID
9318     | name, FBuffer -> pr "  public String %s;\n" name
9319     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9320     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9321     | name, FChar -> pr "  public char %s;\n" name
9322     | name, FOptPercent ->
9323         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9324         pr "  public float %s;\n" name
9325   ) cols;
9326
9327   pr "}\n"
9328
9329 and generate_java_c () =
9330   generate_header CStyle LGPLv2;
9331
9332   pr "\
9333 #include <stdio.h>
9334 #include <stdlib.h>
9335 #include <string.h>
9336
9337 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9338 #include \"guestfs.h\"
9339
9340 /* Note that this function returns.  The exception is not thrown
9341  * until after the wrapper function returns.
9342  */
9343 static void
9344 throw_exception (JNIEnv *env, const char *msg)
9345 {
9346   jclass cl;
9347   cl = (*env)->FindClass (env,
9348                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9349   (*env)->ThrowNew (env, cl, msg);
9350 }
9351
9352 JNIEXPORT jlong JNICALL
9353 Java_com_redhat_et_libguestfs_GuestFS__1create
9354   (JNIEnv *env, jobject obj)
9355 {
9356   guestfs_h *g;
9357
9358   g = guestfs_create ();
9359   if (g == NULL) {
9360     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9361     return 0;
9362   }
9363   guestfs_set_error_handler (g, NULL, NULL);
9364   return (jlong) (long) g;
9365 }
9366
9367 JNIEXPORT void JNICALL
9368 Java_com_redhat_et_libguestfs_GuestFS__1close
9369   (JNIEnv *env, jobject obj, jlong jg)
9370 {
9371   guestfs_h *g = (guestfs_h *) (long) jg;
9372   guestfs_close (g);
9373 }
9374
9375 ";
9376
9377   List.iter (
9378     fun (name, style, _, _, _, _, _) ->
9379       pr "JNIEXPORT ";
9380       (match fst style with
9381        | RErr -> pr "void ";
9382        | RInt _ -> pr "jint ";
9383        | RInt64 _ -> pr "jlong ";
9384        | RBool _ -> pr "jboolean ";
9385        | RConstString _ | RConstOptString _ | RString _
9386        | RBufferOut _ -> pr "jstring ";
9387        | RStruct _ | RHashtable _ ->
9388            pr "jobject ";
9389        | RStringList _ | RStructList _ ->
9390            pr "jobjectArray ";
9391       );
9392       pr "JNICALL\n";
9393       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9394       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9395       pr "\n";
9396       pr "  (JNIEnv *env, jobject obj, jlong jg";
9397       List.iter (
9398         function
9399         | Pathname n
9400         | Device n | Dev_or_Path n
9401         | String n
9402         | OptString n
9403         | FileIn n
9404         | FileOut n ->
9405             pr ", jstring j%s" n
9406         | StringList n | DeviceList n ->
9407             pr ", jobjectArray j%s" n
9408         | Bool n ->
9409             pr ", jboolean j%s" n
9410         | Int n ->
9411             pr ", jint j%s" n
9412         | Int64 n ->
9413             pr ", jlong j%s" n
9414       ) (snd style);
9415       pr ")\n";
9416       pr "{\n";
9417       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9418       let error_code, no_ret =
9419         match fst style with
9420         | RErr -> pr "  int r;\n"; "-1", ""
9421         | RBool _
9422         | RInt _ -> pr "  int r;\n"; "-1", "0"
9423         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9424         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9425         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9426         | RString _ ->
9427             pr "  jstring jr;\n";
9428             pr "  char *r;\n"; "NULL", "NULL"
9429         | RStringList _ ->
9430             pr "  jobjectArray jr;\n";
9431             pr "  int r_len;\n";
9432             pr "  jclass cl;\n";
9433             pr "  jstring jstr;\n";
9434             pr "  char **r;\n"; "NULL", "NULL"
9435         | RStruct (_, typ) ->
9436             pr "  jobject jr;\n";
9437             pr "  jclass cl;\n";
9438             pr "  jfieldID fl;\n";
9439             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9440         | RStructList (_, typ) ->
9441             pr "  jobjectArray jr;\n";
9442             pr "  jclass cl;\n";
9443             pr "  jfieldID fl;\n";
9444             pr "  jobject jfl;\n";
9445             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9446         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9447         | RBufferOut _ ->
9448             pr "  jstring jr;\n";
9449             pr "  char *r;\n";
9450             pr "  size_t size;\n";
9451             "NULL", "NULL" in
9452       List.iter (
9453         function
9454         | Pathname n
9455         | Device n | Dev_or_Path n
9456         | String n
9457         | OptString n
9458         | FileIn n
9459         | FileOut n ->
9460             pr "  const char *%s;\n" n
9461         | StringList n | DeviceList n ->
9462             pr "  int %s_len;\n" n;
9463             pr "  const char **%s;\n" n
9464         | Bool n
9465         | Int n ->
9466             pr "  int %s;\n" n
9467         | Int64 n ->
9468             pr "  int64_t %s;\n" n
9469       ) (snd style);
9470
9471       let needs_i =
9472         (match fst style with
9473          | RStringList _ | RStructList _ -> true
9474          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9475          | RConstOptString _
9476          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9477           List.exists (function
9478                        | StringList _ -> true
9479                        | DeviceList _ -> true
9480                        | _ -> false) (snd style) in
9481       if needs_i then
9482         pr "  int i;\n";
9483
9484       pr "\n";
9485
9486       (* Get the parameters. *)
9487       List.iter (
9488         function
9489         | Pathname n
9490         | Device n | Dev_or_Path n
9491         | String n
9492         | FileIn n
9493         | FileOut n ->
9494             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9495         | OptString n ->
9496             (* This is completely undocumented, but Java null becomes
9497              * a NULL parameter.
9498              *)
9499             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9500         | StringList n | DeviceList n ->
9501             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9502             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9503             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9504             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9505               n;
9506             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9507             pr "  }\n";
9508             pr "  %s[%s_len] = NULL;\n" n n;
9509         | Bool n
9510         | Int n
9511         | Int64 n ->
9512             pr "  %s = j%s;\n" n n
9513       ) (snd style);
9514
9515       (* Make the call. *)
9516       pr "  r = guestfs_%s " name;
9517       generate_c_call_args ~handle:"g" style;
9518       pr ";\n";
9519
9520       (* Release the parameters. *)
9521       List.iter (
9522         function
9523         | Pathname n
9524         | Device n | Dev_or_Path n
9525         | String n
9526         | FileIn n
9527         | FileOut n ->
9528             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9529         | OptString n ->
9530             pr "  if (j%s)\n" n;
9531             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9532         | StringList n | DeviceList n ->
9533             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9534             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9535               n;
9536             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9537             pr "  }\n";
9538             pr "  free (%s);\n" n
9539         | Bool n
9540         | Int n
9541         | Int64 n -> ()
9542       ) (snd style);
9543
9544       (* Check for errors. *)
9545       pr "  if (r == %s) {\n" error_code;
9546       pr "    throw_exception (env, guestfs_last_error (g));\n";
9547       pr "    return %s;\n" no_ret;
9548       pr "  }\n";
9549
9550       (* Return value. *)
9551       (match fst style with
9552        | RErr -> ()
9553        | RInt _ -> pr "  return (jint) r;\n"
9554        | RBool _ -> pr "  return (jboolean) r;\n"
9555        | RInt64 _ -> pr "  return (jlong) r;\n"
9556        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9557        | RConstOptString _ ->
9558            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9559        | RString _ ->
9560            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9561            pr "  free (r);\n";
9562            pr "  return jr;\n"
9563        | RStringList _ ->
9564            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9565            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9566            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9567            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9568            pr "  for (i = 0; i < r_len; ++i) {\n";
9569            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9570            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9571            pr "    free (r[i]);\n";
9572            pr "  }\n";
9573            pr "  free (r);\n";
9574            pr "  return jr;\n"
9575        | RStruct (_, typ) ->
9576            let jtyp = java_name_of_struct typ in
9577            let cols = cols_of_struct typ in
9578            generate_java_struct_return typ jtyp cols
9579        | RStructList (_, typ) ->
9580            let jtyp = java_name_of_struct typ in
9581            let cols = cols_of_struct typ in
9582            generate_java_struct_list_return typ jtyp cols
9583        | RHashtable _ ->
9584            (* XXX *)
9585            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9586            pr "  return NULL;\n"
9587        | RBufferOut _ ->
9588            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9589            pr "  free (r);\n";
9590            pr "  return jr;\n"
9591       );
9592
9593       pr "}\n";
9594       pr "\n"
9595   ) all_functions
9596
9597 and generate_java_struct_return typ jtyp cols =
9598   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9599   pr "  jr = (*env)->AllocObject (env, cl);\n";
9600   List.iter (
9601     function
9602     | name, FString ->
9603         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9604         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9605     | name, FUUID ->
9606         pr "  {\n";
9607         pr "    char s[33];\n";
9608         pr "    memcpy (s, r->%s, 32);\n" name;
9609         pr "    s[32] = 0;\n";
9610         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9611         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9612         pr "  }\n";
9613     | name, FBuffer ->
9614         pr "  {\n";
9615         pr "    int len = r->%s_len;\n" name;
9616         pr "    char s[len+1];\n";
9617         pr "    memcpy (s, r->%s, len);\n" name;
9618         pr "    s[len] = 0;\n";
9619         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9620         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9621         pr "  }\n";
9622     | name, (FBytes|FUInt64|FInt64) ->
9623         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9624         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9625     | name, (FUInt32|FInt32) ->
9626         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9627         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9628     | name, FOptPercent ->
9629         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9630         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9631     | name, FChar ->
9632         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9633         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9634   ) cols;
9635   pr "  free (r);\n";
9636   pr "  return jr;\n"
9637
9638 and generate_java_struct_list_return typ jtyp cols =
9639   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9640   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9641   pr "  for (i = 0; i < r->len; ++i) {\n";
9642   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9643   List.iter (
9644     function
9645     | name, FString ->
9646         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9647         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9648     | name, FUUID ->
9649         pr "    {\n";
9650         pr "      char s[33];\n";
9651         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9652         pr "      s[32] = 0;\n";
9653         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9654         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9655         pr "    }\n";
9656     | name, FBuffer ->
9657         pr "    {\n";
9658         pr "      int len = r->val[i].%s_len;\n" name;
9659         pr "      char s[len+1];\n";
9660         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9661         pr "      s[len] = 0;\n";
9662         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9663         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9664         pr "    }\n";
9665     | name, (FBytes|FUInt64|FInt64) ->
9666         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9667         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9668     | name, (FUInt32|FInt32) ->
9669         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9670         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9671     | name, FOptPercent ->
9672         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9673         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9674     | name, FChar ->
9675         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9676         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9677   ) cols;
9678   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9679   pr "  }\n";
9680   pr "  guestfs_free_%s_list (r);\n" typ;
9681   pr "  return jr;\n"
9682
9683 and generate_java_makefile_inc () =
9684   generate_header HashStyle GPLv2;
9685
9686   pr "java_built_sources = \\\n";
9687   List.iter (
9688     fun (typ, jtyp) ->
9689         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9690   ) java_structs;
9691   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9692
9693 and generate_haskell_hs () =
9694   generate_header HaskellStyle LGPLv2;
9695
9696   (* XXX We only know how to generate partial FFI for Haskell
9697    * at the moment.  Please help out!
9698    *)
9699   let can_generate style =
9700     match style with
9701     | RErr, _
9702     | RInt _, _
9703     | RInt64 _, _ -> true
9704     | RBool _, _
9705     | RConstString _, _
9706     | RConstOptString _, _
9707     | RString _, _
9708     | RStringList _, _
9709     | RStruct _, _
9710     | RStructList _, _
9711     | RHashtable _, _
9712     | RBufferOut _, _ -> false in
9713
9714   pr "\
9715 {-# INCLUDE <guestfs.h> #-}
9716 {-# LANGUAGE ForeignFunctionInterface #-}
9717
9718 module Guestfs (
9719   create";
9720
9721   (* List out the names of the actions we want to export. *)
9722   List.iter (
9723     fun (name, style, _, _, _, _, _) ->
9724       if can_generate style then pr ",\n  %s" name
9725   ) all_functions;
9726
9727   pr "
9728   ) where
9729
9730 -- Unfortunately some symbols duplicate ones already present
9731 -- in Prelude.  We don't know which, so we hard-code a list
9732 -- here.
9733 import Prelude hiding (truncate)
9734
9735 import Foreign
9736 import Foreign.C
9737 import Foreign.C.Types
9738 import IO
9739 import Control.Exception
9740 import Data.Typeable
9741
9742 data GuestfsS = GuestfsS            -- represents the opaque C struct
9743 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9744 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9745
9746 -- XXX define properly later XXX
9747 data PV = PV
9748 data VG = VG
9749 data LV = LV
9750 data IntBool = IntBool
9751 data Stat = Stat
9752 data StatVFS = StatVFS
9753 data Hashtable = Hashtable
9754
9755 foreign import ccall unsafe \"guestfs_create\" c_create
9756   :: IO GuestfsP
9757 foreign import ccall unsafe \"&guestfs_close\" c_close
9758   :: FunPtr (GuestfsP -> IO ())
9759 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9760   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9761
9762 create :: IO GuestfsH
9763 create = do
9764   p <- c_create
9765   c_set_error_handler p nullPtr nullPtr
9766   h <- newForeignPtr c_close p
9767   return h
9768
9769 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9770   :: GuestfsP -> IO CString
9771
9772 -- last_error :: GuestfsH -> IO (Maybe String)
9773 -- last_error h = do
9774 --   str <- withForeignPtr h (\\p -> c_last_error p)
9775 --   maybePeek peekCString str
9776
9777 last_error :: GuestfsH -> IO (String)
9778 last_error h = do
9779   str <- withForeignPtr h (\\p -> c_last_error p)
9780   if (str == nullPtr)
9781     then return \"no error\"
9782     else peekCString str
9783
9784 ";
9785
9786   (* Generate wrappers for each foreign function. *)
9787   List.iter (
9788     fun (name, style, _, _, _, _, _) ->
9789       if can_generate style then (
9790         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9791         pr "  :: ";
9792         generate_haskell_prototype ~handle:"GuestfsP" style;
9793         pr "\n";
9794         pr "\n";
9795         pr "%s :: " name;
9796         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9797         pr "\n";
9798         pr "%s %s = do\n" name
9799           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9800         pr "  r <- ";
9801         (* Convert pointer arguments using with* functions. *)
9802         List.iter (
9803           function
9804           | FileIn n
9805           | FileOut n
9806           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9807           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9808           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9809           | Bool _ | Int _ | Int64 _ -> ()
9810         ) (snd style);
9811         (* Convert integer arguments. *)
9812         let args =
9813           List.map (
9814             function
9815             | Bool n -> sprintf "(fromBool %s)" n
9816             | Int n -> sprintf "(fromIntegral %s)" n
9817             | Int64 n -> sprintf "(fromIntegral %s)" n
9818             | FileIn n | FileOut n
9819             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9820           ) (snd style) in
9821         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9822           (String.concat " " ("p" :: args));
9823         (match fst style with
9824          | RErr | RInt _ | RInt64 _ | RBool _ ->
9825              pr "  if (r == -1)\n";
9826              pr "    then do\n";
9827              pr "      err <- last_error h\n";
9828              pr "      fail err\n";
9829          | RConstString _ | RConstOptString _ | RString _
9830          | RStringList _ | RStruct _
9831          | RStructList _ | RHashtable _ | RBufferOut _ ->
9832              pr "  if (r == nullPtr)\n";
9833              pr "    then do\n";
9834              pr "      err <- last_error h\n";
9835              pr "      fail err\n";
9836         );
9837         (match fst style with
9838          | RErr ->
9839              pr "    else return ()\n"
9840          | RInt _ ->
9841              pr "    else return (fromIntegral r)\n"
9842          | RInt64 _ ->
9843              pr "    else return (fromIntegral r)\n"
9844          | RBool _ ->
9845              pr "    else return (toBool r)\n"
9846          | RConstString _
9847          | RConstOptString _
9848          | RString _
9849          | RStringList _
9850          | RStruct _
9851          | RStructList _
9852          | RHashtable _
9853          | RBufferOut _ ->
9854              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9855         );
9856         pr "\n";
9857       )
9858   ) all_functions
9859
9860 and generate_haskell_prototype ~handle ?(hs = false) style =
9861   pr "%s -> " handle;
9862   let string = if hs then "String" else "CString" in
9863   let int = if hs then "Int" else "CInt" in
9864   let bool = if hs then "Bool" else "CInt" in
9865   let int64 = if hs then "Integer" else "Int64" in
9866   List.iter (
9867     fun arg ->
9868       (match arg with
9869        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9870        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9871        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9872        | Bool _ -> pr "%s" bool
9873        | Int _ -> pr "%s" int
9874        | Int64 _ -> pr "%s" int
9875        | FileIn _ -> pr "%s" string
9876        | FileOut _ -> pr "%s" string
9877       );
9878       pr " -> ";
9879   ) (snd style);
9880   pr "IO (";
9881   (match fst style with
9882    | RErr -> if not hs then pr "CInt"
9883    | RInt _ -> pr "%s" int
9884    | RInt64 _ -> pr "%s" int64
9885    | RBool _ -> pr "%s" bool
9886    | RConstString _ -> pr "%s" string
9887    | RConstOptString _ -> pr "Maybe %s" string
9888    | RString _ -> pr "%s" string
9889    | RStringList _ -> pr "[%s]" string
9890    | RStruct (_, typ) ->
9891        let name = java_name_of_struct typ in
9892        pr "%s" name
9893    | RStructList (_, typ) ->
9894        let name = java_name_of_struct typ in
9895        pr "[%s]" name
9896    | RHashtable _ -> pr "Hashtable"
9897    | RBufferOut _ -> pr "%s" string
9898   );
9899   pr ")"
9900
9901 and generate_bindtests () =
9902   generate_header CStyle LGPLv2;
9903
9904   pr "\
9905 #include <stdio.h>
9906 #include <stdlib.h>
9907 #include <inttypes.h>
9908 #include <string.h>
9909
9910 #include \"guestfs.h\"
9911 #include \"guestfs-internal.h\"
9912 #include \"guestfs-internal-actions.h\"
9913 #include \"guestfs_protocol.h\"
9914
9915 #define error guestfs_error
9916 #define safe_calloc guestfs_safe_calloc
9917 #define safe_malloc guestfs_safe_malloc
9918
9919 static void
9920 print_strings (char *const *argv)
9921 {
9922   int argc;
9923
9924   printf (\"[\");
9925   for (argc = 0; argv[argc] != NULL; ++argc) {
9926     if (argc > 0) printf (\", \");
9927     printf (\"\\\"%%s\\\"\", argv[argc]);
9928   }
9929   printf (\"]\\n\");
9930 }
9931
9932 /* The test0 function prints its parameters to stdout. */
9933 ";
9934
9935   let test0, tests =
9936     match test_functions with
9937     | [] -> assert false
9938     | test0 :: tests -> test0, tests in
9939
9940   let () =
9941     let (name, style, _, _, _, _, _) = test0 in
9942     generate_prototype ~extern:false ~semicolon:false ~newline:true
9943       ~handle:"g" ~prefix:"guestfs__" name style;
9944     pr "{\n";
9945     List.iter (
9946       function
9947       | Pathname n
9948       | Device n | Dev_or_Path n
9949       | String n
9950       | FileIn n
9951       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9952       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9953       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9954       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9955       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9956       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9957     ) (snd style);
9958     pr "  /* Java changes stdout line buffering so we need this: */\n";
9959     pr "  fflush (stdout);\n";
9960     pr "  return 0;\n";
9961     pr "}\n";
9962     pr "\n" in
9963
9964   List.iter (
9965     fun (name, style, _, _, _, _, _) ->
9966       if String.sub name (String.length name - 3) 3 <> "err" then (
9967         pr "/* Test normal return. */\n";
9968         generate_prototype ~extern:false ~semicolon:false ~newline:true
9969           ~handle:"g" ~prefix:"guestfs__" name style;
9970         pr "{\n";
9971         (match fst style with
9972          | RErr ->
9973              pr "  return 0;\n"
9974          | RInt _ ->
9975              pr "  int r;\n";
9976              pr "  sscanf (val, \"%%d\", &r);\n";
9977              pr "  return r;\n"
9978          | RInt64 _ ->
9979              pr "  int64_t r;\n";
9980              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9981              pr "  return r;\n"
9982          | RBool _ ->
9983              pr "  return STREQ (val, \"true\");\n"
9984          | RConstString _
9985          | RConstOptString _ ->
9986              (* Can't return the input string here.  Return a static
9987               * string so we ensure we get a segfault if the caller
9988               * tries to free it.
9989               *)
9990              pr "  return \"static string\";\n"
9991          | RString _ ->
9992              pr "  return strdup (val);\n"
9993          | RStringList _ ->
9994              pr "  char **strs;\n";
9995              pr "  int n, i;\n";
9996              pr "  sscanf (val, \"%%d\", &n);\n";
9997              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9998              pr "  for (i = 0; i < n; ++i) {\n";
9999              pr "    strs[i] = safe_malloc (g, 16);\n";
10000              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10001              pr "  }\n";
10002              pr "  strs[n] = NULL;\n";
10003              pr "  return strs;\n"
10004          | RStruct (_, typ) ->
10005              pr "  struct guestfs_%s *r;\n" typ;
10006              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10007              pr "  return r;\n"
10008          | RStructList (_, typ) ->
10009              pr "  struct guestfs_%s_list *r;\n" typ;
10010              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10011              pr "  sscanf (val, \"%%d\", &r->len);\n";
10012              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10013              pr "  return r;\n"
10014          | RHashtable _ ->
10015              pr "  char **strs;\n";
10016              pr "  int n, i;\n";
10017              pr "  sscanf (val, \"%%d\", &n);\n";
10018              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10019              pr "  for (i = 0; i < n; ++i) {\n";
10020              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10021              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10022              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10023              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10024              pr "  }\n";
10025              pr "  strs[n*2] = NULL;\n";
10026              pr "  return strs;\n"
10027          | RBufferOut _ ->
10028              pr "  return strdup (val);\n"
10029         );
10030         pr "}\n";
10031         pr "\n"
10032       ) else (
10033         pr "/* Test error return. */\n";
10034         generate_prototype ~extern:false ~semicolon:false ~newline:true
10035           ~handle:"g" ~prefix:"guestfs__" name style;
10036         pr "{\n";
10037         pr "  error (g, \"error\");\n";
10038         (match fst style with
10039          | RErr | RInt _ | RInt64 _ | RBool _ ->
10040              pr "  return -1;\n"
10041          | RConstString _ | RConstOptString _
10042          | RString _ | RStringList _ | RStruct _
10043          | RStructList _
10044          | RHashtable _
10045          | RBufferOut _ ->
10046              pr "  return NULL;\n"
10047         );
10048         pr "}\n";
10049         pr "\n"
10050       )
10051   ) tests
10052
10053 and generate_ocaml_bindtests () =
10054   generate_header OCamlStyle GPLv2;
10055
10056   pr "\
10057 let () =
10058   let g = Guestfs.create () in
10059 ";
10060
10061   let mkargs args =
10062     String.concat " " (
10063       List.map (
10064         function
10065         | CallString s -> "\"" ^ s ^ "\""
10066         | CallOptString None -> "None"
10067         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10068         | CallStringList xs ->
10069             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10070         | CallInt i when i >= 0 -> string_of_int i
10071         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10072         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10073         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10074         | CallBool b -> string_of_bool b
10075       ) args
10076     )
10077   in
10078
10079   generate_lang_bindtests (
10080     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10081   );
10082
10083   pr "print_endline \"EOF\"\n"
10084
10085 and generate_perl_bindtests () =
10086   pr "#!/usr/bin/perl -w\n";
10087   generate_header HashStyle GPLv2;
10088
10089   pr "\
10090 use strict;
10091
10092 use Sys::Guestfs;
10093
10094 my $g = Sys::Guestfs->new ();
10095 ";
10096
10097   let mkargs args =
10098     String.concat ", " (
10099       List.map (
10100         function
10101         | CallString s -> "\"" ^ s ^ "\""
10102         | CallOptString None -> "undef"
10103         | CallOptString (Some s) -> sprintf "\"%s\"" s
10104         | CallStringList xs ->
10105             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10106         | CallInt i -> string_of_int i
10107         | CallInt64 i -> Int64.to_string i
10108         | CallBool b -> if b then "1" else "0"
10109       ) args
10110     )
10111   in
10112
10113   generate_lang_bindtests (
10114     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10115   );
10116
10117   pr "print \"EOF\\n\"\n"
10118
10119 and generate_python_bindtests () =
10120   generate_header HashStyle GPLv2;
10121
10122   pr "\
10123 import guestfs
10124
10125 g = guestfs.GuestFS ()
10126 ";
10127
10128   let mkargs args =
10129     String.concat ", " (
10130       List.map (
10131         function
10132         | CallString s -> "\"" ^ s ^ "\""
10133         | CallOptString None -> "None"
10134         | CallOptString (Some s) -> sprintf "\"%s\"" s
10135         | CallStringList xs ->
10136             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10137         | CallInt i -> string_of_int i
10138         | CallInt64 i -> Int64.to_string i
10139         | CallBool b -> if b then "1" else "0"
10140       ) args
10141     )
10142   in
10143
10144   generate_lang_bindtests (
10145     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10146   );
10147
10148   pr "print \"EOF\"\n"
10149
10150 and generate_ruby_bindtests () =
10151   generate_header HashStyle GPLv2;
10152
10153   pr "\
10154 require 'guestfs'
10155
10156 g = Guestfs::create()
10157 ";
10158
10159   let mkargs args =
10160     String.concat ", " (
10161       List.map (
10162         function
10163         | CallString s -> "\"" ^ s ^ "\""
10164         | CallOptString None -> "nil"
10165         | CallOptString (Some s) -> sprintf "\"%s\"" s
10166         | CallStringList xs ->
10167             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10168         | CallInt i -> string_of_int i
10169         | CallInt64 i -> Int64.to_string i
10170         | CallBool b -> string_of_bool b
10171       ) args
10172     )
10173   in
10174
10175   generate_lang_bindtests (
10176     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10177   );
10178
10179   pr "print \"EOF\\n\"\n"
10180
10181 and generate_java_bindtests () =
10182   generate_header CStyle GPLv2;
10183
10184   pr "\
10185 import com.redhat.et.libguestfs.*;
10186
10187 public class Bindtests {
10188     public static void main (String[] argv)
10189     {
10190         try {
10191             GuestFS g = new GuestFS ();
10192 ";
10193
10194   let mkargs args =
10195     String.concat ", " (
10196       List.map (
10197         function
10198         | CallString s -> "\"" ^ s ^ "\""
10199         | CallOptString None -> "null"
10200         | CallOptString (Some s) -> sprintf "\"%s\"" s
10201         | CallStringList xs ->
10202             "new String[]{" ^
10203               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10204         | CallInt i -> string_of_int i
10205         | CallInt64 i -> Int64.to_string i
10206         | CallBool b -> string_of_bool b
10207       ) args
10208     )
10209   in
10210
10211   generate_lang_bindtests (
10212     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10213   );
10214
10215   pr "
10216             System.out.println (\"EOF\");
10217         }
10218         catch (Exception exn) {
10219             System.err.println (exn);
10220             System.exit (1);
10221         }
10222     }
10223 }
10224 "
10225
10226 and generate_haskell_bindtests () =
10227   generate_header HaskellStyle GPLv2;
10228
10229   pr "\
10230 module Bindtests where
10231 import qualified Guestfs
10232
10233 main = do
10234   g <- Guestfs.create
10235 ";
10236
10237   let mkargs args =
10238     String.concat " " (
10239       List.map (
10240         function
10241         | CallString s -> "\"" ^ s ^ "\""
10242         | CallOptString None -> "Nothing"
10243         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10244         | CallStringList xs ->
10245             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10246         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10247         | CallInt i -> string_of_int i
10248         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10249         | CallInt64 i -> Int64.to_string i
10250         | CallBool true -> "True"
10251         | CallBool false -> "False"
10252       ) args
10253     )
10254   in
10255
10256   generate_lang_bindtests (
10257     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10258   );
10259
10260   pr "  putStrLn \"EOF\"\n"
10261
10262 (* Language-independent bindings tests - we do it this way to
10263  * ensure there is parity in testing bindings across all languages.
10264  *)
10265 and generate_lang_bindtests call =
10266   call "test0" [CallString "abc"; CallOptString (Some "def");
10267                 CallStringList []; CallBool false;
10268                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10269   call "test0" [CallString "abc"; CallOptString None;
10270                 CallStringList []; CallBool false;
10271                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10272   call "test0" [CallString ""; CallOptString (Some "def");
10273                 CallStringList []; CallBool false;
10274                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10275   call "test0" [CallString ""; CallOptString (Some "");
10276                 CallStringList []; CallBool false;
10277                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10278   call "test0" [CallString "abc"; CallOptString (Some "def");
10279                 CallStringList ["1"]; CallBool false;
10280                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10281   call "test0" [CallString "abc"; CallOptString (Some "def");
10282                 CallStringList ["1"; "2"]; CallBool false;
10283                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10284   call "test0" [CallString "abc"; CallOptString (Some "def");
10285                 CallStringList ["1"]; CallBool true;
10286                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10287   call "test0" [CallString "abc"; CallOptString (Some "def");
10288                 CallStringList ["1"]; CallBool false;
10289                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10290   call "test0" [CallString "abc"; CallOptString (Some "def");
10291                 CallStringList ["1"]; CallBool false;
10292                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10293   call "test0" [CallString "abc"; CallOptString (Some "def");
10294                 CallStringList ["1"]; CallBool false;
10295                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10296   call "test0" [CallString "abc"; CallOptString (Some "def");
10297                 CallStringList ["1"]; CallBool false;
10298                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10299   call "test0" [CallString "abc"; CallOptString (Some "def");
10300                 CallStringList ["1"]; CallBool false;
10301                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10302   call "test0" [CallString "abc"; CallOptString (Some "def");
10303                 CallStringList ["1"]; CallBool false;
10304                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10305
10306 (* XXX Add here tests of the return and error functions. *)
10307
10308 (* This is used to generate the src/MAX_PROC_NR file which
10309  * contains the maximum procedure number, a surrogate for the
10310  * ABI version number.  See src/Makefile.am for the details.
10311  *)
10312 and generate_max_proc_nr () =
10313   let proc_nrs = List.map (
10314     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10315   ) daemon_functions in
10316
10317   let max_proc_nr = List.fold_left max 0 proc_nrs in
10318
10319   pr "%d\n" max_proc_nr
10320
10321 let output_to filename =
10322   let filename_new = filename ^ ".new" in
10323   chan := open_out filename_new;
10324   let close () =
10325     close_out !chan;
10326     chan := Pervasives.stdout;
10327
10328     (* Is the new file different from the current file? *)
10329     if Sys.file_exists filename && files_equal filename filename_new then
10330       unlink filename_new               (* same, so skip it *)
10331     else (
10332       (* different, overwrite old one *)
10333       (try chmod filename 0o644 with Unix_error _ -> ());
10334       rename filename_new filename;
10335       chmod filename 0o444;
10336       printf "written %s\n%!" filename;
10337     )
10338   in
10339   close
10340
10341 let perror msg = function
10342   | Unix_error (err, _, _) ->
10343       eprintf "%s: %s\n" msg (error_message err)
10344   | exn ->
10345       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10346
10347 (* Main program. *)
10348 let () =
10349   let lock_fd =
10350     try openfile "HACKING" [O_RDWR] 0
10351     with
10352     | Unix_error (ENOENT, _, _) ->
10353         eprintf "\
10354 You are probably running this from the wrong directory.
10355 Run it from the top source directory using the command
10356   src/generator.ml
10357 ";
10358         exit 1
10359     | exn ->
10360         perror "open: HACKING" exn;
10361         exit 1 in
10362
10363   (* Acquire a lock so parallel builds won't try to run the generator
10364    * twice at the same time.  Subsequent builds will wait for the first
10365    * one to finish.  Note the lock is released implicitly when the
10366    * program exits.
10367    *)
10368   (try lockf lock_fd F_LOCK 1
10369    with exn ->
10370      perror "lock: HACKING" exn;
10371      exit 1);
10372
10373   check_functions ();
10374
10375   let close = output_to "src/guestfs_protocol.x" in
10376   generate_xdr ();
10377   close ();
10378
10379   let close = output_to "src/guestfs-structs.h" in
10380   generate_structs_h ();
10381   close ();
10382
10383   let close = output_to "src/guestfs-actions.h" in
10384   generate_actions_h ();
10385   close ();
10386
10387   let close = output_to "src/guestfs-internal-actions.h" in
10388   generate_internal_actions_h ();
10389   close ();
10390
10391   let close = output_to "src/guestfs-actions.c" in
10392   generate_client_actions ();
10393   close ();
10394
10395   let close = output_to "daemon/actions.h" in
10396   generate_daemon_actions_h ();
10397   close ();
10398
10399   let close = output_to "daemon/stubs.c" in
10400   generate_daemon_actions ();
10401   close ();
10402
10403   let close = output_to "daemon/names.c" in
10404   generate_daemon_names ();
10405   close ();
10406
10407   let close = output_to "daemon/optgroups.c" in
10408   generate_daemon_optgroups_c ();
10409   close ();
10410
10411   let close = output_to "daemon/optgroups.h" in
10412   generate_daemon_optgroups_h ();
10413   close ();
10414
10415   let close = output_to "capitests/tests.c" in
10416   generate_tests ();
10417   close ();
10418
10419   let close = output_to "src/guestfs-bindtests.c" in
10420   generate_bindtests ();
10421   close ();
10422
10423   let close = output_to "fish/cmds.c" in
10424   generate_fish_cmds ();
10425   close ();
10426
10427   let close = output_to "fish/completion.c" in
10428   generate_fish_completion ();
10429   close ();
10430
10431   let close = output_to "guestfs-structs.pod" in
10432   generate_structs_pod ();
10433   close ();
10434
10435   let close = output_to "guestfs-actions.pod" in
10436   generate_actions_pod ();
10437   close ();
10438
10439   let close = output_to "guestfs-availability.pod" in
10440   generate_availability_pod ();
10441   close ();
10442
10443   let close = output_to "guestfish-actions.pod" in
10444   generate_fish_actions_pod ();
10445   close ();
10446
10447   let close = output_to "ocaml/guestfs.mli" in
10448   generate_ocaml_mli ();
10449   close ();
10450
10451   let close = output_to "ocaml/guestfs.ml" in
10452   generate_ocaml_ml ();
10453   close ();
10454
10455   let close = output_to "ocaml/guestfs_c_actions.c" in
10456   generate_ocaml_c ();
10457   close ();
10458
10459   let close = output_to "ocaml/bindtests.ml" in
10460   generate_ocaml_bindtests ();
10461   close ();
10462
10463   let close = output_to "perl/Guestfs.xs" in
10464   generate_perl_xs ();
10465   close ();
10466
10467   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10468   generate_perl_pm ();
10469   close ();
10470
10471   let close = output_to "perl/bindtests.pl" in
10472   generate_perl_bindtests ();
10473   close ();
10474
10475   let close = output_to "python/guestfs-py.c" in
10476   generate_python_c ();
10477   close ();
10478
10479   let close = output_to "python/guestfs.py" in
10480   generate_python_py ();
10481   close ();
10482
10483   let close = output_to "python/bindtests.py" in
10484   generate_python_bindtests ();
10485   close ();
10486
10487   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10488   generate_ruby_c ();
10489   close ();
10490
10491   let close = output_to "ruby/bindtests.rb" in
10492   generate_ruby_bindtests ();
10493   close ();
10494
10495   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10496   generate_java_java ();
10497   close ();
10498
10499   List.iter (
10500     fun (typ, jtyp) ->
10501       let cols = cols_of_struct typ in
10502       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10503       let close = output_to filename in
10504       generate_java_struct jtyp cols;
10505       close ();
10506   ) java_structs;
10507
10508   let close = output_to "java/Makefile.inc" in
10509   generate_java_makefile_inc ();
10510   close ();
10511
10512   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10513   generate_java_c ();
10514   close ();
10515
10516   let close = output_to "java/Bindtests.java" in
10517   generate_java_bindtests ();
10518   close ();
10519
10520   let close = output_to "haskell/Guestfs.hs" in
10521   generate_haskell_hs ();
10522   close ();
10523
10524   let close = output_to "haskell/Bindtests.hs" in
10525   generate_haskell_bindtests ();
10526   close ();
10527
10528   let close = output_to "src/MAX_PROC_NR" in
10529   generate_max_proc_nr ();
10530   close ();
10531
10532   (* Always generate this file last, and unconditionally.  It's used
10533    * by the Makefile to know when we must re-run the generator.
10534    *)
10535   let chan = open_out "src/stamp-generator" in
10536   fprintf chan "1\n";
10537   close_out chan