Implement 'dd' command.
[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, arg | DeviceList n, arg ->
6648             let strs = string_split " " arg in
6649             iteri (
6650               fun i str ->
6651                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6652             ) strs;
6653             pr "    const char *const %s[] = {\n" n;
6654             iteri (
6655               fun i _ -> pr "      %s_%d,\n" n i
6656             ) strs;
6657             pr "      NULL\n";
6658             pr "    };\n";
6659       ) (List.combine (snd style) args);
6660
6661       let error_code =
6662         match fst style with
6663         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6664         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6665         | RConstString _ | RConstOptString _ ->
6666             pr "    const char *r;\n"; "NULL"
6667         | RString _ -> pr "    char *r;\n"; "NULL"
6668         | RStringList _ | RHashtable _ ->
6669             pr "    char **r;\n";
6670             pr "    int i;\n";
6671             "NULL"
6672         | RStruct (_, typ) ->
6673             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6674         | RStructList (_, typ) ->
6675             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6676         | RBufferOut _ ->
6677             pr "    char *r;\n";
6678             pr "    size_t size;\n";
6679             "NULL" in
6680
6681       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6682       pr "    r = guestfs_%s (g" name;
6683
6684       (* Generate the parameters. *)
6685       List.iter (
6686         function
6687         | OptString _, "NULL" -> pr ", NULL"
6688         | Pathname n, _
6689         | Device n, _ | Dev_or_Path n, _
6690         | String n, _
6691         | OptString n, _ ->
6692             pr ", %s" n
6693         | FileIn _, arg | FileOut _, arg ->
6694             pr ", \"%s\"" (c_quote arg)
6695         | StringList n, _ | DeviceList n, _ ->
6696             pr ", (char **) %s" n
6697         | Int _, arg ->
6698             let i =
6699               try int_of_string arg
6700               with Failure "int_of_string" ->
6701                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6702             pr ", %d" i
6703         | Int64 _, arg ->
6704             let i =
6705               try Int64.of_string arg
6706               with Failure "int_of_string" ->
6707                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6708             pr ", %Ld" i
6709         | Bool _, arg ->
6710             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6711       ) (List.combine (snd style) args);
6712
6713       (match fst style with
6714        | RBufferOut _ -> pr ", &size"
6715        | _ -> ()
6716       );
6717
6718       pr ");\n";
6719
6720       if not expect_error then
6721         pr "    if (r == %s)\n" error_code
6722       else
6723         pr "    if (r != %s)\n" error_code;
6724       pr "      return -1;\n";
6725
6726       (* Insert the test code. *)
6727       (match test with
6728        | None -> ()
6729        | Some f -> f ()
6730       );
6731
6732       (match fst style with
6733        | RErr | RInt _ | RInt64 _ | RBool _
6734        | RConstString _ | RConstOptString _ -> ()
6735        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6736        | RStringList _ | RHashtable _ ->
6737            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6738            pr "      free (r[i]);\n";
6739            pr "    free (r);\n"
6740        | RStruct (_, typ) ->
6741            pr "    guestfs_free_%s (r);\n" typ
6742        | RStructList (_, typ) ->
6743            pr "    guestfs_free_%s_list (r);\n" typ
6744       );
6745
6746       pr "  }\n"
6747
6748 and c_quote str =
6749   let str = replace_str str "\r" "\\r" in
6750   let str = replace_str str "\n" "\\n" in
6751   let str = replace_str str "\t" "\\t" in
6752   let str = replace_str str "\000" "\\0" in
6753   str
6754
6755 (* Generate a lot of different functions for guestfish. *)
6756 and generate_fish_cmds () =
6757   generate_header CStyle GPLv2;
6758
6759   let all_functions =
6760     List.filter (
6761       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6762     ) all_functions in
6763   let all_functions_sorted =
6764     List.filter (
6765       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6766     ) all_functions_sorted in
6767
6768   pr "#include <stdio.h>\n";
6769   pr "#include <stdlib.h>\n";
6770   pr "#include <string.h>\n";
6771   pr "#include <inttypes.h>\n";
6772   pr "\n";
6773   pr "#include <guestfs.h>\n";
6774   pr "#include \"c-ctype.h\"\n";
6775   pr "#include \"fish.h\"\n";
6776   pr "\n";
6777
6778   (* list_commands function, which implements guestfish -h *)
6779   pr "void list_commands (void)\n";
6780   pr "{\n";
6781   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6782   pr "  list_builtin_commands ();\n";
6783   List.iter (
6784     fun (name, _, _, flags, _, shortdesc, _) ->
6785       let name = replace_char name '_' '-' in
6786       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6787         name shortdesc
6788   ) all_functions_sorted;
6789   pr "  printf (\"    %%s\\n\",";
6790   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6791   pr "}\n";
6792   pr "\n";
6793
6794   (* display_command function, which implements guestfish -h cmd *)
6795   pr "void display_command (const char *cmd)\n";
6796   pr "{\n";
6797   List.iter (
6798     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6799       let name2 = replace_char name '_' '-' in
6800       let alias =
6801         try find_map (function FishAlias n -> Some n | _ -> None) flags
6802         with Not_found -> name in
6803       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6804       let synopsis =
6805         match snd style with
6806         | [] -> name2
6807         | args ->
6808             sprintf "%s %s"
6809               name2 (String.concat " " (List.map name_of_argt args)) in
6810
6811       let warnings =
6812         if List.mem ProtocolLimitWarning flags then
6813           ("\n\n" ^ protocol_limit_warning)
6814         else "" in
6815
6816       (* For DangerWillRobinson commands, we should probably have
6817        * guestfish prompt before allowing you to use them (especially
6818        * in interactive mode). XXX
6819        *)
6820       let warnings =
6821         warnings ^
6822           if List.mem DangerWillRobinson flags then
6823             ("\n\n" ^ danger_will_robinson)
6824           else "" in
6825
6826       let warnings =
6827         warnings ^
6828           match deprecation_notice flags with
6829           | None -> ""
6830           | Some txt -> "\n\n" ^ txt in
6831
6832       let describe_alias =
6833         if name <> alias then
6834           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6835         else "" in
6836
6837       pr "  if (";
6838       pr "STRCASEEQ (cmd, \"%s\")" name;
6839       if name <> name2 then
6840         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6841       if name <> alias then
6842         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6843       pr ")\n";
6844       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6845         name2 shortdesc
6846         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6847          "=head1 DESCRIPTION\n\n" ^
6848          longdesc ^ warnings ^ describe_alias);
6849       pr "  else\n"
6850   ) all_functions;
6851   pr "    display_builtin_command (cmd);\n";
6852   pr "}\n";
6853   pr "\n";
6854
6855   let emit_print_list_function typ =
6856     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6857       typ typ typ;
6858     pr "{\n";
6859     pr "  unsigned int i;\n";
6860     pr "\n";
6861     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6862     pr "    printf (\"[%%d] = {\\n\", i);\n";
6863     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6864     pr "    printf (\"}\\n\");\n";
6865     pr "  }\n";
6866     pr "}\n";
6867     pr "\n";
6868   in
6869
6870   (* print_* functions *)
6871   List.iter (
6872     fun (typ, cols) ->
6873       let needs_i =
6874         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6875
6876       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6877       pr "{\n";
6878       if needs_i then (
6879         pr "  unsigned int i;\n";
6880         pr "\n"
6881       );
6882       List.iter (
6883         function
6884         | name, FString ->
6885             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6886         | name, FUUID ->
6887             pr "  printf (\"%%s%s: \", indent);\n" name;
6888             pr "  for (i = 0; i < 32; ++i)\n";
6889             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6890             pr "  printf (\"\\n\");\n"
6891         | name, FBuffer ->
6892             pr "  printf (\"%%s%s: \", indent);\n" name;
6893             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6894             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6895             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6896             pr "    else\n";
6897             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6898             pr "  printf (\"\\n\");\n"
6899         | name, (FUInt64|FBytes) ->
6900             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6901               name typ name
6902         | name, FInt64 ->
6903             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6904               name typ name
6905         | name, FUInt32 ->
6906             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6907               name typ name
6908         | name, FInt32 ->
6909             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6910               name typ name
6911         | name, FChar ->
6912             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6913               name typ name
6914         | name, FOptPercent ->
6915             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6916               typ name name typ name;
6917             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6918       ) cols;
6919       pr "}\n";
6920       pr "\n";
6921   ) structs;
6922
6923   (* Emit a print_TYPE_list function definition only if that function is used. *)
6924   List.iter (
6925     function
6926     | typ, (RStructListOnly | RStructAndList) ->
6927         (* generate the function for typ *)
6928         emit_print_list_function typ
6929     | typ, _ -> () (* empty *)
6930   ) (rstructs_used_by all_functions);
6931
6932   (* Emit a print_TYPE function definition only if that function is used. *)
6933   List.iter (
6934     function
6935     | typ, (RStructOnly | RStructAndList) ->
6936         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6937         pr "{\n";
6938         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6939         pr "}\n";
6940         pr "\n";
6941     | typ, _ -> () (* empty *)
6942   ) (rstructs_used_by all_functions);
6943
6944   (* run_<action> actions *)
6945   List.iter (
6946     fun (name, style, _, flags, _, _, _) ->
6947       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6948       pr "{\n";
6949       (match fst style with
6950        | RErr
6951        | RInt _
6952        | RBool _ -> pr "  int r;\n"
6953        | RInt64 _ -> pr "  int64_t r;\n"
6954        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6955        | RString _ -> pr "  char *r;\n"
6956        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6957        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6958        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6959        | RBufferOut _ ->
6960            pr "  char *r;\n";
6961            pr "  size_t size;\n";
6962       );
6963       List.iter (
6964         function
6965         | Device n
6966         | String n
6967         | OptString n
6968         | FileIn n
6969         | FileOut n -> pr "  const char *%s;\n" n
6970         | Pathname n
6971         | Dev_or_Path n -> pr "  char *%s;\n" n
6972         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6973         | Bool n -> pr "  int %s;\n" n
6974         | Int n -> pr "  int %s;\n" n
6975         | Int64 n -> pr "  int64_t %s;\n" n
6976       ) (snd style);
6977
6978       (* Check and convert parameters. *)
6979       let argc_expected = List.length (snd style) in
6980       pr "  if (argc != %d) {\n" argc_expected;
6981       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6982         argc_expected;
6983       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6984       pr "    return -1;\n";
6985       pr "  }\n";
6986       iteri (
6987         fun i ->
6988           function
6989           | Device name
6990           | String name ->
6991               pr "  %s = argv[%d];\n" name i
6992           | Pathname name
6993           | Dev_or_Path name ->
6994               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6995               pr "  if (%s == NULL) return -1;\n" name
6996           | OptString name ->
6997               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6998                 name i i
6999           | FileIn name ->
7000               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7001                 name i i
7002           | FileOut name ->
7003               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7004                 name i i
7005           | StringList name | DeviceList name ->
7006               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7007               pr "  if (%s == NULL) return -1;\n" name;
7008           | Bool name ->
7009               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7010           | Int name ->
7011               pr "  %s = atoi (argv[%d]);\n" name i
7012           | Int64 name ->
7013               pr "  %s = atoll (argv[%d]);\n" name i
7014       ) (snd style);
7015
7016       (* Call C API function. *)
7017       let fn =
7018         try find_map (function FishAction n -> Some n | _ -> None) flags
7019         with Not_found -> sprintf "guestfs_%s" name in
7020       pr "  r = %s " fn;
7021       generate_c_call_args ~handle:"g" style;
7022       pr ";\n";
7023
7024       List.iter (
7025         function
7026         | Device name | String name
7027         | OptString name | FileIn name | FileOut name | Bool name
7028         | Int name | Int64 name -> ()
7029         | Pathname name | Dev_or_Path name ->
7030             pr "  free (%s);\n" name
7031         | StringList name | DeviceList name ->
7032             pr "  free_strings (%s);\n" name
7033       ) (snd style);
7034
7035       (* Check return value for errors and display command results. *)
7036       (match fst style with
7037        | RErr -> pr "  return r;\n"
7038        | RInt _ ->
7039            pr "  if (r == -1) return -1;\n";
7040            pr "  printf (\"%%d\\n\", r);\n";
7041            pr "  return 0;\n"
7042        | RInt64 _ ->
7043            pr "  if (r == -1) return -1;\n";
7044            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7045            pr "  return 0;\n"
7046        | RBool _ ->
7047            pr "  if (r == -1) return -1;\n";
7048            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7049            pr "  return 0;\n"
7050        | RConstString _ ->
7051            pr "  if (r == NULL) return -1;\n";
7052            pr "  printf (\"%%s\\n\", r);\n";
7053            pr "  return 0;\n"
7054        | RConstOptString _ ->
7055            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7056            pr "  return 0;\n"
7057        | RString _ ->
7058            pr "  if (r == NULL) return -1;\n";
7059            pr "  printf (\"%%s\\n\", r);\n";
7060            pr "  free (r);\n";
7061            pr "  return 0;\n"
7062        | RStringList _ ->
7063            pr "  if (r == NULL) return -1;\n";
7064            pr "  print_strings (r);\n";
7065            pr "  free_strings (r);\n";
7066            pr "  return 0;\n"
7067        | RStruct (_, typ) ->
7068            pr "  if (r == NULL) return -1;\n";
7069            pr "  print_%s (r);\n" typ;
7070            pr "  guestfs_free_%s (r);\n" typ;
7071            pr "  return 0;\n"
7072        | RStructList (_, typ) ->
7073            pr "  if (r == NULL) return -1;\n";
7074            pr "  print_%s_list (r);\n" typ;
7075            pr "  guestfs_free_%s_list (r);\n" typ;
7076            pr "  return 0;\n"
7077        | RHashtable _ ->
7078            pr "  if (r == NULL) return -1;\n";
7079            pr "  print_table (r);\n";
7080            pr "  free_strings (r);\n";
7081            pr "  return 0;\n"
7082        | RBufferOut _ ->
7083            pr "  if (r == NULL) return -1;\n";
7084            pr "  fwrite (r, size, 1, stdout);\n";
7085            pr "  free (r);\n";
7086            pr "  return 0;\n"
7087       );
7088       pr "}\n";
7089       pr "\n"
7090   ) all_functions;
7091
7092   (* run_action function *)
7093   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7094   pr "{\n";
7095   List.iter (
7096     fun (name, _, _, flags, _, _, _) ->
7097       let name2 = replace_char name '_' '-' in
7098       let alias =
7099         try find_map (function FishAlias n -> Some n | _ -> None) flags
7100         with Not_found -> name in
7101       pr "  if (";
7102       pr "STRCASEEQ (cmd, \"%s\")" name;
7103       if name <> name2 then
7104         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7105       if name <> alias then
7106         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7107       pr ")\n";
7108       pr "    return run_%s (cmd, argc, argv);\n" name;
7109       pr "  else\n";
7110   ) all_functions;
7111   pr "    {\n";
7112   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7113   pr "      return -1;\n";
7114   pr "    }\n";
7115   pr "  return 0;\n";
7116   pr "}\n";
7117   pr "\n"
7118
7119 (* Readline completion for guestfish. *)
7120 and generate_fish_completion () =
7121   generate_header CStyle GPLv2;
7122
7123   let all_functions =
7124     List.filter (
7125       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7126     ) all_functions in
7127
7128   pr "\
7129 #include <config.h>
7130
7131 #include <stdio.h>
7132 #include <stdlib.h>
7133 #include <string.h>
7134
7135 #ifdef HAVE_LIBREADLINE
7136 #include <readline/readline.h>
7137 #endif
7138
7139 #include \"fish.h\"
7140
7141 #ifdef HAVE_LIBREADLINE
7142
7143 static const char *const commands[] = {
7144   BUILTIN_COMMANDS_FOR_COMPLETION,
7145 ";
7146
7147   (* Get the commands, including the aliases.  They don't need to be
7148    * sorted - the generator() function just does a dumb linear search.
7149    *)
7150   let commands =
7151     List.map (
7152       fun (name, _, _, flags, _, _, _) ->
7153         let name2 = replace_char name '_' '-' in
7154         let alias =
7155           try find_map (function FishAlias n -> Some n | _ -> None) flags
7156           with Not_found -> name in
7157
7158         if name <> alias then [name2; alias] else [name2]
7159     ) all_functions in
7160   let commands = List.flatten commands in
7161
7162   List.iter (pr "  \"%s\",\n") commands;
7163
7164   pr "  NULL
7165 };
7166
7167 static char *
7168 generator (const char *text, int state)
7169 {
7170   static int index, len;
7171   const char *name;
7172
7173   if (!state) {
7174     index = 0;
7175     len = strlen (text);
7176   }
7177
7178   rl_attempted_completion_over = 1;
7179
7180   while ((name = commands[index]) != NULL) {
7181     index++;
7182     if (STRCASEEQLEN (name, text, len))
7183       return strdup (name);
7184   }
7185
7186   return NULL;
7187 }
7188
7189 #endif /* HAVE_LIBREADLINE */
7190
7191 char **do_completion (const char *text, int start, int end)
7192 {
7193   char **matches = NULL;
7194
7195 #ifdef HAVE_LIBREADLINE
7196   rl_completion_append_character = ' ';
7197
7198   if (start == 0)
7199     matches = rl_completion_matches (text, generator);
7200   else if (complete_dest_paths)
7201     matches = rl_completion_matches (text, complete_dest_paths_generator);
7202 #endif
7203
7204   return matches;
7205 }
7206 ";
7207
7208 (* Generate the POD documentation for guestfish. *)
7209 and generate_fish_actions_pod () =
7210   let all_functions_sorted =
7211     List.filter (
7212       fun (_, _, _, flags, _, _, _) ->
7213         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7214     ) all_functions_sorted in
7215
7216   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7217
7218   List.iter (
7219     fun (name, style, _, flags, _, _, longdesc) ->
7220       let longdesc =
7221         Str.global_substitute rex (
7222           fun s ->
7223             let sub =
7224               try Str.matched_group 1 s
7225               with Not_found ->
7226                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7227             "C<" ^ replace_char sub '_' '-' ^ ">"
7228         ) longdesc in
7229       let name = replace_char name '_' '-' in
7230       let alias =
7231         try find_map (function FishAlias n -> Some n | _ -> None) flags
7232         with Not_found -> name in
7233
7234       pr "=head2 %s" name;
7235       if name <> alias then
7236         pr " | %s" alias;
7237       pr "\n";
7238       pr "\n";
7239       pr " %s" name;
7240       List.iter (
7241         function
7242         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7243         | OptString n -> pr " %s" n
7244         | StringList n | DeviceList n -> pr " '%s ...'" n
7245         | Bool _ -> pr " true|false"
7246         | Int n -> pr " %s" n
7247         | Int64 n -> pr " %s" n
7248         | FileIn n | FileOut n -> pr " (%s|-)" n
7249       ) (snd style);
7250       pr "\n";
7251       pr "\n";
7252       pr "%s\n\n" longdesc;
7253
7254       if List.exists (function FileIn _ | FileOut _ -> true
7255                       | _ -> false) (snd style) then
7256         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7257
7258       if List.mem ProtocolLimitWarning flags then
7259         pr "%s\n\n" protocol_limit_warning;
7260
7261       if List.mem DangerWillRobinson flags then
7262         pr "%s\n\n" danger_will_robinson;
7263
7264       match deprecation_notice flags with
7265       | None -> ()
7266       | Some txt -> pr "%s\n\n" txt
7267   ) all_functions_sorted
7268
7269 (* Generate a C function prototype. *)
7270 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7271     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7272     ?(prefix = "")
7273     ?handle name style =
7274   if extern then pr "extern ";
7275   if static then pr "static ";
7276   (match fst style with
7277    | RErr -> pr "int "
7278    | RInt _ -> pr "int "
7279    | RInt64 _ -> pr "int64_t "
7280    | RBool _ -> pr "int "
7281    | RConstString _ | RConstOptString _ -> pr "const char *"
7282    | RString _ | RBufferOut _ -> pr "char *"
7283    | RStringList _ | RHashtable _ -> pr "char **"
7284    | RStruct (_, typ) ->
7285        if not in_daemon then pr "struct guestfs_%s *" typ
7286        else pr "guestfs_int_%s *" typ
7287    | RStructList (_, typ) ->
7288        if not in_daemon then pr "struct guestfs_%s_list *" typ
7289        else pr "guestfs_int_%s_list *" typ
7290   );
7291   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7292   pr "%s%s (" prefix name;
7293   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7294     pr "void"
7295   else (
7296     let comma = ref false in
7297     (match handle with
7298      | None -> ()
7299      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7300     );
7301     let next () =
7302       if !comma then (
7303         if single_line then pr ", " else pr ",\n\t\t"
7304       );
7305       comma := true
7306     in
7307     List.iter (
7308       function
7309       | Pathname n
7310       | Device n | Dev_or_Path n
7311       | String n
7312       | OptString n ->
7313           next ();
7314           pr "const char *%s" n
7315       | StringList n | DeviceList n ->
7316           next ();
7317           pr "char *const *%s" n
7318       | Bool n -> next (); pr "int %s" n
7319       | Int n -> next (); pr "int %s" n
7320       | Int64 n -> next (); pr "int64_t %s" n
7321       | FileIn n
7322       | FileOut n ->
7323           if not in_daemon then (next (); pr "const char *%s" n)
7324     ) (snd style);
7325     if is_RBufferOut then (next (); pr "size_t *size_r");
7326   );
7327   pr ")";
7328   if semicolon then pr ";";
7329   if newline then pr "\n"
7330
7331 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7332 and generate_c_call_args ?handle ?(decl = false) style =
7333   pr "(";
7334   let comma = ref false in
7335   let next () =
7336     if !comma then pr ", ";
7337     comma := true
7338   in
7339   (match handle with
7340    | None -> ()
7341    | Some handle -> pr "%s" handle; comma := true
7342   );
7343   List.iter (
7344     fun arg ->
7345       next ();
7346       pr "%s" (name_of_argt arg)
7347   ) (snd style);
7348   (* For RBufferOut calls, add implicit &size parameter. *)
7349   if not decl then (
7350     match fst style with
7351     | RBufferOut _ ->
7352         next ();
7353         pr "&size"
7354     | _ -> ()
7355   );
7356   pr ")"
7357
7358 (* Generate the OCaml bindings interface. *)
7359 and generate_ocaml_mli () =
7360   generate_header OCamlStyle LGPLv2;
7361
7362   pr "\
7363 (** For API documentation you should refer to the C API
7364     in the guestfs(3) manual page.  The OCaml API uses almost
7365     exactly the same calls. *)
7366
7367 type t
7368 (** A [guestfs_h] handle. *)
7369
7370 exception Error of string
7371 (** This exception is raised when there is an error. *)
7372
7373 exception Handle_closed of string
7374 (** This exception is raised if you use a {!Guestfs.t} handle
7375     after calling {!close} on it.  The string is the name of
7376     the function. *)
7377
7378 val create : unit -> t
7379 (** Create a {!Guestfs.t} handle. *)
7380
7381 val close : t -> unit
7382 (** Close the {!Guestfs.t} handle and free up all resources used
7383     by it immediately.
7384
7385     Handles are closed by the garbage collector when they become
7386     unreferenced, but callers can call this in order to provide
7387     predictable cleanup. *)
7388
7389 ";
7390   generate_ocaml_structure_decls ();
7391
7392   (* The actions. *)
7393   List.iter (
7394     fun (name, style, _, _, _, shortdesc, _) ->
7395       generate_ocaml_prototype name style;
7396       pr "(** %s *)\n" shortdesc;
7397       pr "\n"
7398   ) all_functions_sorted
7399
7400 (* Generate the OCaml bindings implementation. *)
7401 and generate_ocaml_ml () =
7402   generate_header OCamlStyle LGPLv2;
7403
7404   pr "\
7405 type t
7406
7407 exception Error of string
7408 exception Handle_closed of string
7409
7410 external create : unit -> t = \"ocaml_guestfs_create\"
7411 external close : t -> unit = \"ocaml_guestfs_close\"
7412
7413 (* Give the exceptions names, so they can be raised from the C code. *)
7414 let () =
7415   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7416   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7417
7418 ";
7419
7420   generate_ocaml_structure_decls ();
7421
7422   (* The actions. *)
7423   List.iter (
7424     fun (name, style, _, _, _, shortdesc, _) ->
7425       generate_ocaml_prototype ~is_external:true name style;
7426   ) all_functions_sorted
7427
7428 (* Generate the OCaml bindings C implementation. *)
7429 and generate_ocaml_c () =
7430   generate_header CStyle LGPLv2;
7431
7432   pr "\
7433 #include <stdio.h>
7434 #include <stdlib.h>
7435 #include <string.h>
7436
7437 #include <caml/config.h>
7438 #include <caml/alloc.h>
7439 #include <caml/callback.h>
7440 #include <caml/fail.h>
7441 #include <caml/memory.h>
7442 #include <caml/mlvalues.h>
7443 #include <caml/signals.h>
7444
7445 #include <guestfs.h>
7446
7447 #include \"guestfs_c.h\"
7448
7449 /* Copy a hashtable of string pairs into an assoc-list.  We return
7450  * the list in reverse order, but hashtables aren't supposed to be
7451  * ordered anyway.
7452  */
7453 static CAMLprim value
7454 copy_table (char * const * argv)
7455 {
7456   CAMLparam0 ();
7457   CAMLlocal5 (rv, pairv, kv, vv, cons);
7458   int i;
7459
7460   rv = Val_int (0);
7461   for (i = 0; argv[i] != NULL; i += 2) {
7462     kv = caml_copy_string (argv[i]);
7463     vv = caml_copy_string (argv[i+1]);
7464     pairv = caml_alloc (2, 0);
7465     Store_field (pairv, 0, kv);
7466     Store_field (pairv, 1, vv);
7467     cons = caml_alloc (2, 0);
7468     Store_field (cons, 1, rv);
7469     rv = cons;
7470     Store_field (cons, 0, pairv);
7471   }
7472
7473   CAMLreturn (rv);
7474 }
7475
7476 ";
7477
7478   (* Struct copy functions. *)
7479
7480   let emit_ocaml_copy_list_function typ =
7481     pr "static CAMLprim value\n";
7482     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7483     pr "{\n";
7484     pr "  CAMLparam0 ();\n";
7485     pr "  CAMLlocal2 (rv, v);\n";
7486     pr "  unsigned int i;\n";
7487     pr "\n";
7488     pr "  if (%ss->len == 0)\n" typ;
7489     pr "    CAMLreturn (Atom (0));\n";
7490     pr "  else {\n";
7491     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7492     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7493     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7494     pr "      caml_modify (&Field (rv, i), v);\n";
7495     pr "    }\n";
7496     pr "    CAMLreturn (rv);\n";
7497     pr "  }\n";
7498     pr "}\n";
7499     pr "\n";
7500   in
7501
7502   List.iter (
7503     fun (typ, cols) ->
7504       let has_optpercent_col =
7505         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7506
7507       pr "static CAMLprim value\n";
7508       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7509       pr "{\n";
7510       pr "  CAMLparam0 ();\n";
7511       if has_optpercent_col then
7512         pr "  CAMLlocal3 (rv, v, v2);\n"
7513       else
7514         pr "  CAMLlocal2 (rv, v);\n";
7515       pr "\n";
7516       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7517       iteri (
7518         fun i col ->
7519           (match col with
7520            | name, FString ->
7521                pr "  v = caml_copy_string (%s->%s);\n" typ name
7522            | name, FBuffer ->
7523                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7524                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7525                  typ name typ name
7526            | name, FUUID ->
7527                pr "  v = caml_alloc_string (32);\n";
7528                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7529            | name, (FBytes|FInt64|FUInt64) ->
7530                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7531            | name, (FInt32|FUInt32) ->
7532                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7533            | name, FOptPercent ->
7534                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7535                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7536                pr "    v = caml_alloc (1, 0);\n";
7537                pr "    Store_field (v, 0, v2);\n";
7538                pr "  } else /* None */\n";
7539                pr "    v = Val_int (0);\n";
7540            | name, FChar ->
7541                pr "  v = Val_int (%s->%s);\n" typ name
7542           );
7543           pr "  Store_field (rv, %d, v);\n" i
7544       ) cols;
7545       pr "  CAMLreturn (rv);\n";
7546       pr "}\n";
7547       pr "\n";
7548   ) structs;
7549
7550   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7551   List.iter (
7552     function
7553     | typ, (RStructListOnly | RStructAndList) ->
7554         (* generate the function for typ *)
7555         emit_ocaml_copy_list_function typ
7556     | typ, _ -> () (* empty *)
7557   ) (rstructs_used_by all_functions);
7558
7559   (* The wrappers. *)
7560   List.iter (
7561     fun (name, style, _, _, _, _, _) ->
7562       pr "/* Automatically generated wrapper for function\n";
7563       pr " * ";
7564       generate_ocaml_prototype name style;
7565       pr " */\n";
7566       pr "\n";
7567
7568       let params =
7569         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7570
7571       let needs_extra_vs =
7572         match fst style with RConstOptString _ -> true | _ -> false in
7573
7574       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7575       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7576       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7577       pr "\n";
7578
7579       pr "CAMLprim value\n";
7580       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7581       List.iter (pr ", value %s") (List.tl params);
7582       pr ")\n";
7583       pr "{\n";
7584
7585       (match params with
7586        | [p1; p2; p3; p4; p5] ->
7587            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7588        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7589            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7590            pr "  CAMLxparam%d (%s);\n"
7591              (List.length rest) (String.concat ", " rest)
7592        | ps ->
7593            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7594       );
7595       if not needs_extra_vs then
7596         pr "  CAMLlocal1 (rv);\n"
7597       else
7598         pr "  CAMLlocal3 (rv, v, v2);\n";
7599       pr "\n";
7600
7601       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7602       pr "  if (g == NULL)\n";
7603       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7604       pr "\n";
7605
7606       List.iter (
7607         function
7608         | Pathname n
7609         | Device n | Dev_or_Path n
7610         | String n
7611         | FileIn n
7612         | FileOut n ->
7613             pr "  const char *%s = String_val (%sv);\n" n n
7614         | OptString n ->
7615             pr "  const char *%s =\n" n;
7616             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7617               n n
7618         | StringList n | DeviceList n ->
7619             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7620         | Bool n ->
7621             pr "  int %s = Bool_val (%sv);\n" n n
7622         | Int n ->
7623             pr "  int %s = Int_val (%sv);\n" n n
7624         | Int64 n ->
7625             pr "  int64_t %s = Int64_val (%sv);\n" n n
7626       ) (snd style);
7627       let error_code =
7628         match fst style with
7629         | RErr -> pr "  int r;\n"; "-1"
7630         | RInt _ -> pr "  int r;\n"; "-1"
7631         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7632         | RBool _ -> pr "  int r;\n"; "-1"
7633         | RConstString _ | RConstOptString _ ->
7634             pr "  const char *r;\n"; "NULL"
7635         | RString _ -> pr "  char *r;\n"; "NULL"
7636         | RStringList _ ->
7637             pr "  int i;\n";
7638             pr "  char **r;\n";
7639             "NULL"
7640         | RStruct (_, typ) ->
7641             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7642         | RStructList (_, typ) ->
7643             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7644         | RHashtable _ ->
7645             pr "  int i;\n";
7646             pr "  char **r;\n";
7647             "NULL"
7648         | RBufferOut _ ->
7649             pr "  char *r;\n";
7650             pr "  size_t size;\n";
7651             "NULL" in
7652       pr "\n";
7653
7654       pr "  caml_enter_blocking_section ();\n";
7655       pr "  r = guestfs_%s " name;
7656       generate_c_call_args ~handle:"g" style;
7657       pr ";\n";
7658       pr "  caml_leave_blocking_section ();\n";
7659
7660       List.iter (
7661         function
7662         | StringList n | DeviceList n ->
7663             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7664         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7665         | Bool _ | Int _ | Int64 _
7666         | FileIn _ | FileOut _ -> ()
7667       ) (snd style);
7668
7669       pr "  if (r == %s)\n" error_code;
7670       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7671       pr "\n";
7672
7673       (match fst style with
7674        | RErr -> pr "  rv = Val_unit;\n"
7675        | RInt _ -> pr "  rv = Val_int (r);\n"
7676        | RInt64 _ ->
7677            pr "  rv = caml_copy_int64 (r);\n"
7678        | RBool _ -> pr "  rv = Val_bool (r);\n"
7679        | RConstString _ ->
7680            pr "  rv = caml_copy_string (r);\n"
7681        | RConstOptString _ ->
7682            pr "  if (r) { /* Some string */\n";
7683            pr "    v = caml_alloc (1, 0);\n";
7684            pr "    v2 = caml_copy_string (r);\n";
7685            pr "    Store_field (v, 0, v2);\n";
7686            pr "  } else /* None */\n";
7687            pr "    v = Val_int (0);\n";
7688        | RString _ ->
7689            pr "  rv = caml_copy_string (r);\n";
7690            pr "  free (r);\n"
7691        | RStringList _ ->
7692            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7693            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7694            pr "  free (r);\n"
7695        | RStruct (_, typ) ->
7696            pr "  rv = copy_%s (r);\n" typ;
7697            pr "  guestfs_free_%s (r);\n" typ;
7698        | RStructList (_, typ) ->
7699            pr "  rv = copy_%s_list (r);\n" typ;
7700            pr "  guestfs_free_%s_list (r);\n" typ;
7701        | RHashtable _ ->
7702            pr "  rv = copy_table (r);\n";
7703            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7704            pr "  free (r);\n";
7705        | RBufferOut _ ->
7706            pr "  rv = caml_alloc_string (size);\n";
7707            pr "  memcpy (String_val (rv), r, size);\n";
7708       );
7709
7710       pr "  CAMLreturn (rv);\n";
7711       pr "}\n";
7712       pr "\n";
7713
7714       if List.length params > 5 then (
7715         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7716         pr "CAMLprim value ";
7717         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7718         pr "CAMLprim value\n";
7719         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7720         pr "{\n";
7721         pr "  return ocaml_guestfs_%s (argv[0]" name;
7722         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7723         pr ");\n";
7724         pr "}\n";
7725         pr "\n"
7726       )
7727   ) all_functions_sorted
7728
7729 and generate_ocaml_structure_decls () =
7730   List.iter (
7731     fun (typ, cols) ->
7732       pr "type %s = {\n" typ;
7733       List.iter (
7734         function
7735         | name, FString -> pr "  %s : string;\n" name
7736         | name, FBuffer -> pr "  %s : string;\n" name
7737         | name, FUUID -> pr "  %s : string;\n" name
7738         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7739         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7740         | name, FChar -> pr "  %s : char;\n" name
7741         | name, FOptPercent -> pr "  %s : float option;\n" name
7742       ) cols;
7743       pr "}\n";
7744       pr "\n"
7745   ) structs
7746
7747 and generate_ocaml_prototype ?(is_external = false) name style =
7748   if is_external then pr "external " else pr "val ";
7749   pr "%s : t -> " name;
7750   List.iter (
7751     function
7752     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7753     | OptString _ -> pr "string option -> "
7754     | StringList _ | DeviceList _ -> pr "string array -> "
7755     | Bool _ -> pr "bool -> "
7756     | Int _ -> pr "int -> "
7757     | Int64 _ -> pr "int64 -> "
7758   ) (snd style);
7759   (match fst style with
7760    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7761    | RInt _ -> pr "int"
7762    | RInt64 _ -> pr "int64"
7763    | RBool _ -> pr "bool"
7764    | RConstString _ -> pr "string"
7765    | RConstOptString _ -> pr "string option"
7766    | RString _ | RBufferOut _ -> pr "string"
7767    | RStringList _ -> pr "string array"
7768    | RStruct (_, typ) -> pr "%s" typ
7769    | RStructList (_, typ) -> pr "%s array" typ
7770    | RHashtable _ -> pr "(string * string) list"
7771   );
7772   if is_external then (
7773     pr " = ";
7774     if List.length (snd style) + 1 > 5 then
7775       pr "\"ocaml_guestfs_%s_byte\" " name;
7776     pr "\"ocaml_guestfs_%s\"" name
7777   );
7778   pr "\n"
7779
7780 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7781 and generate_perl_xs () =
7782   generate_header CStyle LGPLv2;
7783
7784   pr "\
7785 #include \"EXTERN.h\"
7786 #include \"perl.h\"
7787 #include \"XSUB.h\"
7788
7789 #include <guestfs.h>
7790
7791 #ifndef PRId64
7792 #define PRId64 \"lld\"
7793 #endif
7794
7795 static SV *
7796 my_newSVll(long long val) {
7797 #ifdef USE_64_BIT_ALL
7798   return newSViv(val);
7799 #else
7800   char buf[100];
7801   int len;
7802   len = snprintf(buf, 100, \"%%\" PRId64, val);
7803   return newSVpv(buf, len);
7804 #endif
7805 }
7806
7807 #ifndef PRIu64
7808 #define PRIu64 \"llu\"
7809 #endif
7810
7811 static SV *
7812 my_newSVull(unsigned long long val) {
7813 #ifdef USE_64_BIT_ALL
7814   return newSVuv(val);
7815 #else
7816   char buf[100];
7817   int len;
7818   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7819   return newSVpv(buf, len);
7820 #endif
7821 }
7822
7823 /* http://www.perlmonks.org/?node_id=680842 */
7824 static char **
7825 XS_unpack_charPtrPtr (SV *arg) {
7826   char **ret;
7827   AV *av;
7828   I32 i;
7829
7830   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7831     croak (\"array reference expected\");
7832
7833   av = (AV *)SvRV (arg);
7834   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7835   if (!ret)
7836     croak (\"malloc failed\");
7837
7838   for (i = 0; i <= av_len (av); i++) {
7839     SV **elem = av_fetch (av, i, 0);
7840
7841     if (!elem || !*elem)
7842       croak (\"missing element in list\");
7843
7844     ret[i] = SvPV_nolen (*elem);
7845   }
7846
7847   ret[i] = NULL;
7848
7849   return ret;
7850 }
7851
7852 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7853
7854 PROTOTYPES: ENABLE
7855
7856 guestfs_h *
7857 _create ()
7858    CODE:
7859       RETVAL = guestfs_create ();
7860       if (!RETVAL)
7861         croak (\"could not create guestfs handle\");
7862       guestfs_set_error_handler (RETVAL, NULL, NULL);
7863  OUTPUT:
7864       RETVAL
7865
7866 void
7867 DESTROY (g)
7868       guestfs_h *g;
7869  PPCODE:
7870       guestfs_close (g);
7871
7872 ";
7873
7874   List.iter (
7875     fun (name, style, _, _, _, _, _) ->
7876       (match fst style with
7877        | RErr -> pr "void\n"
7878        | RInt _ -> pr "SV *\n"
7879        | RInt64 _ -> pr "SV *\n"
7880        | RBool _ -> pr "SV *\n"
7881        | RConstString _ -> pr "SV *\n"
7882        | RConstOptString _ -> pr "SV *\n"
7883        | RString _ -> pr "SV *\n"
7884        | RBufferOut _ -> pr "SV *\n"
7885        | RStringList _
7886        | RStruct _ | RStructList _
7887        | RHashtable _ ->
7888            pr "void\n" (* all lists returned implictly on the stack *)
7889       );
7890       (* Call and arguments. *)
7891       pr "%s " name;
7892       generate_c_call_args ~handle:"g" ~decl:true style;
7893       pr "\n";
7894       pr "      guestfs_h *g;\n";
7895       iteri (
7896         fun i ->
7897           function
7898           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7899               pr "      char *%s;\n" n
7900           | OptString n ->
7901               (* http://www.perlmonks.org/?node_id=554277
7902                * Note that the implicit handle argument means we have
7903                * to add 1 to the ST(x) operator.
7904                *)
7905               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7906           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7907           | Bool n -> pr "      int %s;\n" n
7908           | Int n -> pr "      int %s;\n" n
7909           | Int64 n -> pr "      int64_t %s;\n" n
7910       ) (snd style);
7911
7912       let do_cleanups () =
7913         List.iter (
7914           function
7915           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7916           | Bool _ | Int _ | Int64 _
7917           | FileIn _ | FileOut _ -> ()
7918           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7919         ) (snd style)
7920       in
7921
7922       (* Code. *)
7923       (match fst style with
7924        | RErr ->
7925            pr "PREINIT:\n";
7926            pr "      int r;\n";
7927            pr " PPCODE:\n";
7928            pr "      r = guestfs_%s " name;
7929            generate_c_call_args ~handle:"g" style;
7930            pr ";\n";
7931            do_cleanups ();
7932            pr "      if (r == -1)\n";
7933            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7934        | RInt n
7935        | RBool n ->
7936            pr "PREINIT:\n";
7937            pr "      int %s;\n" n;
7938            pr "   CODE:\n";
7939            pr "      %s = guestfs_%s " n name;
7940            generate_c_call_args ~handle:"g" style;
7941            pr ";\n";
7942            do_cleanups ();
7943            pr "      if (%s == -1)\n" n;
7944            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7945            pr "      RETVAL = newSViv (%s);\n" n;
7946            pr " OUTPUT:\n";
7947            pr "      RETVAL\n"
7948        | RInt64 n ->
7949            pr "PREINIT:\n";
7950            pr "      int64_t %s;\n" n;
7951            pr "   CODE:\n";
7952            pr "      %s = guestfs_%s " n name;
7953            generate_c_call_args ~handle:"g" style;
7954            pr ";\n";
7955            do_cleanups ();
7956            pr "      if (%s == -1)\n" n;
7957            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7958            pr "      RETVAL = my_newSVll (%s);\n" n;
7959            pr " OUTPUT:\n";
7960            pr "      RETVAL\n"
7961        | RConstString n ->
7962            pr "PREINIT:\n";
7963            pr "      const char *%s;\n" n;
7964            pr "   CODE:\n";
7965            pr "      %s = guestfs_%s " n name;
7966            generate_c_call_args ~handle:"g" style;
7967            pr ";\n";
7968            do_cleanups ();
7969            pr "      if (%s == NULL)\n" n;
7970            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7971            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7972            pr " OUTPUT:\n";
7973            pr "      RETVAL\n"
7974        | RConstOptString n ->
7975            pr "PREINIT:\n";
7976            pr "      const char *%s;\n" n;
7977            pr "   CODE:\n";
7978            pr "      %s = guestfs_%s " n name;
7979            generate_c_call_args ~handle:"g" style;
7980            pr ";\n";
7981            do_cleanups ();
7982            pr "      if (%s == NULL)\n" n;
7983            pr "        RETVAL = &PL_sv_undef;\n";
7984            pr "      else\n";
7985            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7986            pr " OUTPUT:\n";
7987            pr "      RETVAL\n"
7988        | RString n ->
7989            pr "PREINIT:\n";
7990            pr "      char *%s;\n" n;
7991            pr "   CODE:\n";
7992            pr "      %s = guestfs_%s " n name;
7993            generate_c_call_args ~handle:"g" style;
7994            pr ";\n";
7995            do_cleanups ();
7996            pr "      if (%s == NULL)\n" n;
7997            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7998            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7999            pr "      free (%s);\n" n;
8000            pr " OUTPUT:\n";
8001            pr "      RETVAL\n"
8002        | RStringList n | RHashtable n ->
8003            pr "PREINIT:\n";
8004            pr "      char **%s;\n" n;
8005            pr "      int i, n;\n";
8006            pr " PPCODE:\n";
8007            pr "      %s = guestfs_%s " n name;
8008            generate_c_call_args ~handle:"g" style;
8009            pr ";\n";
8010            do_cleanups ();
8011            pr "      if (%s == NULL)\n" n;
8012            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8013            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8014            pr "      EXTEND (SP, n);\n";
8015            pr "      for (i = 0; i < n; ++i) {\n";
8016            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8017            pr "        free (%s[i]);\n" n;
8018            pr "      }\n";
8019            pr "      free (%s);\n" n;
8020        | RStruct (n, typ) ->
8021            let cols = cols_of_struct typ in
8022            generate_perl_struct_code typ cols name style n do_cleanups
8023        | RStructList (n, typ) ->
8024            let cols = cols_of_struct typ in
8025            generate_perl_struct_list_code typ cols name style n do_cleanups
8026        | RBufferOut n ->
8027            pr "PREINIT:\n";
8028            pr "      char *%s;\n" n;
8029            pr "      size_t size;\n";
8030            pr "   CODE:\n";
8031            pr "      %s = guestfs_%s " n name;
8032            generate_c_call_args ~handle:"g" style;
8033            pr ";\n";
8034            do_cleanups ();
8035            pr "      if (%s == NULL)\n" n;
8036            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8037            pr "      RETVAL = newSVpv (%s, size);\n" n;
8038            pr "      free (%s);\n" n;
8039            pr " OUTPUT:\n";
8040            pr "      RETVAL\n"
8041       );
8042
8043       pr "\n"
8044   ) all_functions
8045
8046 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8047   pr "PREINIT:\n";
8048   pr "      struct guestfs_%s_list *%s;\n" typ n;
8049   pr "      int i;\n";
8050   pr "      HV *hv;\n";
8051   pr " PPCODE:\n";
8052   pr "      %s = guestfs_%s " n name;
8053   generate_c_call_args ~handle:"g" style;
8054   pr ";\n";
8055   do_cleanups ();
8056   pr "      if (%s == NULL)\n" n;
8057   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8058   pr "      EXTEND (SP, %s->len);\n" n;
8059   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8060   pr "        hv = newHV ();\n";
8061   List.iter (
8062     function
8063     | name, FString ->
8064         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8065           name (String.length name) n name
8066     | name, FUUID ->
8067         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8068           name (String.length name) n name
8069     | name, FBuffer ->
8070         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8071           name (String.length name) n name n name
8072     | name, (FBytes|FUInt64) ->
8073         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8074           name (String.length name) n name
8075     | name, FInt64 ->
8076         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8077           name (String.length name) n name
8078     | name, (FInt32|FUInt32) ->
8079         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8080           name (String.length name) n name
8081     | name, FChar ->
8082         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8083           name (String.length name) n name
8084     | name, FOptPercent ->
8085         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8086           name (String.length name) n name
8087   ) cols;
8088   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8089   pr "      }\n";
8090   pr "      guestfs_free_%s_list (%s);\n" typ n
8091
8092 and generate_perl_struct_code typ cols name style n do_cleanups =
8093   pr "PREINIT:\n";
8094   pr "      struct guestfs_%s *%s;\n" typ n;
8095   pr " PPCODE:\n";
8096   pr "      %s = guestfs_%s " n name;
8097   generate_c_call_args ~handle:"g" style;
8098   pr ";\n";
8099   do_cleanups ();
8100   pr "      if (%s == NULL)\n" n;
8101   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8102   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8103   List.iter (
8104     fun ((name, _) as col) ->
8105       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8106
8107       match col with
8108       | name, FString ->
8109           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8110             n name
8111       | name, FBuffer ->
8112           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8113             n name n name
8114       | name, FUUID ->
8115           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8116             n name
8117       | name, (FBytes|FUInt64) ->
8118           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8119             n name
8120       | name, FInt64 ->
8121           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8122             n name
8123       | name, (FInt32|FUInt32) ->
8124           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8125             n name
8126       | name, FChar ->
8127           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8128             n name
8129       | name, FOptPercent ->
8130           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8131             n name
8132   ) cols;
8133   pr "      free (%s);\n" n
8134
8135 (* Generate Sys/Guestfs.pm. *)
8136 and generate_perl_pm () =
8137   generate_header HashStyle LGPLv2;
8138
8139   pr "\
8140 =pod
8141
8142 =head1 NAME
8143
8144 Sys::Guestfs - Perl bindings for libguestfs
8145
8146 =head1 SYNOPSIS
8147
8148  use Sys::Guestfs;
8149
8150  my $h = Sys::Guestfs->new ();
8151  $h->add_drive ('guest.img');
8152  $h->launch ();
8153  $h->mount ('/dev/sda1', '/');
8154  $h->touch ('/hello');
8155  $h->sync ();
8156
8157 =head1 DESCRIPTION
8158
8159 The C<Sys::Guestfs> module provides a Perl XS binding to the
8160 libguestfs API for examining and modifying virtual machine
8161 disk images.
8162
8163 Amongst the things this is good for: making batch configuration
8164 changes to guests, getting disk used/free statistics (see also:
8165 virt-df), migrating between virtualization systems (see also:
8166 virt-p2v), performing partial backups, performing partial guest
8167 clones, cloning guests and changing registry/UUID/hostname info, and
8168 much else besides.
8169
8170 Libguestfs uses Linux kernel and qemu code, and can access any type of
8171 guest filesystem that Linux and qemu can, including but not limited
8172 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8173 schemes, qcow, qcow2, vmdk.
8174
8175 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8176 LVs, what filesystem is in each LV, etc.).  It can also run commands
8177 in the context of the guest.  Also you can access filesystems over FTP.
8178
8179 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8180 functions for using libguestfs from Perl, including integration
8181 with libvirt.
8182
8183 =head1 ERRORS
8184
8185 All errors turn into calls to C<croak> (see L<Carp(3)>).
8186
8187 =head1 METHODS
8188
8189 =over 4
8190
8191 =cut
8192
8193 package Sys::Guestfs;
8194
8195 use strict;
8196 use warnings;
8197
8198 require XSLoader;
8199 XSLoader::load ('Sys::Guestfs');
8200
8201 =item $h = Sys::Guestfs->new ();
8202
8203 Create a new guestfs handle.
8204
8205 =cut
8206
8207 sub new {
8208   my $proto = shift;
8209   my $class = ref ($proto) || $proto;
8210
8211   my $self = Sys::Guestfs::_create ();
8212   bless $self, $class;
8213   return $self;
8214 }
8215
8216 ";
8217
8218   (* Actions.  We only need to print documentation for these as
8219    * they are pulled in from the XS code automatically.
8220    *)
8221   List.iter (
8222     fun (name, style, _, flags, _, _, longdesc) ->
8223       if not (List.mem NotInDocs flags) then (
8224         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8225         pr "=item ";
8226         generate_perl_prototype name style;
8227         pr "\n\n";
8228         pr "%s\n\n" longdesc;
8229         if List.mem ProtocolLimitWarning flags then
8230           pr "%s\n\n" protocol_limit_warning;
8231         if List.mem DangerWillRobinson flags then
8232           pr "%s\n\n" danger_will_robinson;
8233         match deprecation_notice flags with
8234         | None -> ()
8235         | Some txt -> pr "%s\n\n" txt
8236       )
8237   ) all_functions_sorted;
8238
8239   (* End of file. *)
8240   pr "\
8241 =cut
8242
8243 1;
8244
8245 =back
8246
8247 =head1 COPYRIGHT
8248
8249 Copyright (C) 2009 Red Hat Inc.
8250
8251 =head1 LICENSE
8252
8253 Please see the file COPYING.LIB for the full license.
8254
8255 =head1 SEE ALSO
8256
8257 L<guestfs(3)>,
8258 L<guestfish(1)>,
8259 L<http://libguestfs.org>,
8260 L<Sys::Guestfs::Lib(3)>.
8261
8262 =cut
8263 "
8264
8265 and generate_perl_prototype name style =
8266   (match fst style with
8267    | RErr -> ()
8268    | RBool n
8269    | RInt n
8270    | RInt64 n
8271    | RConstString n
8272    | RConstOptString n
8273    | RString n
8274    | RBufferOut n -> pr "$%s = " n
8275    | RStruct (n,_)
8276    | RHashtable n -> pr "%%%s = " n
8277    | RStringList n
8278    | RStructList (n,_) -> pr "@%s = " n
8279   );
8280   pr "$h->%s (" name;
8281   let comma = ref false in
8282   List.iter (
8283     fun arg ->
8284       if !comma then pr ", ";
8285       comma := true;
8286       match arg with
8287       | Pathname n | Device n | Dev_or_Path n | String n
8288       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8289           pr "$%s" n
8290       | StringList n | DeviceList n ->
8291           pr "\\@%s" n
8292   ) (snd style);
8293   pr ");"
8294
8295 (* Generate Python C module. *)
8296 and generate_python_c () =
8297   generate_header CStyle LGPLv2;
8298
8299   pr "\
8300 #include <Python.h>
8301
8302 #include <stdio.h>
8303 #include <stdlib.h>
8304 #include <assert.h>
8305
8306 #include \"guestfs.h\"
8307
8308 typedef struct {
8309   PyObject_HEAD
8310   guestfs_h *g;
8311 } Pyguestfs_Object;
8312
8313 static guestfs_h *
8314 get_handle (PyObject *obj)
8315 {
8316   assert (obj);
8317   assert (obj != Py_None);
8318   return ((Pyguestfs_Object *) obj)->g;
8319 }
8320
8321 static PyObject *
8322 put_handle (guestfs_h *g)
8323 {
8324   assert (g);
8325   return
8326     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8327 }
8328
8329 /* This list should be freed (but not the strings) after use. */
8330 static char **
8331 get_string_list (PyObject *obj)
8332 {
8333   int i, len;
8334   char **r;
8335
8336   assert (obj);
8337
8338   if (!PyList_Check (obj)) {
8339     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8340     return NULL;
8341   }
8342
8343   len = PyList_Size (obj);
8344   r = malloc (sizeof (char *) * (len+1));
8345   if (r == NULL) {
8346     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8347     return NULL;
8348   }
8349
8350   for (i = 0; i < len; ++i)
8351     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8352   r[len] = NULL;
8353
8354   return r;
8355 }
8356
8357 static PyObject *
8358 put_string_list (char * const * const argv)
8359 {
8360   PyObject *list;
8361   int argc, i;
8362
8363   for (argc = 0; argv[argc] != NULL; ++argc)
8364     ;
8365
8366   list = PyList_New (argc);
8367   for (i = 0; i < argc; ++i)
8368     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8369
8370   return list;
8371 }
8372
8373 static PyObject *
8374 put_table (char * const * const argv)
8375 {
8376   PyObject *list, *item;
8377   int argc, i;
8378
8379   for (argc = 0; argv[argc] != NULL; ++argc)
8380     ;
8381
8382   list = PyList_New (argc >> 1);
8383   for (i = 0; i < argc; i += 2) {
8384     item = PyTuple_New (2);
8385     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8386     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8387     PyList_SetItem (list, i >> 1, item);
8388   }
8389
8390   return list;
8391 }
8392
8393 static void
8394 free_strings (char **argv)
8395 {
8396   int argc;
8397
8398   for (argc = 0; argv[argc] != NULL; ++argc)
8399     free (argv[argc]);
8400   free (argv);
8401 }
8402
8403 static PyObject *
8404 py_guestfs_create (PyObject *self, PyObject *args)
8405 {
8406   guestfs_h *g;
8407
8408   g = guestfs_create ();
8409   if (g == NULL) {
8410     PyErr_SetString (PyExc_RuntimeError,
8411                      \"guestfs.create: failed to allocate handle\");
8412     return NULL;
8413   }
8414   guestfs_set_error_handler (g, NULL, NULL);
8415   return put_handle (g);
8416 }
8417
8418 static PyObject *
8419 py_guestfs_close (PyObject *self, PyObject *args)
8420 {
8421   PyObject *py_g;
8422   guestfs_h *g;
8423
8424   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8425     return NULL;
8426   g = get_handle (py_g);
8427
8428   guestfs_close (g);
8429
8430   Py_INCREF (Py_None);
8431   return Py_None;
8432 }
8433
8434 ";
8435
8436   let emit_put_list_function typ =
8437     pr "static PyObject *\n";
8438     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8439     pr "{\n";
8440     pr "  PyObject *list;\n";
8441     pr "  int i;\n";
8442     pr "\n";
8443     pr "  list = PyList_New (%ss->len);\n" typ;
8444     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8445     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8446     pr "  return list;\n";
8447     pr "};\n";
8448     pr "\n"
8449   in
8450
8451   (* Structures, turned into Python dictionaries. *)
8452   List.iter (
8453     fun (typ, cols) ->
8454       pr "static PyObject *\n";
8455       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8456       pr "{\n";
8457       pr "  PyObject *dict;\n";
8458       pr "\n";
8459       pr "  dict = PyDict_New ();\n";
8460       List.iter (
8461         function
8462         | name, FString ->
8463             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8464             pr "                        PyString_FromString (%s->%s));\n"
8465               typ name
8466         | name, FBuffer ->
8467             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8468             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8469               typ name typ name
8470         | name, FUUID ->
8471             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8472             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8473               typ name
8474         | name, (FBytes|FUInt64) ->
8475             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8476             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8477               typ name
8478         | name, FInt64 ->
8479             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8480             pr "                        PyLong_FromLongLong (%s->%s));\n"
8481               typ name
8482         | name, FUInt32 ->
8483             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8484             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8485               typ name
8486         | name, FInt32 ->
8487             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8488             pr "                        PyLong_FromLong (%s->%s));\n"
8489               typ name
8490         | name, FOptPercent ->
8491             pr "  if (%s->%s >= 0)\n" typ name;
8492             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8493             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8494               typ name;
8495             pr "  else {\n";
8496             pr "    Py_INCREF (Py_None);\n";
8497             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8498             pr "  }\n"
8499         | name, FChar ->
8500             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8501             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8502       ) cols;
8503       pr "  return dict;\n";
8504       pr "};\n";
8505       pr "\n";
8506
8507   ) structs;
8508
8509   (* Emit a put_TYPE_list function definition only if that function is used. *)
8510   List.iter (
8511     function
8512     | typ, (RStructListOnly | RStructAndList) ->
8513         (* generate the function for typ *)
8514         emit_put_list_function typ
8515     | typ, _ -> () (* empty *)
8516   ) (rstructs_used_by all_functions);
8517
8518   (* Python wrapper functions. *)
8519   List.iter (
8520     fun (name, style, _, _, _, _, _) ->
8521       pr "static PyObject *\n";
8522       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8523       pr "{\n";
8524
8525       pr "  PyObject *py_g;\n";
8526       pr "  guestfs_h *g;\n";
8527       pr "  PyObject *py_r;\n";
8528
8529       let error_code =
8530         match fst style with
8531         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8532         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8533         | RConstString _ | RConstOptString _ ->
8534             pr "  const char *r;\n"; "NULL"
8535         | RString _ -> pr "  char *r;\n"; "NULL"
8536         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8537         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8538         | RStructList (_, typ) ->
8539             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8540         | RBufferOut _ ->
8541             pr "  char *r;\n";
8542             pr "  size_t size;\n";
8543             "NULL" in
8544
8545       List.iter (
8546         function
8547         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8548             pr "  const char *%s;\n" n
8549         | OptString n -> pr "  const char *%s;\n" n
8550         | StringList n | DeviceList n ->
8551             pr "  PyObject *py_%s;\n" n;
8552             pr "  char **%s;\n" n
8553         | Bool n -> pr "  int %s;\n" n
8554         | Int n -> pr "  int %s;\n" n
8555         | Int64 n -> pr "  long long %s;\n" n
8556       ) (snd style);
8557
8558       pr "\n";
8559
8560       (* Convert the parameters. *)
8561       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8562       List.iter (
8563         function
8564         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8565         | OptString _ -> pr "z"
8566         | StringList _ | DeviceList _ -> pr "O"
8567         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8568         | Int _ -> pr "i"
8569         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8570                              * emulate C's int/long/long long in Python?
8571                              *)
8572       ) (snd style);
8573       pr ":guestfs_%s\",\n" name;
8574       pr "                         &py_g";
8575       List.iter (
8576         function
8577         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8578         | OptString n -> pr ", &%s" n
8579         | StringList n | DeviceList n -> pr ", &py_%s" n
8580         | Bool n -> pr ", &%s" n
8581         | Int n -> pr ", &%s" n
8582         | Int64 n -> pr ", &%s" n
8583       ) (snd style);
8584
8585       pr "))\n";
8586       pr "    return NULL;\n";
8587
8588       pr "  g = get_handle (py_g);\n";
8589       List.iter (
8590         function
8591         | Pathname _ | Device _ | Dev_or_Path _ | String _
8592         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8593         | StringList n | DeviceList n ->
8594             pr "  %s = get_string_list (py_%s);\n" n n;
8595             pr "  if (!%s) return NULL;\n" n
8596       ) (snd style);
8597
8598       pr "\n";
8599
8600       pr "  r = guestfs_%s " name;
8601       generate_c_call_args ~handle:"g" style;
8602       pr ";\n";
8603
8604       List.iter (
8605         function
8606         | Pathname _ | Device _ | Dev_or_Path _ | String _
8607         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8608         | StringList n | DeviceList n ->
8609             pr "  free (%s);\n" n
8610       ) (snd style);
8611
8612       pr "  if (r == %s) {\n" error_code;
8613       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8614       pr "    return NULL;\n";
8615       pr "  }\n";
8616       pr "\n";
8617
8618       (match fst style with
8619        | RErr ->
8620            pr "  Py_INCREF (Py_None);\n";
8621            pr "  py_r = Py_None;\n"
8622        | RInt _
8623        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8624        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8625        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8626        | RConstOptString _ ->
8627            pr "  if (r)\n";
8628            pr "    py_r = PyString_FromString (r);\n";
8629            pr "  else {\n";
8630            pr "    Py_INCREF (Py_None);\n";
8631            pr "    py_r = Py_None;\n";
8632            pr "  }\n"
8633        | RString _ ->
8634            pr "  py_r = PyString_FromString (r);\n";
8635            pr "  free (r);\n"
8636        | RStringList _ ->
8637            pr "  py_r = put_string_list (r);\n";
8638            pr "  free_strings (r);\n"
8639        | RStruct (_, typ) ->
8640            pr "  py_r = put_%s (r);\n" typ;
8641            pr "  guestfs_free_%s (r);\n" typ
8642        | RStructList (_, typ) ->
8643            pr "  py_r = put_%s_list (r);\n" typ;
8644            pr "  guestfs_free_%s_list (r);\n" typ
8645        | RHashtable n ->
8646            pr "  py_r = put_table (r);\n";
8647            pr "  free_strings (r);\n"
8648        | RBufferOut _ ->
8649            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8650            pr "  free (r);\n"
8651       );
8652
8653       pr "  return py_r;\n";
8654       pr "}\n";
8655       pr "\n"
8656   ) all_functions;
8657
8658   (* Table of functions. *)
8659   pr "static PyMethodDef methods[] = {\n";
8660   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8661   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8662   List.iter (
8663     fun (name, _, _, _, _, _, _) ->
8664       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8665         name name
8666   ) all_functions;
8667   pr "  { NULL, NULL, 0, NULL }\n";
8668   pr "};\n";
8669   pr "\n";
8670
8671   (* Init function. *)
8672   pr "\
8673 void
8674 initlibguestfsmod (void)
8675 {
8676   static int initialized = 0;
8677
8678   if (initialized) return;
8679   Py_InitModule ((char *) \"libguestfsmod\", methods);
8680   initialized = 1;
8681 }
8682 "
8683
8684 (* Generate Python module. *)
8685 and generate_python_py () =
8686   generate_header HashStyle LGPLv2;
8687
8688   pr "\
8689 u\"\"\"Python bindings for libguestfs
8690
8691 import guestfs
8692 g = guestfs.GuestFS ()
8693 g.add_drive (\"guest.img\")
8694 g.launch ()
8695 parts = g.list_partitions ()
8696
8697 The guestfs module provides a Python binding to the libguestfs API
8698 for examining and modifying virtual machine disk images.
8699
8700 Amongst the things this is good for: making batch configuration
8701 changes to guests, getting disk used/free statistics (see also:
8702 virt-df), migrating between virtualization systems (see also:
8703 virt-p2v), performing partial backups, performing partial guest
8704 clones, cloning guests and changing registry/UUID/hostname info, and
8705 much else besides.
8706
8707 Libguestfs uses Linux kernel and qemu code, and can access any type of
8708 guest filesystem that Linux and qemu can, including but not limited
8709 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8710 schemes, qcow, qcow2, vmdk.
8711
8712 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8713 LVs, what filesystem is in each LV, etc.).  It can also run commands
8714 in the context of the guest.  Also you can access filesystems over FTP.
8715
8716 Errors which happen while using the API are turned into Python
8717 RuntimeError exceptions.
8718
8719 To create a guestfs handle you usually have to perform the following
8720 sequence of calls:
8721
8722 # Create the handle, call add_drive at least once, and possibly
8723 # several times if the guest has multiple block devices:
8724 g = guestfs.GuestFS ()
8725 g.add_drive (\"guest.img\")
8726
8727 # Launch the qemu subprocess and wait for it to become ready:
8728 g.launch ()
8729
8730 # Now you can issue commands, for example:
8731 logvols = g.lvs ()
8732
8733 \"\"\"
8734
8735 import libguestfsmod
8736
8737 class GuestFS:
8738     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8739
8740     def __init__ (self):
8741         \"\"\"Create a new libguestfs handle.\"\"\"
8742         self._o = libguestfsmod.create ()
8743
8744     def __del__ (self):
8745         libguestfsmod.close (self._o)
8746
8747 ";
8748
8749   List.iter (
8750     fun (name, style, _, flags, _, _, longdesc) ->
8751       pr "    def %s " name;
8752       generate_py_call_args ~handle:"self" (snd style);
8753       pr ":\n";
8754
8755       if not (List.mem NotInDocs flags) then (
8756         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8757         let doc =
8758           match fst style with
8759           | RErr | RInt _ | RInt64 _ | RBool _
8760           | RConstOptString _ | RConstString _
8761           | RString _ | RBufferOut _ -> doc
8762           | RStringList _ ->
8763               doc ^ "\n\nThis function returns a list of strings."
8764           | RStruct (_, typ) ->
8765               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8766           | RStructList (_, typ) ->
8767               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8768           | RHashtable _ ->
8769               doc ^ "\n\nThis function returns a dictionary." in
8770         let doc =
8771           if List.mem ProtocolLimitWarning flags then
8772             doc ^ "\n\n" ^ protocol_limit_warning
8773           else doc in
8774         let doc =
8775           if List.mem DangerWillRobinson flags then
8776             doc ^ "\n\n" ^ danger_will_robinson
8777           else doc in
8778         let doc =
8779           match deprecation_notice flags with
8780           | None -> doc
8781           | Some txt -> doc ^ "\n\n" ^ txt in
8782         let doc = pod2text ~width:60 name doc in
8783         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8784         let doc = String.concat "\n        " doc in
8785         pr "        u\"\"\"%s\"\"\"\n" doc;
8786       );
8787       pr "        return libguestfsmod.%s " name;
8788       generate_py_call_args ~handle:"self._o" (snd style);
8789       pr "\n";
8790       pr "\n";
8791   ) all_functions
8792
8793 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8794 and generate_py_call_args ~handle args =
8795   pr "(%s" handle;
8796   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8797   pr ")"
8798
8799 (* Useful if you need the longdesc POD text as plain text.  Returns a
8800  * list of lines.
8801  *
8802  * Because this is very slow (the slowest part of autogeneration),
8803  * we memoize the results.
8804  *)
8805 and pod2text ~width name longdesc =
8806   let key = width, name, longdesc in
8807   try Hashtbl.find pod2text_memo key
8808   with Not_found ->
8809     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8810     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8811     close_out chan;
8812     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8813     let chan = open_process_in cmd in
8814     let lines = ref [] in
8815     let rec loop i =
8816       let line = input_line chan in
8817       if i = 1 then             (* discard the first line of output *)
8818         loop (i+1)
8819       else (
8820         let line = triml line in
8821         lines := line :: !lines;
8822         loop (i+1)
8823       ) in
8824     let lines = try loop 1 with End_of_file -> List.rev !lines in
8825     unlink filename;
8826     (match close_process_in chan with
8827      | WEXITED 0 -> ()
8828      | WEXITED i ->
8829          failwithf "pod2text: process exited with non-zero status (%d)" i
8830      | WSIGNALED i | WSTOPPED i ->
8831          failwithf "pod2text: process signalled or stopped by signal %d" i
8832     );
8833     Hashtbl.add pod2text_memo key lines;
8834     pod2text_memo_updated ();
8835     lines
8836
8837 (* Generate ruby bindings. *)
8838 and generate_ruby_c () =
8839   generate_header CStyle LGPLv2;
8840
8841   pr "\
8842 #include <stdio.h>
8843 #include <stdlib.h>
8844
8845 #include <ruby.h>
8846
8847 #include \"guestfs.h\"
8848
8849 #include \"extconf.h\"
8850
8851 /* For Ruby < 1.9 */
8852 #ifndef RARRAY_LEN
8853 #define RARRAY_LEN(r) (RARRAY((r))->len)
8854 #endif
8855
8856 static VALUE m_guestfs;                 /* guestfs module */
8857 static VALUE c_guestfs;                 /* guestfs_h handle */
8858 static VALUE e_Error;                   /* used for all errors */
8859
8860 static void ruby_guestfs_free (void *p)
8861 {
8862   if (!p) return;
8863   guestfs_close ((guestfs_h *) p);
8864 }
8865
8866 static VALUE ruby_guestfs_create (VALUE m)
8867 {
8868   guestfs_h *g;
8869
8870   g = guestfs_create ();
8871   if (!g)
8872     rb_raise (e_Error, \"failed to create guestfs handle\");
8873
8874   /* Don't print error messages to stderr by default. */
8875   guestfs_set_error_handler (g, NULL, NULL);
8876
8877   /* Wrap it, and make sure the close function is called when the
8878    * handle goes away.
8879    */
8880   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8881 }
8882
8883 static VALUE ruby_guestfs_close (VALUE gv)
8884 {
8885   guestfs_h *g;
8886   Data_Get_Struct (gv, guestfs_h, g);
8887
8888   ruby_guestfs_free (g);
8889   DATA_PTR (gv) = NULL;
8890
8891   return Qnil;
8892 }
8893
8894 ";
8895
8896   List.iter (
8897     fun (name, style, _, _, _, _, _) ->
8898       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8899       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8900       pr ")\n";
8901       pr "{\n";
8902       pr "  guestfs_h *g;\n";
8903       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8904       pr "  if (!g)\n";
8905       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8906         name;
8907       pr "\n";
8908
8909       List.iter (
8910         function
8911         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8912             pr "  Check_Type (%sv, T_STRING);\n" n;
8913             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8914             pr "  if (!%s)\n" n;
8915             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8916             pr "              \"%s\", \"%s\");\n" n name
8917         | OptString n ->
8918             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8919         | StringList n | DeviceList n ->
8920             pr "  char **%s;\n" n;
8921             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8922             pr "  {\n";
8923             pr "    int i, len;\n";
8924             pr "    len = RARRAY_LEN (%sv);\n" n;
8925             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8926               n;
8927             pr "    for (i = 0; i < len; ++i) {\n";
8928             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8929             pr "      %s[i] = StringValueCStr (v);\n" n;
8930             pr "    }\n";
8931             pr "    %s[len] = NULL;\n" n;
8932             pr "  }\n";
8933         | Bool n ->
8934             pr "  int %s = RTEST (%sv);\n" n n
8935         | Int n ->
8936             pr "  int %s = NUM2INT (%sv);\n" n n
8937         | Int64 n ->
8938             pr "  long long %s = NUM2LL (%sv);\n" n n
8939       ) (snd style);
8940       pr "\n";
8941
8942       let error_code =
8943         match fst style with
8944         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8945         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8946         | RConstString _ | RConstOptString _ ->
8947             pr "  const char *r;\n"; "NULL"
8948         | RString _ -> pr "  char *r;\n"; "NULL"
8949         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8950         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8951         | RStructList (_, typ) ->
8952             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8953         | RBufferOut _ ->
8954             pr "  char *r;\n";
8955             pr "  size_t size;\n";
8956             "NULL" in
8957       pr "\n";
8958
8959       pr "  r = guestfs_%s " name;
8960       generate_c_call_args ~handle:"g" style;
8961       pr ";\n";
8962
8963       List.iter (
8964         function
8965         | Pathname _ | Device _ | Dev_or_Path _ | String _
8966         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8967         | StringList n | DeviceList n ->
8968             pr "  free (%s);\n" n
8969       ) (snd style);
8970
8971       pr "  if (r == %s)\n" error_code;
8972       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8973       pr "\n";
8974
8975       (match fst style with
8976        | RErr ->
8977            pr "  return Qnil;\n"
8978        | RInt _ | RBool _ ->
8979            pr "  return INT2NUM (r);\n"
8980        | RInt64 _ ->
8981            pr "  return ULL2NUM (r);\n"
8982        | RConstString _ ->
8983            pr "  return rb_str_new2 (r);\n";
8984        | RConstOptString _ ->
8985            pr "  if (r)\n";
8986            pr "    return rb_str_new2 (r);\n";
8987            pr "  else\n";
8988            pr "    return Qnil;\n";
8989        | RString _ ->
8990            pr "  VALUE rv = rb_str_new2 (r);\n";
8991            pr "  free (r);\n";
8992            pr "  return rv;\n";
8993        | RStringList _ ->
8994            pr "  int i, len = 0;\n";
8995            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8996            pr "  VALUE rv = rb_ary_new2 (len);\n";
8997            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8998            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8999            pr "    free (r[i]);\n";
9000            pr "  }\n";
9001            pr "  free (r);\n";
9002            pr "  return rv;\n"
9003        | RStruct (_, typ) ->
9004            let cols = cols_of_struct typ in
9005            generate_ruby_struct_code typ cols
9006        | RStructList (_, typ) ->
9007            let cols = cols_of_struct typ in
9008            generate_ruby_struct_list_code typ cols
9009        | RHashtable _ ->
9010            pr "  VALUE rv = rb_hash_new ();\n";
9011            pr "  int i;\n";
9012            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9013            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9014            pr "    free (r[i]);\n";
9015            pr "    free (r[i+1]);\n";
9016            pr "  }\n";
9017            pr "  free (r);\n";
9018            pr "  return rv;\n"
9019        | RBufferOut _ ->
9020            pr "  VALUE rv = rb_str_new (r, size);\n";
9021            pr "  free (r);\n";
9022            pr "  return rv;\n";
9023       );
9024
9025       pr "}\n";
9026       pr "\n"
9027   ) all_functions;
9028
9029   pr "\
9030 /* Initialize the module. */
9031 void Init__guestfs ()
9032 {
9033   m_guestfs = rb_define_module (\"Guestfs\");
9034   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9035   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9036
9037   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9038   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9039
9040 ";
9041   (* Define the rest of the methods. *)
9042   List.iter (
9043     fun (name, style, _, _, _, _, _) ->
9044       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9045       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9046   ) all_functions;
9047
9048   pr "}\n"
9049
9050 (* Ruby code to return a struct. *)
9051 and generate_ruby_struct_code typ cols =
9052   pr "  VALUE rv = rb_hash_new ();\n";
9053   List.iter (
9054     function
9055     | name, FString ->
9056         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9057     | name, FBuffer ->
9058         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9059     | name, FUUID ->
9060         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9061     | name, (FBytes|FUInt64) ->
9062         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9063     | name, FInt64 ->
9064         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9065     | name, FUInt32 ->
9066         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9067     | name, FInt32 ->
9068         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9069     | name, FOptPercent ->
9070         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9071     | name, FChar -> (* XXX wrong? *)
9072         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9073   ) cols;
9074   pr "  guestfs_free_%s (r);\n" typ;
9075   pr "  return rv;\n"
9076
9077 (* Ruby code to return a struct list. *)
9078 and generate_ruby_struct_list_code typ cols =
9079   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9080   pr "  int i;\n";
9081   pr "  for (i = 0; i < r->len; ++i) {\n";
9082   pr "    VALUE hv = rb_hash_new ();\n";
9083   List.iter (
9084     function
9085     | name, FString ->
9086         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9087     | name, FBuffer ->
9088         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
9089     | name, FUUID ->
9090         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9091     | name, (FBytes|FUInt64) ->
9092         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9093     | name, FInt64 ->
9094         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9095     | name, FUInt32 ->
9096         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9097     | name, FInt32 ->
9098         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9099     | name, FOptPercent ->
9100         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9101     | name, FChar -> (* XXX wrong? *)
9102         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9103   ) cols;
9104   pr "    rb_ary_push (rv, hv);\n";
9105   pr "  }\n";
9106   pr "  guestfs_free_%s_list (r);\n" typ;
9107   pr "  return rv;\n"
9108
9109 (* Generate Java bindings GuestFS.java file. *)
9110 and generate_java_java () =
9111   generate_header CStyle LGPLv2;
9112
9113   pr "\
9114 package com.redhat.et.libguestfs;
9115
9116 import java.util.HashMap;
9117 import com.redhat.et.libguestfs.LibGuestFSException;
9118 import com.redhat.et.libguestfs.PV;
9119 import com.redhat.et.libguestfs.VG;
9120 import com.redhat.et.libguestfs.LV;
9121 import com.redhat.et.libguestfs.Stat;
9122 import com.redhat.et.libguestfs.StatVFS;
9123 import com.redhat.et.libguestfs.IntBool;
9124 import com.redhat.et.libguestfs.Dirent;
9125
9126 /**
9127  * The GuestFS object is a libguestfs handle.
9128  *
9129  * @author rjones
9130  */
9131 public class GuestFS {
9132   // Load the native code.
9133   static {
9134     System.loadLibrary (\"guestfs_jni\");
9135   }
9136
9137   /**
9138    * The native guestfs_h pointer.
9139    */
9140   long g;
9141
9142   /**
9143    * Create a libguestfs handle.
9144    *
9145    * @throws LibGuestFSException
9146    */
9147   public GuestFS () throws LibGuestFSException
9148   {
9149     g = _create ();
9150   }
9151   private native long _create () throws LibGuestFSException;
9152
9153   /**
9154    * Close a libguestfs handle.
9155    *
9156    * You can also leave handles to be collected by the garbage
9157    * collector, but this method ensures that the resources used
9158    * by the handle are freed up immediately.  If you call any
9159    * other methods after closing the handle, you will get an
9160    * exception.
9161    *
9162    * @throws LibGuestFSException
9163    */
9164   public void close () throws LibGuestFSException
9165   {
9166     if (g != 0)
9167       _close (g);
9168     g = 0;
9169   }
9170   private native void _close (long g) throws LibGuestFSException;
9171
9172   public void finalize () throws LibGuestFSException
9173   {
9174     close ();
9175   }
9176
9177 ";
9178
9179   List.iter (
9180     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9181       if not (List.mem NotInDocs flags); then (
9182         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9183         let doc =
9184           if List.mem ProtocolLimitWarning flags then
9185             doc ^ "\n\n" ^ protocol_limit_warning
9186           else doc in
9187         let doc =
9188           if List.mem DangerWillRobinson flags then
9189             doc ^ "\n\n" ^ danger_will_robinson
9190           else doc in
9191         let doc =
9192           match deprecation_notice flags with
9193           | None -> doc
9194           | Some txt -> doc ^ "\n\n" ^ txt in
9195         let doc = pod2text ~width:60 name doc in
9196         let doc = List.map (            (* RHBZ#501883 *)
9197           function
9198           | "" -> "<p>"
9199           | nonempty -> nonempty
9200         ) doc in
9201         let doc = String.concat "\n   * " doc in
9202
9203         pr "  /**\n";
9204         pr "   * %s\n" shortdesc;
9205         pr "   * <p>\n";
9206         pr "   * %s\n" doc;
9207         pr "   * @throws LibGuestFSException\n";
9208         pr "   */\n";
9209         pr "  ";
9210       );
9211       generate_java_prototype ~public:true ~semicolon:false name style;
9212       pr "\n";
9213       pr "  {\n";
9214       pr "    if (g == 0)\n";
9215       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9216         name;
9217       pr "    ";
9218       if fst style <> RErr then pr "return ";
9219       pr "_%s " name;
9220       generate_java_call_args ~handle:"g" (snd style);
9221       pr ";\n";
9222       pr "  }\n";
9223       pr "  ";
9224       generate_java_prototype ~privat:true ~native:true name style;
9225       pr "\n";
9226       pr "\n";
9227   ) all_functions;
9228
9229   pr "}\n"
9230
9231 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9232 and generate_java_call_args ~handle args =
9233   pr "(%s" handle;
9234   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9235   pr ")"
9236
9237 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9238     ?(semicolon=true) name style =
9239   if privat then pr "private ";
9240   if public then pr "public ";
9241   if native then pr "native ";
9242
9243   (* return type *)
9244   (match fst style with
9245    | RErr -> pr "void ";
9246    | RInt _ -> pr "int ";
9247    | RInt64 _ -> pr "long ";
9248    | RBool _ -> pr "boolean ";
9249    | RConstString _ | RConstOptString _ | RString _
9250    | RBufferOut _ -> pr "String ";
9251    | RStringList _ -> pr "String[] ";
9252    | RStruct (_, typ) ->
9253        let name = java_name_of_struct typ in
9254        pr "%s " name;
9255    | RStructList (_, typ) ->
9256        let name = java_name_of_struct typ in
9257        pr "%s[] " name;
9258    | RHashtable _ -> pr "HashMap<String,String> ";
9259   );
9260
9261   if native then pr "_%s " name else pr "%s " name;
9262   pr "(";
9263   let needs_comma = ref false in
9264   if native then (
9265     pr "long g";
9266     needs_comma := true
9267   );
9268
9269   (* args *)
9270   List.iter (
9271     fun arg ->
9272       if !needs_comma then pr ", ";
9273       needs_comma := true;
9274
9275       match arg with
9276       | Pathname n
9277       | Device n | Dev_or_Path n
9278       | String n
9279       | OptString n
9280       | FileIn n
9281       | FileOut n ->
9282           pr "String %s" n
9283       | StringList n | DeviceList n ->
9284           pr "String[] %s" n
9285       | Bool n ->
9286           pr "boolean %s" n
9287       | Int n ->
9288           pr "int %s" n
9289       | Int64 n ->
9290           pr "long %s" n
9291   ) (snd style);
9292
9293   pr ")\n";
9294   pr "    throws LibGuestFSException";
9295   if semicolon then pr ";"
9296
9297 and generate_java_struct jtyp cols =
9298   generate_header CStyle LGPLv2;
9299
9300   pr "\
9301 package com.redhat.et.libguestfs;
9302
9303 /**
9304  * Libguestfs %s structure.
9305  *
9306  * @author rjones
9307  * @see GuestFS
9308  */
9309 public class %s {
9310 " jtyp jtyp;
9311
9312   List.iter (
9313     function
9314     | name, FString
9315     | name, FUUID
9316     | name, FBuffer -> pr "  public String %s;\n" name
9317     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9318     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9319     | name, FChar -> pr "  public char %s;\n" name
9320     | name, FOptPercent ->
9321         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9322         pr "  public float %s;\n" name
9323   ) cols;
9324
9325   pr "}\n"
9326
9327 and generate_java_c () =
9328   generate_header CStyle LGPLv2;
9329
9330   pr "\
9331 #include <stdio.h>
9332 #include <stdlib.h>
9333 #include <string.h>
9334
9335 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9336 #include \"guestfs.h\"
9337
9338 /* Note that this function returns.  The exception is not thrown
9339  * until after the wrapper function returns.
9340  */
9341 static void
9342 throw_exception (JNIEnv *env, const char *msg)
9343 {
9344   jclass cl;
9345   cl = (*env)->FindClass (env,
9346                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9347   (*env)->ThrowNew (env, cl, msg);
9348 }
9349
9350 JNIEXPORT jlong JNICALL
9351 Java_com_redhat_et_libguestfs_GuestFS__1create
9352   (JNIEnv *env, jobject obj)
9353 {
9354   guestfs_h *g;
9355
9356   g = guestfs_create ();
9357   if (g == NULL) {
9358     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9359     return 0;
9360   }
9361   guestfs_set_error_handler (g, NULL, NULL);
9362   return (jlong) (long) g;
9363 }
9364
9365 JNIEXPORT void JNICALL
9366 Java_com_redhat_et_libguestfs_GuestFS__1close
9367   (JNIEnv *env, jobject obj, jlong jg)
9368 {
9369   guestfs_h *g = (guestfs_h *) (long) jg;
9370   guestfs_close (g);
9371 }
9372
9373 ";
9374
9375   List.iter (
9376     fun (name, style, _, _, _, _, _) ->
9377       pr "JNIEXPORT ";
9378       (match fst style with
9379        | RErr -> pr "void ";
9380        | RInt _ -> pr "jint ";
9381        | RInt64 _ -> pr "jlong ";
9382        | RBool _ -> pr "jboolean ";
9383        | RConstString _ | RConstOptString _ | RString _
9384        | RBufferOut _ -> pr "jstring ";
9385        | RStruct _ | RHashtable _ ->
9386            pr "jobject ";
9387        | RStringList _ | RStructList _ ->
9388            pr "jobjectArray ";
9389       );
9390       pr "JNICALL\n";
9391       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9392       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9393       pr "\n";
9394       pr "  (JNIEnv *env, jobject obj, jlong jg";
9395       List.iter (
9396         function
9397         | Pathname n
9398         | Device n | Dev_or_Path n
9399         | String n
9400         | OptString n
9401         | FileIn n
9402         | FileOut n ->
9403             pr ", jstring j%s" n
9404         | StringList n | DeviceList n ->
9405             pr ", jobjectArray j%s" n
9406         | Bool n ->
9407             pr ", jboolean j%s" n
9408         | Int n ->
9409             pr ", jint j%s" n
9410         | Int64 n ->
9411             pr ", jlong j%s" n
9412       ) (snd style);
9413       pr ")\n";
9414       pr "{\n";
9415       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9416       let error_code, no_ret =
9417         match fst style with
9418         | RErr -> pr "  int r;\n"; "-1", ""
9419         | RBool _
9420         | RInt _ -> pr "  int r;\n"; "-1", "0"
9421         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9422         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9423         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9424         | RString _ ->
9425             pr "  jstring jr;\n";
9426             pr "  char *r;\n"; "NULL", "NULL"
9427         | RStringList _ ->
9428             pr "  jobjectArray jr;\n";
9429             pr "  int r_len;\n";
9430             pr "  jclass cl;\n";
9431             pr "  jstring jstr;\n";
9432             pr "  char **r;\n"; "NULL", "NULL"
9433         | RStruct (_, typ) ->
9434             pr "  jobject jr;\n";
9435             pr "  jclass cl;\n";
9436             pr "  jfieldID fl;\n";
9437             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9438         | RStructList (_, typ) ->
9439             pr "  jobjectArray jr;\n";
9440             pr "  jclass cl;\n";
9441             pr "  jfieldID fl;\n";
9442             pr "  jobject jfl;\n";
9443             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9444         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9445         | RBufferOut _ ->
9446             pr "  jstring jr;\n";
9447             pr "  char *r;\n";
9448             pr "  size_t size;\n";
9449             "NULL", "NULL" in
9450       List.iter (
9451         function
9452         | Pathname n
9453         | Device n | Dev_or_Path n
9454         | String n
9455         | OptString n
9456         | FileIn n
9457         | FileOut n ->
9458             pr "  const char *%s;\n" n
9459         | StringList n | DeviceList n ->
9460             pr "  int %s_len;\n" n;
9461             pr "  const char **%s;\n" n
9462         | Bool n
9463         | Int n ->
9464             pr "  int %s;\n" n
9465         | Int64 n ->
9466             pr "  int64_t %s;\n" n
9467       ) (snd style);
9468
9469       let needs_i =
9470         (match fst style with
9471          | RStringList _ | RStructList _ -> true
9472          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9473          | RConstOptString _
9474          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9475           List.exists (function
9476                        | StringList _ -> true
9477                        | DeviceList _ -> true
9478                        | _ -> false) (snd style) in
9479       if needs_i then
9480         pr "  int i;\n";
9481
9482       pr "\n";
9483
9484       (* Get the parameters. *)
9485       List.iter (
9486         function
9487         | Pathname n
9488         | Device n | Dev_or_Path n
9489         | String n
9490         | FileIn n
9491         | FileOut n ->
9492             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9493         | OptString n ->
9494             (* This is completely undocumented, but Java null becomes
9495              * a NULL parameter.
9496              *)
9497             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9498         | StringList n | DeviceList n ->
9499             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9500             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9501             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9502             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9503               n;
9504             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9505             pr "  }\n";
9506             pr "  %s[%s_len] = NULL;\n" n n;
9507         | Bool n
9508         | Int n
9509         | Int64 n ->
9510             pr "  %s = j%s;\n" n n
9511       ) (snd style);
9512
9513       (* Make the call. *)
9514       pr "  r = guestfs_%s " name;
9515       generate_c_call_args ~handle:"g" style;
9516       pr ";\n";
9517
9518       (* Release the parameters. *)
9519       List.iter (
9520         function
9521         | Pathname n
9522         | Device n | Dev_or_Path n
9523         | String n
9524         | FileIn n
9525         | FileOut n ->
9526             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9527         | OptString n ->
9528             pr "  if (j%s)\n" n;
9529             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9530         | StringList n | DeviceList n ->
9531             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9532             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9533               n;
9534             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9535             pr "  }\n";
9536             pr "  free (%s);\n" n
9537         | Bool n
9538         | Int n
9539         | Int64 n -> ()
9540       ) (snd style);
9541
9542       (* Check for errors. *)
9543       pr "  if (r == %s) {\n" error_code;
9544       pr "    throw_exception (env, guestfs_last_error (g));\n";
9545       pr "    return %s;\n" no_ret;
9546       pr "  }\n";
9547
9548       (* Return value. *)
9549       (match fst style with
9550        | RErr -> ()
9551        | RInt _ -> pr "  return (jint) r;\n"
9552        | RBool _ -> pr "  return (jboolean) r;\n"
9553        | RInt64 _ -> pr "  return (jlong) r;\n"
9554        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9555        | RConstOptString _ ->
9556            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9557        | RString _ ->
9558            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9559            pr "  free (r);\n";
9560            pr "  return jr;\n"
9561        | RStringList _ ->
9562            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9563            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9564            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9565            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9566            pr "  for (i = 0; i < r_len; ++i) {\n";
9567            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9568            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9569            pr "    free (r[i]);\n";
9570            pr "  }\n";
9571            pr "  free (r);\n";
9572            pr "  return jr;\n"
9573        | RStruct (_, typ) ->
9574            let jtyp = java_name_of_struct typ in
9575            let cols = cols_of_struct typ in
9576            generate_java_struct_return typ jtyp cols
9577        | RStructList (_, typ) ->
9578            let jtyp = java_name_of_struct typ in
9579            let cols = cols_of_struct typ in
9580            generate_java_struct_list_return typ jtyp cols
9581        | RHashtable _ ->
9582            (* XXX *)
9583            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9584            pr "  return NULL;\n"
9585        | RBufferOut _ ->
9586            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9587            pr "  free (r);\n";
9588            pr "  return jr;\n"
9589       );
9590
9591       pr "}\n";
9592       pr "\n"
9593   ) all_functions
9594
9595 and generate_java_struct_return typ jtyp cols =
9596   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9597   pr "  jr = (*env)->AllocObject (env, cl);\n";
9598   List.iter (
9599     function
9600     | name, FString ->
9601         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9602         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9603     | name, FUUID ->
9604         pr "  {\n";
9605         pr "    char s[33];\n";
9606         pr "    memcpy (s, r->%s, 32);\n" name;
9607         pr "    s[32] = 0;\n";
9608         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9609         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9610         pr "  }\n";
9611     | name, FBuffer ->
9612         pr "  {\n";
9613         pr "    int len = r->%s_len;\n" name;
9614         pr "    char s[len+1];\n";
9615         pr "    memcpy (s, r->%s, len);\n" name;
9616         pr "    s[len] = 0;\n";
9617         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9618         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9619         pr "  }\n";
9620     | name, (FBytes|FUInt64|FInt64) ->
9621         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9622         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9623     | name, (FUInt32|FInt32) ->
9624         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9625         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9626     | name, FOptPercent ->
9627         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9628         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9629     | name, FChar ->
9630         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9631         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9632   ) cols;
9633   pr "  free (r);\n";
9634   pr "  return jr;\n"
9635
9636 and generate_java_struct_list_return typ jtyp cols =
9637   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9638   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9639   pr "  for (i = 0; i < r->len; ++i) {\n";
9640   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9641   List.iter (
9642     function
9643     | name, FString ->
9644         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9645         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9646     | name, FUUID ->
9647         pr "    {\n";
9648         pr "      char s[33];\n";
9649         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9650         pr "      s[32] = 0;\n";
9651         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9652         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9653         pr "    }\n";
9654     | name, FBuffer ->
9655         pr "    {\n";
9656         pr "      int len = r->val[i].%s_len;\n" name;
9657         pr "      char s[len+1];\n";
9658         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9659         pr "      s[len] = 0;\n";
9660         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9661         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9662         pr "    }\n";
9663     | name, (FBytes|FUInt64|FInt64) ->
9664         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9665         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9666     | name, (FUInt32|FInt32) ->
9667         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9668         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9669     | name, FOptPercent ->
9670         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9671         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9672     | name, FChar ->
9673         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9674         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9675   ) cols;
9676   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9677   pr "  }\n";
9678   pr "  guestfs_free_%s_list (r);\n" typ;
9679   pr "  return jr;\n"
9680
9681 and generate_java_makefile_inc () =
9682   generate_header HashStyle GPLv2;
9683
9684   pr "java_built_sources = \\\n";
9685   List.iter (
9686     fun (typ, jtyp) ->
9687         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9688   ) java_structs;
9689   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9690
9691 and generate_haskell_hs () =
9692   generate_header HaskellStyle LGPLv2;
9693
9694   (* XXX We only know how to generate partial FFI for Haskell
9695    * at the moment.  Please help out!
9696    *)
9697   let can_generate style =
9698     match style with
9699     | RErr, _
9700     | RInt _, _
9701     | RInt64 _, _ -> true
9702     | RBool _, _
9703     | RConstString _, _
9704     | RConstOptString _, _
9705     | RString _, _
9706     | RStringList _, _
9707     | RStruct _, _
9708     | RStructList _, _
9709     | RHashtable _, _
9710     | RBufferOut _, _ -> false in
9711
9712   pr "\
9713 {-# INCLUDE <guestfs.h> #-}
9714 {-# LANGUAGE ForeignFunctionInterface #-}
9715
9716 module Guestfs (
9717   create";
9718
9719   (* List out the names of the actions we want to export. *)
9720   List.iter (
9721     fun (name, style, _, _, _, _, _) ->
9722       if can_generate style then pr ",\n  %s" name
9723   ) all_functions;
9724
9725   pr "
9726   ) where
9727
9728 -- Unfortunately some symbols duplicate ones already present
9729 -- in Prelude.  We don't know which, so we hard-code a list
9730 -- here.
9731 import Prelude hiding (truncate)
9732
9733 import Foreign
9734 import Foreign.C
9735 import Foreign.C.Types
9736 import IO
9737 import Control.Exception
9738 import Data.Typeable
9739
9740 data GuestfsS = GuestfsS            -- represents the opaque C struct
9741 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9742 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9743
9744 -- XXX define properly later XXX
9745 data PV = PV
9746 data VG = VG
9747 data LV = LV
9748 data IntBool = IntBool
9749 data Stat = Stat
9750 data StatVFS = StatVFS
9751 data Hashtable = Hashtable
9752
9753 foreign import ccall unsafe \"guestfs_create\" c_create
9754   :: IO GuestfsP
9755 foreign import ccall unsafe \"&guestfs_close\" c_close
9756   :: FunPtr (GuestfsP -> IO ())
9757 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9758   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9759
9760 create :: IO GuestfsH
9761 create = do
9762   p <- c_create
9763   c_set_error_handler p nullPtr nullPtr
9764   h <- newForeignPtr c_close p
9765   return h
9766
9767 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9768   :: GuestfsP -> IO CString
9769
9770 -- last_error :: GuestfsH -> IO (Maybe String)
9771 -- last_error h = do
9772 --   str <- withForeignPtr h (\\p -> c_last_error p)
9773 --   maybePeek peekCString str
9774
9775 last_error :: GuestfsH -> IO (String)
9776 last_error h = do
9777   str <- withForeignPtr h (\\p -> c_last_error p)
9778   if (str == nullPtr)
9779     then return \"no error\"
9780     else peekCString str
9781
9782 ";
9783
9784   (* Generate wrappers for each foreign function. *)
9785   List.iter (
9786     fun (name, style, _, _, _, _, _) ->
9787       if can_generate style then (
9788         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9789         pr "  :: ";
9790         generate_haskell_prototype ~handle:"GuestfsP" style;
9791         pr "\n";
9792         pr "\n";
9793         pr "%s :: " name;
9794         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9795         pr "\n";
9796         pr "%s %s = do\n" name
9797           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9798         pr "  r <- ";
9799         (* Convert pointer arguments using with* functions. *)
9800         List.iter (
9801           function
9802           | FileIn n
9803           | FileOut n
9804           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9805           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9806           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9807           | Bool _ | Int _ | Int64 _ -> ()
9808         ) (snd style);
9809         (* Convert integer arguments. *)
9810         let args =
9811           List.map (
9812             function
9813             | Bool n -> sprintf "(fromBool %s)" n
9814             | Int n -> sprintf "(fromIntegral %s)" n
9815             | Int64 n -> sprintf "(fromIntegral %s)" n
9816             | FileIn n | FileOut n
9817             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9818           ) (snd style) in
9819         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9820           (String.concat " " ("p" :: args));
9821         (match fst style with
9822          | RErr | RInt _ | RInt64 _ | RBool _ ->
9823              pr "  if (r == -1)\n";
9824              pr "    then do\n";
9825              pr "      err <- last_error h\n";
9826              pr "      fail err\n";
9827          | RConstString _ | RConstOptString _ | RString _
9828          | RStringList _ | RStruct _
9829          | RStructList _ | RHashtable _ | RBufferOut _ ->
9830              pr "  if (r == nullPtr)\n";
9831              pr "    then do\n";
9832              pr "      err <- last_error h\n";
9833              pr "      fail err\n";
9834         );
9835         (match fst style with
9836          | RErr ->
9837              pr "    else return ()\n"
9838          | RInt _ ->
9839              pr "    else return (fromIntegral r)\n"
9840          | RInt64 _ ->
9841              pr "    else return (fromIntegral r)\n"
9842          | RBool _ ->
9843              pr "    else return (toBool r)\n"
9844          | RConstString _
9845          | RConstOptString _
9846          | RString _
9847          | RStringList _
9848          | RStruct _
9849          | RStructList _
9850          | RHashtable _
9851          | RBufferOut _ ->
9852              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9853         );
9854         pr "\n";
9855       )
9856   ) all_functions
9857
9858 and generate_haskell_prototype ~handle ?(hs = false) style =
9859   pr "%s -> " handle;
9860   let string = if hs then "String" else "CString" in
9861   let int = if hs then "Int" else "CInt" in
9862   let bool = if hs then "Bool" else "CInt" in
9863   let int64 = if hs then "Integer" else "Int64" in
9864   List.iter (
9865     fun arg ->
9866       (match arg with
9867        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9868        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9869        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9870        | Bool _ -> pr "%s" bool
9871        | Int _ -> pr "%s" int
9872        | Int64 _ -> pr "%s" int
9873        | FileIn _ -> pr "%s" string
9874        | FileOut _ -> pr "%s" string
9875       );
9876       pr " -> ";
9877   ) (snd style);
9878   pr "IO (";
9879   (match fst style with
9880    | RErr -> if not hs then pr "CInt"
9881    | RInt _ -> pr "%s" int
9882    | RInt64 _ -> pr "%s" int64
9883    | RBool _ -> pr "%s" bool
9884    | RConstString _ -> pr "%s" string
9885    | RConstOptString _ -> pr "Maybe %s" string
9886    | RString _ -> pr "%s" string
9887    | RStringList _ -> pr "[%s]" string
9888    | RStruct (_, typ) ->
9889        let name = java_name_of_struct typ in
9890        pr "%s" name
9891    | RStructList (_, typ) ->
9892        let name = java_name_of_struct typ in
9893        pr "[%s]" name
9894    | RHashtable _ -> pr "Hashtable"
9895    | RBufferOut _ -> pr "%s" string
9896   );
9897   pr ")"
9898
9899 and generate_bindtests () =
9900   generate_header CStyle LGPLv2;
9901
9902   pr "\
9903 #include <stdio.h>
9904 #include <stdlib.h>
9905 #include <inttypes.h>
9906 #include <string.h>
9907
9908 #include \"guestfs.h\"
9909 #include \"guestfs-internal.h\"
9910 #include \"guestfs-internal-actions.h\"
9911 #include \"guestfs_protocol.h\"
9912
9913 #define error guestfs_error
9914 #define safe_calloc guestfs_safe_calloc
9915 #define safe_malloc guestfs_safe_malloc
9916
9917 static void
9918 print_strings (char *const *argv)
9919 {
9920   int argc;
9921
9922   printf (\"[\");
9923   for (argc = 0; argv[argc] != NULL; ++argc) {
9924     if (argc > 0) printf (\", \");
9925     printf (\"\\\"%%s\\\"\", argv[argc]);
9926   }
9927   printf (\"]\\n\");
9928 }
9929
9930 /* The test0 function prints its parameters to stdout. */
9931 ";
9932
9933   let test0, tests =
9934     match test_functions with
9935     | [] -> assert false
9936     | test0 :: tests -> test0, tests in
9937
9938   let () =
9939     let (name, style, _, _, _, _, _) = test0 in
9940     generate_prototype ~extern:false ~semicolon:false ~newline:true
9941       ~handle:"g" ~prefix:"guestfs__" name style;
9942     pr "{\n";
9943     List.iter (
9944       function
9945       | Pathname n
9946       | Device n | Dev_or_Path n
9947       | String n
9948       | FileIn n
9949       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9950       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9951       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9952       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9953       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9954       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9955     ) (snd style);
9956     pr "  /* Java changes stdout line buffering so we need this: */\n";
9957     pr "  fflush (stdout);\n";
9958     pr "  return 0;\n";
9959     pr "}\n";
9960     pr "\n" in
9961
9962   List.iter (
9963     fun (name, style, _, _, _, _, _) ->
9964       if String.sub name (String.length name - 3) 3 <> "err" then (
9965         pr "/* Test normal return. */\n";
9966         generate_prototype ~extern:false ~semicolon:false ~newline:true
9967           ~handle:"g" ~prefix:"guestfs__" name style;
9968         pr "{\n";
9969         (match fst style with
9970          | RErr ->
9971              pr "  return 0;\n"
9972          | RInt _ ->
9973              pr "  int r;\n";
9974              pr "  sscanf (val, \"%%d\", &r);\n";
9975              pr "  return r;\n"
9976          | RInt64 _ ->
9977              pr "  int64_t r;\n";
9978              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9979              pr "  return r;\n"
9980          | RBool _ ->
9981              pr "  return STREQ (val, \"true\");\n"
9982          | RConstString _
9983          | RConstOptString _ ->
9984              (* Can't return the input string here.  Return a static
9985               * string so we ensure we get a segfault if the caller
9986               * tries to free it.
9987               *)
9988              pr "  return \"static string\";\n"
9989          | RString _ ->
9990              pr "  return strdup (val);\n"
9991          | RStringList _ ->
9992              pr "  char **strs;\n";
9993              pr "  int n, i;\n";
9994              pr "  sscanf (val, \"%%d\", &n);\n";
9995              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9996              pr "  for (i = 0; i < n; ++i) {\n";
9997              pr "    strs[i] = safe_malloc (g, 16);\n";
9998              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9999              pr "  }\n";
10000              pr "  strs[n] = NULL;\n";
10001              pr "  return strs;\n"
10002          | RStruct (_, typ) ->
10003              pr "  struct guestfs_%s *r;\n" typ;
10004              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10005              pr "  return r;\n"
10006          | RStructList (_, typ) ->
10007              pr "  struct guestfs_%s_list *r;\n" typ;
10008              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10009              pr "  sscanf (val, \"%%d\", &r->len);\n";
10010              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10011              pr "  return r;\n"
10012          | RHashtable _ ->
10013              pr "  char **strs;\n";
10014              pr "  int n, i;\n";
10015              pr "  sscanf (val, \"%%d\", &n);\n";
10016              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10017              pr "  for (i = 0; i < n; ++i) {\n";
10018              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10019              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10020              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10021              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10022              pr "  }\n";
10023              pr "  strs[n*2] = NULL;\n";
10024              pr "  return strs;\n"
10025          | RBufferOut _ ->
10026              pr "  return strdup (val);\n"
10027         );
10028         pr "}\n";
10029         pr "\n"
10030       ) else (
10031         pr "/* Test error return. */\n";
10032         generate_prototype ~extern:false ~semicolon:false ~newline:true
10033           ~handle:"g" ~prefix:"guestfs__" name style;
10034         pr "{\n";
10035         pr "  error (g, \"error\");\n";
10036         (match fst style with
10037          | RErr | RInt _ | RInt64 _ | RBool _ ->
10038              pr "  return -1;\n"
10039          | RConstString _ | RConstOptString _
10040          | RString _ | RStringList _ | RStruct _
10041          | RStructList _
10042          | RHashtable _
10043          | RBufferOut _ ->
10044              pr "  return NULL;\n"
10045         );
10046         pr "}\n";
10047         pr "\n"
10048       )
10049   ) tests
10050
10051 and generate_ocaml_bindtests () =
10052   generate_header OCamlStyle GPLv2;
10053
10054   pr "\
10055 let () =
10056   let g = Guestfs.create () in
10057 ";
10058
10059   let mkargs args =
10060     String.concat " " (
10061       List.map (
10062         function
10063         | CallString s -> "\"" ^ s ^ "\""
10064         | CallOptString None -> "None"
10065         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10066         | CallStringList xs ->
10067             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10068         | CallInt i when i >= 0 -> string_of_int i
10069         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10070         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10071         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10072         | CallBool b -> string_of_bool b
10073       ) args
10074     )
10075   in
10076
10077   generate_lang_bindtests (
10078     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10079   );
10080
10081   pr "print_endline \"EOF\"\n"
10082
10083 and generate_perl_bindtests () =
10084   pr "#!/usr/bin/perl -w\n";
10085   generate_header HashStyle GPLv2;
10086
10087   pr "\
10088 use strict;
10089
10090 use Sys::Guestfs;
10091
10092 my $g = Sys::Guestfs->new ();
10093 ";
10094
10095   let mkargs args =
10096     String.concat ", " (
10097       List.map (
10098         function
10099         | CallString s -> "\"" ^ s ^ "\""
10100         | CallOptString None -> "undef"
10101         | CallOptString (Some s) -> sprintf "\"%s\"" s
10102         | CallStringList xs ->
10103             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10104         | CallInt i -> string_of_int i
10105         | CallInt64 i -> Int64.to_string i
10106         | CallBool b -> if b then "1" else "0"
10107       ) args
10108     )
10109   in
10110
10111   generate_lang_bindtests (
10112     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10113   );
10114
10115   pr "print \"EOF\\n\"\n"
10116
10117 and generate_python_bindtests () =
10118   generate_header HashStyle GPLv2;
10119
10120   pr "\
10121 import guestfs
10122
10123 g = guestfs.GuestFS ()
10124 ";
10125
10126   let mkargs args =
10127     String.concat ", " (
10128       List.map (
10129         function
10130         | CallString s -> "\"" ^ s ^ "\""
10131         | CallOptString None -> "None"
10132         | CallOptString (Some s) -> sprintf "\"%s\"" s
10133         | CallStringList xs ->
10134             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10135         | CallInt i -> string_of_int i
10136         | CallInt64 i -> Int64.to_string i
10137         | CallBool b -> if b then "1" else "0"
10138       ) args
10139     )
10140   in
10141
10142   generate_lang_bindtests (
10143     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10144   );
10145
10146   pr "print \"EOF\"\n"
10147
10148 and generate_ruby_bindtests () =
10149   generate_header HashStyle GPLv2;
10150
10151   pr "\
10152 require 'guestfs'
10153
10154 g = Guestfs::create()
10155 ";
10156
10157   let mkargs args =
10158     String.concat ", " (
10159       List.map (
10160         function
10161         | CallString s -> "\"" ^ s ^ "\""
10162         | CallOptString None -> "nil"
10163         | CallOptString (Some s) -> sprintf "\"%s\"" s
10164         | CallStringList xs ->
10165             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10166         | CallInt i -> string_of_int i
10167         | CallInt64 i -> Int64.to_string i
10168         | CallBool b -> string_of_bool b
10169       ) args
10170     )
10171   in
10172
10173   generate_lang_bindtests (
10174     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10175   );
10176
10177   pr "print \"EOF\\n\"\n"
10178
10179 and generate_java_bindtests () =
10180   generate_header CStyle GPLv2;
10181
10182   pr "\
10183 import com.redhat.et.libguestfs.*;
10184
10185 public class Bindtests {
10186     public static void main (String[] argv)
10187     {
10188         try {
10189             GuestFS g = new GuestFS ();
10190 ";
10191
10192   let mkargs args =
10193     String.concat ", " (
10194       List.map (
10195         function
10196         | CallString s -> "\"" ^ s ^ "\""
10197         | CallOptString None -> "null"
10198         | CallOptString (Some s) -> sprintf "\"%s\"" s
10199         | CallStringList xs ->
10200             "new String[]{" ^
10201               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10202         | CallInt i -> string_of_int i
10203         | CallInt64 i -> Int64.to_string i
10204         | CallBool b -> string_of_bool b
10205       ) args
10206     )
10207   in
10208
10209   generate_lang_bindtests (
10210     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10211   );
10212
10213   pr "
10214             System.out.println (\"EOF\");
10215         }
10216         catch (Exception exn) {
10217             System.err.println (exn);
10218             System.exit (1);
10219         }
10220     }
10221 }
10222 "
10223
10224 and generate_haskell_bindtests () =
10225   generate_header HaskellStyle GPLv2;
10226
10227   pr "\
10228 module Bindtests where
10229 import qualified Guestfs
10230
10231 main = do
10232   g <- Guestfs.create
10233 ";
10234
10235   let mkargs args =
10236     String.concat " " (
10237       List.map (
10238         function
10239         | CallString s -> "\"" ^ s ^ "\""
10240         | CallOptString None -> "Nothing"
10241         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10242         | CallStringList xs ->
10243             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10244         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10245         | CallInt i -> string_of_int i
10246         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10247         | CallInt64 i -> Int64.to_string i
10248         | CallBool true -> "True"
10249         | CallBool false -> "False"
10250       ) args
10251     )
10252   in
10253
10254   generate_lang_bindtests (
10255     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10256   );
10257
10258   pr "  putStrLn \"EOF\"\n"
10259
10260 (* Language-independent bindings tests - we do it this way to
10261  * ensure there is parity in testing bindings across all languages.
10262  *)
10263 and generate_lang_bindtests call =
10264   call "test0" [CallString "abc"; CallOptString (Some "def");
10265                 CallStringList []; CallBool false;
10266                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10267   call "test0" [CallString "abc"; CallOptString None;
10268                 CallStringList []; CallBool false;
10269                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10270   call "test0" [CallString ""; CallOptString (Some "def");
10271                 CallStringList []; CallBool false;
10272                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10273   call "test0" [CallString ""; CallOptString (Some "");
10274                 CallStringList []; CallBool false;
10275                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10276   call "test0" [CallString "abc"; CallOptString (Some "def");
10277                 CallStringList ["1"]; CallBool false;
10278                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10279   call "test0" [CallString "abc"; CallOptString (Some "def");
10280                 CallStringList ["1"; "2"]; CallBool false;
10281                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10282   call "test0" [CallString "abc"; CallOptString (Some "def");
10283                 CallStringList ["1"]; CallBool true;
10284                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10285   call "test0" [CallString "abc"; CallOptString (Some "def");
10286                 CallStringList ["1"]; CallBool false;
10287                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10288   call "test0" [CallString "abc"; CallOptString (Some "def");
10289                 CallStringList ["1"]; CallBool false;
10290                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10291   call "test0" [CallString "abc"; CallOptString (Some "def");
10292                 CallStringList ["1"]; CallBool false;
10293                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10294   call "test0" [CallString "abc"; CallOptString (Some "def");
10295                 CallStringList ["1"]; CallBool false;
10296                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10297   call "test0" [CallString "abc"; CallOptString (Some "def");
10298                 CallStringList ["1"]; CallBool false;
10299                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10300   call "test0" [CallString "abc"; CallOptString (Some "def");
10301                 CallStringList ["1"]; CallBool false;
10302                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10303
10304 (* XXX Add here tests of the return and error functions. *)
10305
10306 (* This is used to generate the src/MAX_PROC_NR file which
10307  * contains the maximum procedure number, a surrogate for the
10308  * ABI version number.  See src/Makefile.am for the details.
10309  *)
10310 and generate_max_proc_nr () =
10311   let proc_nrs = List.map (
10312     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10313   ) daemon_functions in
10314
10315   let max_proc_nr = List.fold_left max 0 proc_nrs in
10316
10317   pr "%d\n" max_proc_nr
10318
10319 let output_to filename =
10320   let filename_new = filename ^ ".new" in
10321   chan := open_out filename_new;
10322   let close () =
10323     close_out !chan;
10324     chan := Pervasives.stdout;
10325
10326     (* Is the new file different from the current file? *)
10327     if Sys.file_exists filename && files_equal filename filename_new then
10328       unlink filename_new               (* same, so skip it *)
10329     else (
10330       (* different, overwrite old one *)
10331       (try chmod filename 0o644 with Unix_error _ -> ());
10332       rename filename_new filename;
10333       chmod filename 0o444;
10334       printf "written %s\n%!" filename;
10335     )
10336   in
10337   close
10338
10339 let perror msg = function
10340   | Unix_error (err, _, _) ->
10341       eprintf "%s: %s\n" msg (error_message err)
10342   | exn ->
10343       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10344
10345 (* Main program. *)
10346 let () =
10347   let lock_fd =
10348     try openfile "HACKING" [O_RDWR] 0
10349     with
10350     | Unix_error (ENOENT, _, _) ->
10351         eprintf "\
10352 You are probably running this from the wrong directory.
10353 Run it from the top source directory using the command
10354   src/generator.ml
10355 ";
10356         exit 1
10357     | exn ->
10358         perror "open: HACKING" exn;
10359         exit 1 in
10360
10361   (* Acquire a lock so parallel builds won't try to run the generator
10362    * twice at the same time.  Subsequent builds will wait for the first
10363    * one to finish.  Note the lock is released implicitly when the
10364    * program exits.
10365    *)
10366   (try lockf lock_fd F_LOCK 1
10367    with exn ->
10368      perror "lock: HACKING" exn;
10369      exit 1);
10370
10371   check_functions ();
10372
10373   let close = output_to "src/guestfs_protocol.x" in
10374   generate_xdr ();
10375   close ();
10376
10377   let close = output_to "src/guestfs-structs.h" in
10378   generate_structs_h ();
10379   close ();
10380
10381   let close = output_to "src/guestfs-actions.h" in
10382   generate_actions_h ();
10383   close ();
10384
10385   let close = output_to "src/guestfs-internal-actions.h" in
10386   generate_internal_actions_h ();
10387   close ();
10388
10389   let close = output_to "src/guestfs-actions.c" in
10390   generate_client_actions ();
10391   close ();
10392
10393   let close = output_to "daemon/actions.h" in
10394   generate_daemon_actions_h ();
10395   close ();
10396
10397   let close = output_to "daemon/stubs.c" in
10398   generate_daemon_actions ();
10399   close ();
10400
10401   let close = output_to "daemon/names.c" in
10402   generate_daemon_names ();
10403   close ();
10404
10405   let close = output_to "daemon/optgroups.c" in
10406   generate_daemon_optgroups_c ();
10407   close ();
10408
10409   let close = output_to "daemon/optgroups.h" in
10410   generate_daemon_optgroups_h ();
10411   close ();
10412
10413   let close = output_to "capitests/tests.c" in
10414   generate_tests ();
10415   close ();
10416
10417   let close = output_to "src/guestfs-bindtests.c" in
10418   generate_bindtests ();
10419   close ();
10420
10421   let close = output_to "fish/cmds.c" in
10422   generate_fish_cmds ();
10423   close ();
10424
10425   let close = output_to "fish/completion.c" in
10426   generate_fish_completion ();
10427   close ();
10428
10429   let close = output_to "guestfs-structs.pod" in
10430   generate_structs_pod ();
10431   close ();
10432
10433   let close = output_to "guestfs-actions.pod" in
10434   generate_actions_pod ();
10435   close ();
10436
10437   let close = output_to "guestfs-availability.pod" in
10438   generate_availability_pod ();
10439   close ();
10440
10441   let close = output_to "guestfish-actions.pod" in
10442   generate_fish_actions_pod ();
10443   close ();
10444
10445   let close = output_to "ocaml/guestfs.mli" in
10446   generate_ocaml_mli ();
10447   close ();
10448
10449   let close = output_to "ocaml/guestfs.ml" in
10450   generate_ocaml_ml ();
10451   close ();
10452
10453   let close = output_to "ocaml/guestfs_c_actions.c" in
10454   generate_ocaml_c ();
10455   close ();
10456
10457   let close = output_to "ocaml/bindtests.ml" in
10458   generate_ocaml_bindtests ();
10459   close ();
10460
10461   let close = output_to "perl/Guestfs.xs" in
10462   generate_perl_xs ();
10463   close ();
10464
10465   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10466   generate_perl_pm ();
10467   close ();
10468
10469   let close = output_to "perl/bindtests.pl" in
10470   generate_perl_bindtests ();
10471   close ();
10472
10473   let close = output_to "python/guestfs-py.c" in
10474   generate_python_c ();
10475   close ();
10476
10477   let close = output_to "python/guestfs.py" in
10478   generate_python_py ();
10479   close ();
10480
10481   let close = output_to "python/bindtests.py" in
10482   generate_python_bindtests ();
10483   close ();
10484
10485   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10486   generate_ruby_c ();
10487   close ();
10488
10489   let close = output_to "ruby/bindtests.rb" in
10490   generate_ruby_bindtests ();
10491   close ();
10492
10493   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10494   generate_java_java ();
10495   close ();
10496
10497   List.iter (
10498     fun (typ, jtyp) ->
10499       let cols = cols_of_struct typ in
10500       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10501       let close = output_to filename in
10502       generate_java_struct jtyp cols;
10503       close ();
10504   ) java_structs;
10505
10506   let close = output_to "java/Makefile.inc" in
10507   generate_java_makefile_inc ();
10508   close ();
10509
10510   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10511   generate_java_c ();
10512   close ();
10513
10514   let close = output_to "java/Bindtests.java" in
10515   generate_java_bindtests ();
10516   close ();
10517
10518   let close = output_to "haskell/Guestfs.hs" in
10519   generate_haskell_hs ();
10520   close ();
10521
10522   let close = output_to "haskell/Bindtests.hs" in
10523   generate_haskell_bindtests ();
10524   close ();
10525
10526   let close = output_to "src/MAX_PROC_NR" in
10527   generate_max_proc_nr ();
10528   close ();
10529
10530   (* Always generate this file last, and unconditionally.  It's used
10531    * by the Makefile to know when we must re-run the generator.
10532    *)
10533   let chan = open_out "src/stamp-generator" in
10534   fprintf chan "1\n";
10535   close_out chan