Make realpath call optional, disable it for Windows.
[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, [Optional "realpath"],
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    [InitNone, Always, TestRun [["available"; ""]]],
4109    "test availability of some parts of the API",
4110    "\
4111 This command is used to check the availability of some
4112 groups of functionality in the appliance, which not all builds of
4113 the libguestfs appliance will be able to provide.
4114
4115 The libguestfs groups, and the functions that those
4116 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4117
4118 The argument C<groups> is a list of group names, eg:
4119 C<[\"inotify\", \"augeas\"]> would check for the availability of
4120 the Linux inotify functions and Augeas (configuration file
4121 editing) functions.
4122
4123 The command returns no error if I<all> requested groups are available.
4124
4125 It fails with an error if one or more of the requested
4126 groups is unavailable in the appliance.
4127
4128 If an unknown group name is included in the
4129 list of 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
4139 The reason is because we don't know what groups are
4140 supported by the appliance/daemon until it is running and can
4141 be queried.
4142
4143 =item *
4144
4145 If a group of functions is available, this does not necessarily
4146 mean that they will work.  You still have to check for errors
4147 when calling individual API functions even if they are
4148 available.
4149
4150 =item *
4151
4152 It is usually the job of distro packagers to build
4153 complete functionality into the libguestfs appliance.
4154 Upstream libguestfs, if built from source with all
4155 requirements satisfied, will support everything.
4156
4157 =item *
4158
4159 This call was added in version C<1.0.80>.  In previous
4160 versions of libguestfs all you could do would be to speculatively
4161 execute a command to find out if the daemon implemented it.
4162 See also C<guestfs_version>.
4163
4164 =back");
4165
4166   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4167    [InitBasicFS, Always, TestOutputBuffer (
4168       [["write_file"; "/src"; "hello, world"; "0"];
4169        ["dd"; "/src"; "/dest"];
4170        ["read_file"; "/dest"]], "hello, world")],
4171    "copy from source to destination using dd",
4172    "\
4173 This command copies from one source device or file C<src>
4174 to another destination device or file C<dest>.  Normally you
4175 would use this to copy to or from a device or partition, for
4176 example to duplicate a filesystem.
4177
4178 If the destination is a device, it must be as large or larger
4179 than the source file or device, otherwise the copy will fail.
4180 This command cannot do partial copies.");
4181
4182 ]
4183
4184 let all_functions = non_daemon_functions @ daemon_functions
4185
4186 (* In some places we want the functions to be displayed sorted
4187  * alphabetically, so this is useful:
4188  *)
4189 let all_functions_sorted =
4190   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4191                compare n1 n2) all_functions
4192
4193 (* Field types for structures. *)
4194 type field =
4195   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4196   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4197   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4198   | FUInt32
4199   | FInt32
4200   | FUInt64
4201   | FInt64
4202   | FBytes                      (* Any int measure that counts bytes. *)
4203   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4204   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4205
4206 (* Because we generate extra parsing code for LVM command line tools,
4207  * we have to pull out the LVM columns separately here.
4208  *)
4209 let lvm_pv_cols = [
4210   "pv_name", FString;
4211   "pv_uuid", FUUID;
4212   "pv_fmt", FString;
4213   "pv_size", FBytes;
4214   "dev_size", FBytes;
4215   "pv_free", FBytes;
4216   "pv_used", FBytes;
4217   "pv_attr", FString (* XXX *);
4218   "pv_pe_count", FInt64;
4219   "pv_pe_alloc_count", FInt64;
4220   "pv_tags", FString;
4221   "pe_start", FBytes;
4222   "pv_mda_count", FInt64;
4223   "pv_mda_free", FBytes;
4224   (* Not in Fedora 10:
4225      "pv_mda_size", FBytes;
4226   *)
4227 ]
4228 let lvm_vg_cols = [
4229   "vg_name", FString;
4230   "vg_uuid", FUUID;
4231   "vg_fmt", FString;
4232   "vg_attr", FString (* XXX *);
4233   "vg_size", FBytes;
4234   "vg_free", FBytes;
4235   "vg_sysid", FString;
4236   "vg_extent_size", FBytes;
4237   "vg_extent_count", FInt64;
4238   "vg_free_count", FInt64;
4239   "max_lv", FInt64;
4240   "max_pv", FInt64;
4241   "pv_count", FInt64;
4242   "lv_count", FInt64;
4243   "snap_count", FInt64;
4244   "vg_seqno", FInt64;
4245   "vg_tags", FString;
4246   "vg_mda_count", FInt64;
4247   "vg_mda_free", FBytes;
4248   (* Not in Fedora 10:
4249      "vg_mda_size", FBytes;
4250   *)
4251 ]
4252 let lvm_lv_cols = [
4253   "lv_name", FString;
4254   "lv_uuid", FUUID;
4255   "lv_attr", FString (* XXX *);
4256   "lv_major", FInt64;
4257   "lv_minor", FInt64;
4258   "lv_kernel_major", FInt64;
4259   "lv_kernel_minor", FInt64;
4260   "lv_size", FBytes;
4261   "seg_count", FInt64;
4262   "origin", FString;
4263   "snap_percent", FOptPercent;
4264   "copy_percent", FOptPercent;
4265   "move_pv", FString;
4266   "lv_tags", FString;
4267   "mirror_log", FString;
4268   "modules", FString;
4269 ]
4270
4271 (* Names and fields in all structures (in RStruct and RStructList)
4272  * that we support.
4273  *)
4274 let structs = [
4275   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4276    * not use this struct in any new code.
4277    *)
4278   "int_bool", [
4279     "i", FInt32;                (* for historical compatibility *)
4280     "b", FInt32;                (* for historical compatibility *)
4281   ];
4282
4283   (* LVM PVs, VGs, LVs. *)
4284   "lvm_pv", lvm_pv_cols;
4285   "lvm_vg", lvm_vg_cols;
4286   "lvm_lv", lvm_lv_cols;
4287
4288   (* Column names and types from stat structures.
4289    * NB. Can't use things like 'st_atime' because glibc header files
4290    * define some of these as macros.  Ugh.
4291    *)
4292   "stat", [
4293     "dev", FInt64;
4294     "ino", FInt64;
4295     "mode", FInt64;
4296     "nlink", FInt64;
4297     "uid", FInt64;
4298     "gid", FInt64;
4299     "rdev", FInt64;
4300     "size", FInt64;
4301     "blksize", FInt64;
4302     "blocks", FInt64;
4303     "atime", FInt64;
4304     "mtime", FInt64;
4305     "ctime", FInt64;
4306   ];
4307   "statvfs", [
4308     "bsize", FInt64;
4309     "frsize", FInt64;
4310     "blocks", FInt64;
4311     "bfree", FInt64;
4312     "bavail", FInt64;
4313     "files", FInt64;
4314     "ffree", FInt64;
4315     "favail", FInt64;
4316     "fsid", FInt64;
4317     "flag", FInt64;
4318     "namemax", FInt64;
4319   ];
4320
4321   (* Column names in dirent structure. *)
4322   "dirent", [
4323     "ino", FInt64;
4324     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4325     "ftyp", FChar;
4326     "name", FString;
4327   ];
4328
4329   (* Version numbers. *)
4330   "version", [
4331     "major", FInt64;
4332     "minor", FInt64;
4333     "release", FInt64;
4334     "extra", FString;
4335   ];
4336
4337   (* Extended attribute. *)
4338   "xattr", [
4339     "attrname", FString;
4340     "attrval", FBuffer;
4341   ];
4342
4343   (* Inotify events. *)
4344   "inotify_event", [
4345     "in_wd", FInt64;
4346     "in_mask", FUInt32;
4347     "in_cookie", FUInt32;
4348     "in_name", FString;
4349   ];
4350
4351   (* Partition table entry. *)
4352   "partition", [
4353     "part_num", FInt32;
4354     "part_start", FBytes;
4355     "part_end", FBytes;
4356     "part_size", FBytes;
4357   ];
4358 ] (* end of structs *)
4359
4360 (* Ugh, Java has to be different ..
4361  * These names are also used by the Haskell bindings.
4362  *)
4363 let java_structs = [
4364   "int_bool", "IntBool";
4365   "lvm_pv", "PV";
4366   "lvm_vg", "VG";
4367   "lvm_lv", "LV";
4368   "stat", "Stat";
4369   "statvfs", "StatVFS";
4370   "dirent", "Dirent";
4371   "version", "Version";
4372   "xattr", "XAttr";
4373   "inotify_event", "INotifyEvent";
4374   "partition", "Partition";
4375 ]
4376
4377 (* What structs are actually returned. *)
4378 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4379
4380 (* Returns a list of RStruct/RStructList structs that are returned
4381  * by any function.  Each element of returned list is a pair:
4382  *
4383  * (structname, RStructOnly)
4384  *    == there exists function which returns RStruct (_, structname)
4385  * (structname, RStructListOnly)
4386  *    == there exists function which returns RStructList (_, structname)
4387  * (structname, RStructAndList)
4388  *    == there are functions returning both RStruct (_, structname)
4389  *                                      and RStructList (_, structname)
4390  *)
4391 let rstructs_used_by functions =
4392   (* ||| is a "logical OR" for rstructs_used_t *)
4393   let (|||) a b =
4394     match a, b with
4395     | RStructAndList, _
4396     | _, RStructAndList -> RStructAndList
4397     | RStructOnly, RStructListOnly
4398     | RStructListOnly, RStructOnly -> RStructAndList
4399     | RStructOnly, RStructOnly -> RStructOnly
4400     | RStructListOnly, RStructListOnly -> RStructListOnly
4401   in
4402
4403   let h = Hashtbl.create 13 in
4404
4405   (* if elem->oldv exists, update entry using ||| operator,
4406    * else just add elem->newv to the hash
4407    *)
4408   let update elem newv =
4409     try  let oldv = Hashtbl.find h elem in
4410          Hashtbl.replace h elem (newv ||| oldv)
4411     with Not_found -> Hashtbl.add h elem newv
4412   in
4413
4414   List.iter (
4415     fun (_, style, _, _, _, _, _) ->
4416       match fst style with
4417       | RStruct (_, structname) -> update structname RStructOnly
4418       | RStructList (_, structname) -> update structname RStructListOnly
4419       | _ -> ()
4420   ) functions;
4421
4422   (* return key->values as a list of (key,value) *)
4423   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4424
4425 (* Used for testing language bindings. *)
4426 type callt =
4427   | CallString of string
4428   | CallOptString of string option
4429   | CallStringList of string list
4430   | CallInt of int
4431   | CallInt64 of int64
4432   | CallBool of bool
4433
4434 (* Used to memoize the result of pod2text. *)
4435 let pod2text_memo_filename = "src/.pod2text.data"
4436 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4437   try
4438     let chan = open_in pod2text_memo_filename in
4439     let v = input_value chan in
4440     close_in chan;
4441     v
4442   with
4443     _ -> Hashtbl.create 13
4444 let pod2text_memo_updated () =
4445   let chan = open_out pod2text_memo_filename in
4446   output_value chan pod2text_memo;
4447   close_out chan
4448
4449 (* Useful functions.
4450  * Note we don't want to use any external OCaml libraries which
4451  * makes this a bit harder than it should be.
4452  *)
4453 let failwithf fs = ksprintf failwith fs
4454
4455 let replace_char s c1 c2 =
4456   let s2 = String.copy s in
4457   let r = ref false in
4458   for i = 0 to String.length s2 - 1 do
4459     if String.unsafe_get s2 i = c1 then (
4460       String.unsafe_set s2 i c2;
4461       r := true
4462     )
4463   done;
4464   if not !r then s else s2
4465
4466 let isspace c =
4467   c = ' '
4468   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4469
4470 let triml ?(test = isspace) str =
4471   let i = ref 0 in
4472   let n = ref (String.length str) in
4473   while !n > 0 && test str.[!i]; do
4474     decr n;
4475     incr i
4476   done;
4477   if !i = 0 then str
4478   else String.sub str !i !n
4479
4480 let trimr ?(test = isspace) str =
4481   let n = ref (String.length str) in
4482   while !n > 0 && test str.[!n-1]; do
4483     decr n
4484   done;
4485   if !n = String.length str then str
4486   else String.sub str 0 !n
4487
4488 let trim ?(test = isspace) str =
4489   trimr ~test (triml ~test str)
4490
4491 let rec find s sub =
4492   let len = String.length s in
4493   let sublen = String.length sub in
4494   let rec loop i =
4495     if i <= len-sublen then (
4496       let rec loop2 j =
4497         if j < sublen then (
4498           if s.[i+j] = sub.[j] then loop2 (j+1)
4499           else -1
4500         ) else
4501           i (* found *)
4502       in
4503       let r = loop2 0 in
4504       if r = -1 then loop (i+1) else r
4505     ) else
4506       -1 (* not found *)
4507   in
4508   loop 0
4509
4510 let rec replace_str s s1 s2 =
4511   let len = String.length s in
4512   let sublen = String.length s1 in
4513   let i = find s s1 in
4514   if i = -1 then s
4515   else (
4516     let s' = String.sub s 0 i in
4517     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4518     s' ^ s2 ^ replace_str s'' s1 s2
4519   )
4520
4521 let rec string_split sep str =
4522   let len = String.length str in
4523   let seplen = String.length sep in
4524   let i = find str sep in
4525   if i = -1 then [str]
4526   else (
4527     let s' = String.sub str 0 i in
4528     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4529     s' :: string_split sep s''
4530   )
4531
4532 let files_equal n1 n2 =
4533   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4534   match Sys.command cmd with
4535   | 0 -> true
4536   | 1 -> false
4537   | i -> failwithf "%s: failed with error code %d" cmd i
4538
4539 let rec filter_map f = function
4540   | [] -> []
4541   | x :: xs ->
4542       match f x with
4543       | Some y -> y :: filter_map f xs
4544       | None -> filter_map f xs
4545
4546 let rec find_map f = function
4547   | [] -> raise Not_found
4548   | x :: xs ->
4549       match f x with
4550       | Some y -> y
4551       | None -> find_map f xs
4552
4553 let iteri f xs =
4554   let rec loop i = function
4555     | [] -> ()
4556     | x :: xs -> f i x; loop (i+1) xs
4557   in
4558   loop 0 xs
4559
4560 let mapi f xs =
4561   let rec loop i = function
4562     | [] -> []
4563     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4564   in
4565   loop 0 xs
4566
4567 let name_of_argt = function
4568   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4569   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4570   | FileIn n | FileOut n -> n
4571
4572 let java_name_of_struct typ =
4573   try List.assoc typ java_structs
4574   with Not_found ->
4575     failwithf
4576       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4577
4578 let cols_of_struct typ =
4579   try List.assoc typ structs
4580   with Not_found ->
4581     failwithf "cols_of_struct: unknown struct %s" typ
4582
4583 let seq_of_test = function
4584   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4585   | TestOutputListOfDevices (s, _)
4586   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4587   | TestOutputTrue s | TestOutputFalse s
4588   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4589   | TestOutputStruct (s, _)
4590   | TestLastFail s -> s
4591
4592 (* Handling for function flags. *)
4593 let protocol_limit_warning =
4594   "Because of the message protocol, there is a transfer limit
4595 of somewhere between 2MB and 4MB.  To transfer large files you should use
4596 FTP."
4597
4598 let danger_will_robinson =
4599   "B<This command is dangerous.  Without careful use you
4600 can easily destroy all your data>."
4601
4602 let deprecation_notice flags =
4603   try
4604     let alt =
4605       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4606     let txt =
4607       sprintf "This function is deprecated.
4608 In new code, use the C<%s> call instead.
4609
4610 Deprecated functions will not be removed from the API, but the
4611 fact that they are deprecated indicates that there are problems
4612 with correct use of these functions." alt in
4613     Some txt
4614   with
4615     Not_found -> None
4616
4617 (* Create list of optional groups. *)
4618 let optgroups =
4619   let h = Hashtbl.create 13 in
4620   List.iter (
4621     fun (name, _, _, flags, _, _, _) ->
4622       List.iter (
4623         function
4624         | Optional group ->
4625             let names = try Hashtbl.find h group with Not_found -> [] in
4626             Hashtbl.replace h group (name :: names)
4627         | _ -> ()
4628       ) flags
4629   ) daemon_functions;
4630   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4631   let groups =
4632     List.map (
4633       fun group -> group, List.sort compare (Hashtbl.find h group)
4634     ) groups in
4635   List.sort (fun x y -> compare (fst x) (fst y)) groups
4636
4637 (* Check function names etc. for consistency. *)
4638 let check_functions () =
4639   let contains_uppercase str =
4640     let len = String.length str in
4641     let rec loop i =
4642       if i >= len then false
4643       else (
4644         let c = str.[i] in
4645         if c >= 'A' && c <= 'Z' then true
4646         else loop (i+1)
4647       )
4648     in
4649     loop 0
4650   in
4651
4652   (* Check function names. *)
4653   List.iter (
4654     fun (name, _, _, _, _, _, _) ->
4655       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4656         failwithf "function name %s does not need 'guestfs' prefix" name;
4657       if name = "" then
4658         failwithf "function name is empty";
4659       if name.[0] < 'a' || name.[0] > 'z' then
4660         failwithf "function name %s must start with lowercase a-z" name;
4661       if String.contains name '-' then
4662         failwithf "function name %s should not contain '-', use '_' instead."
4663           name
4664   ) all_functions;
4665
4666   (* Check function parameter/return names. *)
4667   List.iter (
4668     fun (name, style, _, _, _, _, _) ->
4669       let check_arg_ret_name n =
4670         if contains_uppercase n then
4671           failwithf "%s param/ret %s should not contain uppercase chars"
4672             name n;
4673         if String.contains n '-' || String.contains n '_' then
4674           failwithf "%s param/ret %s should not contain '-' or '_'"
4675             name n;
4676         if n = "value" then
4677           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;
4678         if n = "int" || n = "char" || n = "short" || n = "long" then
4679           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4680         if n = "i" || n = "n" then
4681           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4682         if n = "argv" || n = "args" then
4683           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4684
4685         (* List Haskell, OCaml and C keywords here.
4686          * http://www.haskell.org/haskellwiki/Keywords
4687          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4688          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4689          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4690          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4691          * Omitting _-containing words, since they're handled above.
4692          * Omitting the OCaml reserved word, "val", is ok,
4693          * and saves us from renaming several parameters.
4694          *)
4695         let reserved = [
4696           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4697           "char"; "class"; "const"; "constraint"; "continue"; "data";
4698           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4699           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4700           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4701           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4702           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4703           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4704           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4705           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4706           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4707           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4708           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4709           "volatile"; "when"; "where"; "while";
4710           ] in
4711         if List.mem n reserved then
4712           failwithf "%s has param/ret using reserved word %s" name n;
4713       in
4714
4715       (match fst style with
4716        | RErr -> ()
4717        | RInt n | RInt64 n | RBool n
4718        | RConstString n | RConstOptString n | RString n
4719        | RStringList n | RStruct (n, _) | RStructList (n, _)
4720        | RHashtable n | RBufferOut n ->
4721            check_arg_ret_name n
4722       );
4723       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4724   ) all_functions;
4725
4726   (* Check short descriptions. *)
4727   List.iter (
4728     fun (name, _, _, _, _, shortdesc, _) ->
4729       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4730         failwithf "short description of %s should begin with lowercase." name;
4731       let c = shortdesc.[String.length shortdesc-1] in
4732       if c = '\n' || c = '.' then
4733         failwithf "short description of %s should not end with . or \\n." name
4734   ) all_functions;
4735
4736   (* Check long dscriptions. *)
4737   List.iter (
4738     fun (name, _, _, _, _, _, longdesc) ->
4739       if longdesc.[String.length longdesc-1] = '\n' then
4740         failwithf "long description of %s should not end with \\n." name
4741   ) all_functions;
4742
4743   (* Check proc_nrs. *)
4744   List.iter (
4745     fun (name, _, proc_nr, _, _, _, _) ->
4746       if proc_nr <= 0 then
4747         failwithf "daemon function %s should have proc_nr > 0" name
4748   ) daemon_functions;
4749
4750   List.iter (
4751     fun (name, _, proc_nr, _, _, _, _) ->
4752       if proc_nr <> -1 then
4753         failwithf "non-daemon function %s should have proc_nr -1" name
4754   ) non_daemon_functions;
4755
4756   let proc_nrs =
4757     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4758       daemon_functions in
4759   let proc_nrs =
4760     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4761   let rec loop = function
4762     | [] -> ()
4763     | [_] -> ()
4764     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4765         loop rest
4766     | (name1,nr1) :: (name2,nr2) :: _ ->
4767         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4768           name1 name2 nr1 nr2
4769   in
4770   loop proc_nrs;
4771
4772   (* Check tests. *)
4773   List.iter (
4774     function
4775       (* Ignore functions that have no tests.  We generate a
4776        * warning when the user does 'make check' instead.
4777        *)
4778     | name, _, _, _, [], _, _ -> ()
4779     | name, _, _, _, tests, _, _ ->
4780         let funcs =
4781           List.map (
4782             fun (_, _, test) ->
4783               match seq_of_test test with
4784               | [] ->
4785                   failwithf "%s has a test containing an empty sequence" name
4786               | cmds -> List.map List.hd cmds
4787           ) tests in
4788         let funcs = List.flatten funcs in
4789
4790         let tested = List.mem name funcs in
4791
4792         if not tested then
4793           failwithf "function %s has tests but does not test itself" name
4794   ) all_functions
4795
4796 (* 'pr' prints to the current output file. *)
4797 let chan = ref Pervasives.stdout
4798 let pr fs = ksprintf (output_string !chan) fs
4799
4800 (* Generate a header block in a number of standard styles. *)
4801 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4802 type license = GPLv2 | LGPLv2
4803
4804 let generate_header comment license =
4805   let c = match comment with
4806     | CStyle ->     pr "/* "; " *"
4807     | HashStyle ->  pr "# ";  "#"
4808     | OCamlStyle -> pr "(* "; " *"
4809     | HaskellStyle -> pr "{- "; "  " in
4810   pr "libguestfs generated file\n";
4811   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4812   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4813   pr "%s\n" c;
4814   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4815   pr "%s\n" c;
4816   (match license with
4817    | GPLv2 ->
4818        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4819        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4820        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4821        pr "%s (at your option) any later version.\n" c;
4822        pr "%s\n" c;
4823        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4824        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4825        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4826        pr "%s GNU General Public License for more details.\n" c;
4827        pr "%s\n" c;
4828        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4829        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4830        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4831
4832    | LGPLv2 ->
4833        pr "%s This library is free software; you can redistribute it and/or\n" c;
4834        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4835        pr "%s License as published by the Free Software Foundation; either\n" c;
4836        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4837        pr "%s\n" c;
4838        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4839        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4840        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4841        pr "%s Lesser General Public License for more details.\n" c;
4842        pr "%s\n" c;
4843        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4844        pr "%s License along with this library; if not, write to the Free Software\n" c;
4845        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4846   );
4847   (match comment with
4848    | CStyle -> pr " */\n"
4849    | HashStyle -> ()
4850    | OCamlStyle -> pr " *)\n"
4851    | HaskellStyle -> pr "-}\n"
4852   );
4853   pr "\n"
4854
4855 (* Start of main code generation functions below this line. *)
4856
4857 (* Generate the pod documentation for the C API. *)
4858 let rec generate_actions_pod () =
4859   List.iter (
4860     fun (shortname, style, _, flags, _, _, longdesc) ->
4861       if not (List.mem NotInDocs flags) then (
4862         let name = "guestfs_" ^ shortname in
4863         pr "=head2 %s\n\n" name;
4864         pr " ";
4865         generate_prototype ~extern:false ~handle:"handle" name style;
4866         pr "\n\n";
4867         pr "%s\n\n" longdesc;
4868         (match fst style with
4869          | RErr ->
4870              pr "This function returns 0 on success or -1 on error.\n\n"
4871          | RInt _ ->
4872              pr "On error this function returns -1.\n\n"
4873          | RInt64 _ ->
4874              pr "On error this function returns -1.\n\n"
4875          | RBool _ ->
4876              pr "This function returns a C truth value on success or -1 on error.\n\n"
4877          | RConstString _ ->
4878              pr "This function returns a string, or NULL on error.
4879 The string is owned by the guest handle and must I<not> be freed.\n\n"
4880          | RConstOptString _ ->
4881              pr "This function returns a string which may be NULL.
4882 There is way to return an error from this function.
4883 The string is owned by the guest handle and must I<not> be freed.\n\n"
4884          | RString _ ->
4885              pr "This function returns a string, or NULL on error.
4886 I<The caller must free the returned string after use>.\n\n"
4887          | RStringList _ ->
4888              pr "This function returns a NULL-terminated array of strings
4889 (like L<environ(3)>), or NULL if there was an error.
4890 I<The caller must free the strings and the array after use>.\n\n"
4891          | RStruct (_, typ) ->
4892              pr "This function returns a C<struct guestfs_%s *>,
4893 or NULL if there was an error.
4894 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4895          | RStructList (_, typ) ->
4896              pr "This function returns a C<struct guestfs_%s_list *>
4897 (see E<lt>guestfs-structs.hE<gt>),
4898 or NULL if there was an error.
4899 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4900          | RHashtable _ ->
4901              pr "This function returns a NULL-terminated array of
4902 strings, or NULL if there was an error.
4903 The array of strings will always have length C<2n+1>, where
4904 C<n> keys and values alternate, followed by the trailing NULL entry.
4905 I<The caller must free the strings and the array after use>.\n\n"
4906          | RBufferOut _ ->
4907              pr "This function returns a buffer, or NULL on error.
4908 The size of the returned buffer is written to C<*size_r>.
4909 I<The caller must free the returned buffer after use>.\n\n"
4910         );
4911         if List.mem ProtocolLimitWarning flags then
4912           pr "%s\n\n" protocol_limit_warning;
4913         if List.mem DangerWillRobinson flags then
4914           pr "%s\n\n" danger_will_robinson;
4915         match deprecation_notice flags with
4916         | None -> ()
4917         | Some txt -> pr "%s\n\n" txt
4918       )
4919   ) all_functions_sorted
4920
4921 and generate_structs_pod () =
4922   (* Structs documentation. *)
4923   List.iter (
4924     fun (typ, cols) ->
4925       pr "=head2 guestfs_%s\n" typ;
4926       pr "\n";
4927       pr " struct guestfs_%s {\n" typ;
4928       List.iter (
4929         function
4930         | name, FChar -> pr "   char %s;\n" name
4931         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4932         | name, FInt32 -> pr "   int32_t %s;\n" name
4933         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4934         | name, FInt64 -> pr "   int64_t %s;\n" name
4935         | name, FString -> pr "   char *%s;\n" name
4936         | name, FBuffer ->
4937             pr "   /* The next two fields describe a byte array. */\n";
4938             pr "   uint32_t %s_len;\n" name;
4939             pr "   char *%s;\n" name
4940         | name, FUUID ->
4941             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4942             pr "   char %s[32];\n" name
4943         | name, FOptPercent ->
4944             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4945             pr "   float %s;\n" name
4946       ) cols;
4947       pr " };\n";
4948       pr " \n";
4949       pr " struct guestfs_%s_list {\n" typ;
4950       pr "   uint32_t len; /* Number of elements in list. */\n";
4951       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4952       pr " };\n";
4953       pr " \n";
4954       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4955       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4956         typ typ;
4957       pr "\n"
4958   ) structs
4959
4960 and generate_availability_pod () =
4961   (* Availability documentation. *)
4962   pr "=over 4\n";
4963   pr "\n";
4964   List.iter (
4965     fun (group, functions) ->
4966       pr "=item B<%s>\n" group;
4967       pr "\n";
4968       pr "The following functions:\n";
4969       List.iter (pr "L</guestfs_%s>\n") functions;
4970       pr "\n"
4971   ) optgroups;
4972   pr "=back\n";
4973   pr "\n"
4974
4975 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4976  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4977  *
4978  * We have to use an underscore instead of a dash because otherwise
4979  * rpcgen generates incorrect code.
4980  *
4981  * This header is NOT exported to clients, but see also generate_structs_h.
4982  *)
4983 and generate_xdr () =
4984   generate_header CStyle LGPLv2;
4985
4986   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4987   pr "typedef string str<>;\n";
4988   pr "\n";
4989
4990   (* Internal structures. *)
4991   List.iter (
4992     function
4993     | typ, cols ->
4994         pr "struct guestfs_int_%s {\n" typ;
4995         List.iter (function
4996                    | name, FChar -> pr "  char %s;\n" name
4997                    | name, FString -> pr "  string %s<>;\n" name
4998                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4999                    | name, FUUID -> pr "  opaque %s[32];\n" name
5000                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5001                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5002                    | name, FOptPercent -> pr "  float %s;\n" name
5003                   ) cols;
5004         pr "};\n";
5005         pr "\n";
5006         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5007         pr "\n";
5008   ) structs;
5009
5010   List.iter (
5011     fun (shortname, style, _, _, _, _, _) ->
5012       let name = "guestfs_" ^ shortname in
5013
5014       (match snd style with
5015        | [] -> ()
5016        | args ->
5017            pr "struct %s_args {\n" name;
5018            List.iter (
5019              function
5020              | Pathname n | Device n | Dev_or_Path n | String n ->
5021                  pr "  string %s<>;\n" n
5022              | OptString n -> pr "  str *%s;\n" n
5023              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5024              | Bool n -> pr "  bool %s;\n" n
5025              | Int n -> pr "  int %s;\n" n
5026              | Int64 n -> pr "  hyper %s;\n" n
5027              | FileIn _ | FileOut _ -> ()
5028            ) args;
5029            pr "};\n\n"
5030       );
5031       (match fst style with
5032        | RErr -> ()
5033        | RInt n ->
5034            pr "struct %s_ret {\n" name;
5035            pr "  int %s;\n" n;
5036            pr "};\n\n"
5037        | RInt64 n ->
5038            pr "struct %s_ret {\n" name;
5039            pr "  hyper %s;\n" n;
5040            pr "};\n\n"
5041        | RBool n ->
5042            pr "struct %s_ret {\n" name;
5043            pr "  bool %s;\n" n;
5044            pr "};\n\n"
5045        | RConstString _ | RConstOptString _ ->
5046            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5047        | RString n ->
5048            pr "struct %s_ret {\n" name;
5049            pr "  string %s<>;\n" n;
5050            pr "};\n\n"
5051        | RStringList n ->
5052            pr "struct %s_ret {\n" name;
5053            pr "  str %s<>;\n" n;
5054            pr "};\n\n"
5055        | RStruct (n, typ) ->
5056            pr "struct %s_ret {\n" name;
5057            pr "  guestfs_int_%s %s;\n" typ n;
5058            pr "};\n\n"
5059        | RStructList (n, typ) ->
5060            pr "struct %s_ret {\n" name;
5061            pr "  guestfs_int_%s_list %s;\n" typ n;
5062            pr "};\n\n"
5063        | RHashtable n ->
5064            pr "struct %s_ret {\n" name;
5065            pr "  str %s<>;\n" n;
5066            pr "};\n\n"
5067        | RBufferOut n ->
5068            pr "struct %s_ret {\n" name;
5069            pr "  opaque %s<>;\n" n;
5070            pr "};\n\n"
5071       );
5072   ) daemon_functions;
5073
5074   (* Table of procedure numbers. *)
5075   pr "enum guestfs_procedure {\n";
5076   List.iter (
5077     fun (shortname, _, proc_nr, _, _, _, _) ->
5078       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5079   ) daemon_functions;
5080   pr "  GUESTFS_PROC_NR_PROCS\n";
5081   pr "};\n";
5082   pr "\n";
5083
5084   (* Having to choose a maximum message size is annoying for several
5085    * reasons (it limits what we can do in the API), but it (a) makes
5086    * the protocol a lot simpler, and (b) provides a bound on the size
5087    * of the daemon which operates in limited memory space.  For large
5088    * file transfers you should use FTP.
5089    *)
5090   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5091   pr "\n";
5092
5093   (* Message header, etc. *)
5094   pr "\
5095 /* The communication protocol is now documented in the guestfs(3)
5096  * manpage.
5097  */
5098
5099 const GUESTFS_PROGRAM = 0x2000F5F5;
5100 const GUESTFS_PROTOCOL_VERSION = 1;
5101
5102 /* These constants must be larger than any possible message length. */
5103 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5104 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5105
5106 enum guestfs_message_direction {
5107   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5108   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5109 };
5110
5111 enum guestfs_message_status {
5112   GUESTFS_STATUS_OK = 0,
5113   GUESTFS_STATUS_ERROR = 1
5114 };
5115
5116 const GUESTFS_ERROR_LEN = 256;
5117
5118 struct guestfs_message_error {
5119   string error_message<GUESTFS_ERROR_LEN>;
5120 };
5121
5122 struct guestfs_message_header {
5123   unsigned prog;                     /* GUESTFS_PROGRAM */
5124   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5125   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5126   guestfs_message_direction direction;
5127   unsigned serial;                   /* message serial number */
5128   guestfs_message_status status;
5129 };
5130
5131 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5132
5133 struct guestfs_chunk {
5134   int cancel;                        /* if non-zero, transfer is cancelled */
5135   /* data size is 0 bytes if the transfer has finished successfully */
5136   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5137 };
5138 "
5139
5140 (* Generate the guestfs-structs.h file. *)
5141 and generate_structs_h () =
5142   generate_header CStyle LGPLv2;
5143
5144   (* This is a public exported header file containing various
5145    * structures.  The structures are carefully written to have
5146    * exactly the same in-memory format as the XDR structures that
5147    * we use on the wire to the daemon.  The reason for creating
5148    * copies of these structures here is just so we don't have to
5149    * export the whole of guestfs_protocol.h (which includes much
5150    * unrelated and XDR-dependent stuff that we don't want to be
5151    * public, or required by clients).
5152    *
5153    * To reiterate, we will pass these structures to and from the
5154    * client with a simple assignment or memcpy, so the format
5155    * must be identical to what rpcgen / the RFC defines.
5156    *)
5157
5158   (* Public structures. *)
5159   List.iter (
5160     fun (typ, cols) ->
5161       pr "struct guestfs_%s {\n" typ;
5162       List.iter (
5163         function
5164         | name, FChar -> pr "  char %s;\n" name
5165         | name, FString -> pr "  char *%s;\n" name
5166         | name, FBuffer ->
5167             pr "  uint32_t %s_len;\n" name;
5168             pr "  char *%s;\n" name
5169         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5170         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5171         | name, FInt32 -> pr "  int32_t %s;\n" name
5172         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5173         | name, FInt64 -> pr "  int64_t %s;\n" name
5174         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5175       ) cols;
5176       pr "};\n";
5177       pr "\n";
5178       pr "struct guestfs_%s_list {\n" typ;
5179       pr "  uint32_t len;\n";
5180       pr "  struct guestfs_%s *val;\n" typ;
5181       pr "};\n";
5182       pr "\n";
5183       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5184       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5185       pr "\n"
5186   ) structs
5187
5188 (* Generate the guestfs-actions.h file. *)
5189 and generate_actions_h () =
5190   generate_header CStyle LGPLv2;
5191   List.iter (
5192     fun (shortname, style, _, _, _, _, _) ->
5193       let name = "guestfs_" ^ shortname in
5194       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5195         name style
5196   ) all_functions
5197
5198 (* Generate the guestfs-internal-actions.h file. *)
5199 and generate_internal_actions_h () =
5200   generate_header CStyle LGPLv2;
5201   List.iter (
5202     fun (shortname, style, _, _, _, _, _) ->
5203       let name = "guestfs__" ^ shortname in
5204       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5205         name style
5206   ) non_daemon_functions
5207
5208 (* Generate the client-side dispatch stubs. *)
5209 and generate_client_actions () =
5210   generate_header CStyle LGPLv2;
5211
5212   pr "\
5213 #include <stdio.h>
5214 #include <stdlib.h>
5215 #include <stdint.h>
5216 #include <inttypes.h>
5217
5218 #include \"guestfs.h\"
5219 #include \"guestfs-internal.h\"
5220 #include \"guestfs-internal-actions.h\"
5221 #include \"guestfs_protocol.h\"
5222
5223 #define error guestfs_error
5224 //#define perrorf guestfs_perrorf
5225 #define safe_malloc guestfs_safe_malloc
5226 #define safe_realloc guestfs_safe_realloc
5227 //#define safe_strdup guestfs_safe_strdup
5228 #define safe_memdup guestfs_safe_memdup
5229
5230 /* Check the return message from a call for validity. */
5231 static int
5232 check_reply_header (guestfs_h *g,
5233                     const struct guestfs_message_header *hdr,
5234                     unsigned int proc_nr, unsigned int serial)
5235 {
5236   if (hdr->prog != GUESTFS_PROGRAM) {
5237     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5238     return -1;
5239   }
5240   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5241     error (g, \"wrong protocol version (%%d/%%d)\",
5242            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5243     return -1;
5244   }
5245   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5246     error (g, \"unexpected message direction (%%d/%%d)\",
5247            hdr->direction, GUESTFS_DIRECTION_REPLY);
5248     return -1;
5249   }
5250   if (hdr->proc != proc_nr) {
5251     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5252     return -1;
5253   }
5254   if (hdr->serial != serial) {
5255     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5256     return -1;
5257   }
5258
5259   return 0;
5260 }
5261
5262 /* Check we are in the right state to run a high-level action. */
5263 static int
5264 check_state (guestfs_h *g, const char *caller)
5265 {
5266   if (!guestfs__is_ready (g)) {
5267     if (guestfs__is_config (g) || guestfs__is_launching (g))
5268       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5269         caller);
5270     else
5271       error (g, \"%%s called from the wrong state, %%d != READY\",
5272         caller, guestfs__get_state (g));
5273     return -1;
5274   }
5275   return 0;
5276 }
5277
5278 ";
5279
5280   (* Generate code to generate guestfish call traces. *)
5281   let trace_call shortname style =
5282     pr "  if (guestfs__get_trace (g)) {\n";
5283
5284     let needs_i =
5285       List.exists (function
5286                    | StringList _ | DeviceList _ -> true
5287                    | _ -> false) (snd style) in
5288     if needs_i then (
5289       pr "    int i;\n";
5290       pr "\n"
5291     );
5292
5293     pr "    printf (\"%s\");\n" shortname;
5294     List.iter (
5295       function
5296       | String n                        (* strings *)
5297       | Device n
5298       | Pathname n
5299       | Dev_or_Path n
5300       | FileIn n
5301       | FileOut n ->
5302           (* guestfish doesn't support string escaping, so neither do we *)
5303           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5304       | OptString n ->                  (* string option *)
5305           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5306           pr "    else printf (\" null\");\n"
5307       | StringList n
5308       | DeviceList n ->                 (* string list *)
5309           pr "    putchar (' ');\n";
5310           pr "    putchar ('\"');\n";
5311           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5312           pr "      if (i > 0) putchar (' ');\n";
5313           pr "      fputs (%s[i], stdout);\n" n;
5314           pr "    }\n";
5315           pr "    putchar ('\"');\n";
5316       | Bool n ->                       (* boolean *)
5317           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5318       | Int n ->                        (* int *)
5319           pr "    printf (\" %%d\", %s);\n" n
5320       | Int64 n ->
5321           pr "    printf (\" %%\" PRIi64, %s);\n" n
5322     ) (snd style);
5323     pr "    putchar ('\\n');\n";
5324     pr "  }\n";
5325     pr "\n";
5326   in
5327
5328   (* For non-daemon functions, generate a wrapper around each function. *)
5329   List.iter (
5330     fun (shortname, style, _, _, _, _, _) ->
5331       let name = "guestfs_" ^ shortname in
5332
5333       generate_prototype ~extern:false ~semicolon:false ~newline:true
5334         ~handle:"g" name style;
5335       pr "{\n";
5336       trace_call shortname style;
5337       pr "  return guestfs__%s " shortname;
5338       generate_c_call_args ~handle:"g" style;
5339       pr ";\n";
5340       pr "}\n";
5341       pr "\n"
5342   ) non_daemon_functions;
5343
5344   (* Client-side stubs for each function. *)
5345   List.iter (
5346     fun (shortname, style, _, _, _, _, _) ->
5347       let name = "guestfs_" ^ shortname in
5348
5349       (* Generate the action stub. *)
5350       generate_prototype ~extern:false ~semicolon:false ~newline:true
5351         ~handle:"g" name style;
5352
5353       let error_code =
5354         match fst style with
5355         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5356         | RConstString _ | RConstOptString _ ->
5357             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5358         | RString _ | RStringList _
5359         | RStruct _ | RStructList _
5360         | RHashtable _ | RBufferOut _ ->
5361             "NULL" in
5362
5363       pr "{\n";
5364
5365       (match snd style with
5366        | [] -> ()
5367        | _ -> pr "  struct %s_args args;\n" name
5368       );
5369
5370       pr "  guestfs_message_header hdr;\n";
5371       pr "  guestfs_message_error err;\n";
5372       let has_ret =
5373         match fst style with
5374         | RErr -> false
5375         | RConstString _ | RConstOptString _ ->
5376             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5377         | RInt _ | RInt64 _
5378         | RBool _ | RString _ | RStringList _
5379         | RStruct _ | RStructList _
5380         | RHashtable _ | RBufferOut _ ->
5381             pr "  struct %s_ret ret;\n" name;
5382             true in
5383
5384       pr "  int serial;\n";
5385       pr "  int r;\n";
5386       pr "\n";
5387       trace_call shortname style;
5388       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5389       pr "  guestfs___set_busy (g);\n";
5390       pr "\n";
5391
5392       (* Send the main header and arguments. *)
5393       (match snd style with
5394        | [] ->
5395            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5396              (String.uppercase shortname)
5397        | args ->
5398            List.iter (
5399              function
5400              | Pathname n | Device n | Dev_or_Path n | String n ->
5401                  pr "  args.%s = (char *) %s;\n" n n
5402              | OptString n ->
5403                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5404              | StringList n | DeviceList n ->
5405                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5406                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5407              | Bool n ->
5408                  pr "  args.%s = %s;\n" n n
5409              | Int n ->
5410                  pr "  args.%s = %s;\n" n n
5411              | Int64 n ->
5412                  pr "  args.%s = %s;\n" n n
5413              | FileIn _ | FileOut _ -> ()
5414            ) args;
5415            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5416              (String.uppercase shortname);
5417            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5418              name;
5419       );
5420       pr "  if (serial == -1) {\n";
5421       pr "    guestfs___end_busy (g);\n";
5422       pr "    return %s;\n" error_code;
5423       pr "  }\n";
5424       pr "\n";
5425
5426       (* Send any additional files (FileIn) requested. *)
5427       let need_read_reply_label = ref false in
5428       List.iter (
5429         function
5430         | FileIn n ->
5431             pr "  r = guestfs___send_file (g, %s);\n" n;
5432             pr "  if (r == -1) {\n";
5433             pr "    guestfs___end_busy (g);\n";
5434             pr "    return %s;\n" error_code;
5435             pr "  }\n";
5436             pr "  if (r == -2) /* daemon cancelled */\n";
5437             pr "    goto read_reply;\n";
5438             need_read_reply_label := true;
5439             pr "\n";
5440         | _ -> ()
5441       ) (snd style);
5442
5443       (* Wait for the reply from the remote end. *)
5444       if !need_read_reply_label then pr " read_reply:\n";
5445       pr "  memset (&hdr, 0, sizeof hdr);\n";
5446       pr "  memset (&err, 0, sizeof err);\n";
5447       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5448       pr "\n";
5449       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5450       if not has_ret then
5451         pr "NULL, NULL"
5452       else
5453         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5454       pr ");\n";
5455
5456       pr "  if (r == -1) {\n";
5457       pr "    guestfs___end_busy (g);\n";
5458       pr "    return %s;\n" error_code;
5459       pr "  }\n";
5460       pr "\n";
5461
5462       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5463         (String.uppercase shortname);
5464       pr "    guestfs___end_busy (g);\n";
5465       pr "    return %s;\n" error_code;
5466       pr "  }\n";
5467       pr "\n";
5468
5469       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5470       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5471       pr "    free (err.error_message);\n";
5472       pr "    guestfs___end_busy (g);\n";
5473       pr "    return %s;\n" error_code;
5474       pr "  }\n";
5475       pr "\n";
5476
5477       (* Expecting to receive further files (FileOut)? *)
5478       List.iter (
5479         function
5480         | FileOut n ->
5481             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5482             pr "    guestfs___end_busy (g);\n";
5483             pr "    return %s;\n" error_code;
5484             pr "  }\n";
5485             pr "\n";
5486         | _ -> ()
5487       ) (snd style);
5488
5489       pr "  guestfs___end_busy (g);\n";
5490
5491       (match fst style with
5492        | RErr -> pr "  return 0;\n"
5493        | RInt n | RInt64 n | RBool n ->
5494            pr "  return ret.%s;\n" n
5495        | RConstString _ | RConstOptString _ ->
5496            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5497        | RString n ->
5498            pr "  return ret.%s; /* caller will free */\n" n
5499        | RStringList n | RHashtable n ->
5500            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5501            pr "  ret.%s.%s_val =\n" n n;
5502            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5503            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5504              n n;
5505            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5506            pr "  return ret.%s.%s_val;\n" n n
5507        | RStruct (n, _) ->
5508            pr "  /* caller will free this */\n";
5509            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5510        | RStructList (n, _) ->
5511            pr "  /* caller will free this */\n";
5512            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5513        | RBufferOut n ->
5514            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5515            pr "   * _val might be NULL here.  To make the API saner for\n";
5516            pr "   * callers, we turn this case into a unique pointer (using\n";
5517            pr "   * malloc(1)).\n";
5518            pr "   */\n";
5519            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5520            pr "    *size_r = ret.%s.%s_len;\n" n n;
5521            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5522            pr "  } else {\n";
5523            pr "    free (ret.%s.%s_val);\n" n n;
5524            pr "    char *p = safe_malloc (g, 1);\n";
5525            pr "    *size_r = ret.%s.%s_len;\n" n n;
5526            pr "    return p;\n";
5527            pr "  }\n";
5528       );
5529
5530       pr "}\n\n"
5531   ) daemon_functions;
5532
5533   (* Functions to free structures. *)
5534   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5535   pr " * structure format is identical to the XDR format.  See note in\n";
5536   pr " * generator.ml.\n";
5537   pr " */\n";
5538   pr "\n";
5539
5540   List.iter (
5541     fun (typ, _) ->
5542       pr "void\n";
5543       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5544       pr "{\n";
5545       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5546       pr "  free (x);\n";
5547       pr "}\n";
5548       pr "\n";
5549
5550       pr "void\n";
5551       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5552       pr "{\n";
5553       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5554       pr "  free (x);\n";
5555       pr "}\n";
5556       pr "\n";
5557
5558   ) structs;
5559
5560 (* Generate daemon/actions.h. *)
5561 and generate_daemon_actions_h () =
5562   generate_header CStyle GPLv2;
5563
5564   pr "#include \"../src/guestfs_protocol.h\"\n";
5565   pr "\n";
5566
5567   List.iter (
5568     fun (name, style, _, _, _, _, _) ->
5569       generate_prototype
5570         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5571         name style;
5572   ) daemon_functions
5573
5574 (* Generate the server-side stubs. *)
5575 and generate_daemon_actions () =
5576   generate_header CStyle GPLv2;
5577
5578   pr "#include <config.h>\n";
5579   pr "\n";
5580   pr "#include <stdio.h>\n";
5581   pr "#include <stdlib.h>\n";
5582   pr "#include <string.h>\n";
5583   pr "#include <inttypes.h>\n";
5584   pr "#include <rpc/types.h>\n";
5585   pr "#include <rpc/xdr.h>\n";
5586   pr "\n";
5587   pr "#include \"daemon.h\"\n";
5588   pr "#include \"c-ctype.h\"\n";
5589   pr "#include \"../src/guestfs_protocol.h\"\n";
5590   pr "#include \"actions.h\"\n";
5591   pr "\n";
5592
5593   List.iter (
5594     fun (name, style, _, _, _, _, _) ->
5595       (* Generate server-side stubs. *)
5596       pr "static void %s_stub (XDR *xdr_in)\n" name;
5597       pr "{\n";
5598       let error_code =
5599         match fst style with
5600         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5601         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5602         | RBool _ -> pr "  int r;\n"; "-1"
5603         | RConstString _ | RConstOptString _ ->
5604             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5605         | RString _ -> pr "  char *r;\n"; "NULL"
5606         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5607         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5608         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5609         | RBufferOut _ ->
5610             pr "  size_t size = 1;\n";
5611             pr "  char *r;\n";
5612             "NULL" in
5613
5614       (match snd style with
5615        | [] -> ()
5616        | args ->
5617            pr "  struct guestfs_%s_args args;\n" name;
5618            List.iter (
5619              function
5620              | Device n | Dev_or_Path n
5621              | Pathname n
5622              | String n -> ()
5623              | OptString n -> pr "  char *%s;\n" n
5624              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5625              | Bool n -> pr "  int %s;\n" n
5626              | Int n -> pr "  int %s;\n" n
5627              | Int64 n -> pr "  int64_t %s;\n" n
5628              | FileIn _ | FileOut _ -> ()
5629            ) args
5630       );
5631       pr "\n";
5632
5633       (match snd style with
5634        | [] -> ()
5635        | args ->
5636            pr "  memset (&args, 0, sizeof args);\n";
5637            pr "\n";
5638            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5639            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5640            pr "    return;\n";
5641            pr "  }\n";
5642            let pr_args n =
5643              pr "  char *%s = args.%s;\n" n n
5644            in
5645            let pr_list_handling_code n =
5646              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5647              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5648              pr "  if (%s == NULL) {\n" n;
5649              pr "    reply_with_perror (\"realloc\");\n";
5650              pr "    goto done;\n";
5651              pr "  }\n";
5652              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5653              pr "  args.%s.%s_val = %s;\n" n n n;
5654            in
5655            List.iter (
5656              function
5657              | Pathname n ->
5658                  pr_args n;
5659                  pr "  ABS_PATH (%s, goto done);\n" n;
5660              | Device n ->
5661                  pr_args n;
5662                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5663              | Dev_or_Path n ->
5664                  pr_args n;
5665                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5666              | String n -> pr_args n
5667              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5668              | StringList n ->
5669                  pr_list_handling_code n;
5670              | DeviceList n ->
5671                  pr_list_handling_code n;
5672                  pr "  /* Ensure that each is a device,\n";
5673                  pr "   * and perform device name translation. */\n";
5674                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5675                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5676                  pr "  }\n";
5677              | Bool n -> pr "  %s = args.%s;\n" n n
5678              | Int n -> pr "  %s = args.%s;\n" n n
5679              | Int64 n -> pr "  %s = args.%s;\n" n n
5680              | FileIn _ | FileOut _ -> ()
5681            ) args;
5682            pr "\n"
5683       );
5684
5685
5686       (* this is used at least for do_equal *)
5687       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5688         (* Emit NEED_ROOT just once, even when there are two or
5689            more Pathname args *)
5690         pr "  NEED_ROOT (goto done);\n";
5691       );
5692
5693       (* Don't want to call the impl with any FileIn or FileOut
5694        * parameters, since these go "outside" the RPC protocol.
5695        *)
5696       let args' =
5697         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5698           (snd style) in
5699       pr "  r = do_%s " name;
5700       generate_c_call_args (fst style, args');
5701       pr ";\n";
5702
5703       (match fst style with
5704        | RErr | RInt _ | RInt64 _ | RBool _
5705        | RConstString _ | RConstOptString _
5706        | RString _ | RStringList _ | RHashtable _
5707        | RStruct (_, _) | RStructList (_, _) ->
5708            pr "  if (r == %s)\n" error_code;
5709            pr "    /* do_%s has already called reply_with_error */\n" name;
5710            pr "    goto done;\n";
5711            pr "\n"
5712        | RBufferOut _ ->
5713            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5714            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5715            pr "   */\n";
5716            pr "  if (size == 1 && r == %s)\n" error_code;
5717            pr "    /* do_%s has already called reply_with_error */\n" name;
5718            pr "    goto done;\n";
5719            pr "\n"
5720       );
5721
5722       (* If there are any FileOut parameters, then the impl must
5723        * send its own reply.
5724        *)
5725       let no_reply =
5726         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5727       if no_reply then
5728         pr "  /* do_%s has already sent a reply */\n" name
5729       else (
5730         match fst style with
5731         | RErr -> pr "  reply (NULL, NULL);\n"
5732         | RInt n | RInt64 n | RBool n ->
5733             pr "  struct guestfs_%s_ret ret;\n" name;
5734             pr "  ret.%s = r;\n" n;
5735             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5736               name
5737         | RConstString _ | RConstOptString _ ->
5738             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5739         | RString n ->
5740             pr "  struct guestfs_%s_ret ret;\n" name;
5741             pr "  ret.%s = r;\n" n;
5742             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5743               name;
5744             pr "  free (r);\n"
5745         | RStringList n | RHashtable n ->
5746             pr "  struct guestfs_%s_ret ret;\n" name;
5747             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5748             pr "  ret.%s.%s_val = r;\n" n n;
5749             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5750               name;
5751             pr "  free_strings (r);\n"
5752         | RStruct (n, _) ->
5753             pr "  struct guestfs_%s_ret ret;\n" name;
5754             pr "  ret.%s = *r;\n" n;
5755             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5756               name;
5757             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5758               name
5759         | RStructList (n, _) ->
5760             pr "  struct guestfs_%s_ret ret;\n" name;
5761             pr "  ret.%s = *r;\n" n;
5762             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5763               name;
5764             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5765               name
5766         | RBufferOut n ->
5767             pr "  struct guestfs_%s_ret ret;\n" name;
5768             pr "  ret.%s.%s_val = r;\n" n n;
5769             pr "  ret.%s.%s_len = size;\n" n n;
5770             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5771               name;
5772             pr "  free (r);\n"
5773       );
5774
5775       (* Free the args. *)
5776       (match snd style with
5777        | [] ->
5778            pr "done: ;\n";
5779        | _ ->
5780            pr "done:\n";
5781            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5782              name
5783       );
5784
5785       pr "}\n\n";
5786   ) daemon_functions;
5787
5788   (* Dispatch function. *)
5789   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5790   pr "{\n";
5791   pr "  switch (proc_nr) {\n";
5792
5793   List.iter (
5794     fun (name, style, _, _, _, _, _) ->
5795       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5796       pr "      %s_stub (xdr_in);\n" name;
5797       pr "      break;\n"
5798   ) daemon_functions;
5799
5800   pr "    default:\n";
5801   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";
5802   pr "  }\n";
5803   pr "}\n";
5804   pr "\n";
5805
5806   (* LVM columns and tokenization functions. *)
5807   (* XXX This generates crap code.  We should rethink how we
5808    * do this parsing.
5809    *)
5810   List.iter (
5811     function
5812     | typ, cols ->
5813         pr "static const char *lvm_%s_cols = \"%s\";\n"
5814           typ (String.concat "," (List.map fst cols));
5815         pr "\n";
5816
5817         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5818         pr "{\n";
5819         pr "  char *tok, *p, *next;\n";
5820         pr "  int i, j;\n";
5821         pr "\n";
5822         (*
5823           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5824           pr "\n";
5825         *)
5826         pr "  if (!str) {\n";
5827         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5828         pr "    return -1;\n";
5829         pr "  }\n";
5830         pr "  if (!*str || c_isspace (*str)) {\n";
5831         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5832         pr "    return -1;\n";
5833         pr "  }\n";
5834         pr "  tok = str;\n";
5835         List.iter (
5836           fun (name, coltype) ->
5837             pr "  if (!tok) {\n";
5838             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5839             pr "    return -1;\n";
5840             pr "  }\n";
5841             pr "  p = strchrnul (tok, ',');\n";
5842             pr "  if (*p) next = p+1; else next = NULL;\n";
5843             pr "  *p = '\\0';\n";
5844             (match coltype with
5845              | FString ->
5846                  pr "  r->%s = strdup (tok);\n" name;
5847                  pr "  if (r->%s == NULL) {\n" name;
5848                  pr "    perror (\"strdup\");\n";
5849                  pr "    return -1;\n";
5850                  pr "  }\n"
5851              | FUUID ->
5852                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5853                  pr "    if (tok[j] == '\\0') {\n";
5854                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5855                  pr "      return -1;\n";
5856                  pr "    } else if (tok[j] != '-')\n";
5857                  pr "      r->%s[i++] = tok[j];\n" name;
5858                  pr "  }\n";
5859              | FBytes ->
5860                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5861                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5862                  pr "    return -1;\n";
5863                  pr "  }\n";
5864              | FInt64 ->
5865                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5866                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5867                  pr "    return -1;\n";
5868                  pr "  }\n";
5869              | FOptPercent ->
5870                  pr "  if (tok[0] == '\\0')\n";
5871                  pr "    r->%s = -1;\n" name;
5872                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5873                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5874                  pr "    return -1;\n";
5875                  pr "  }\n";
5876              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5877                  assert false (* can never be an LVM column *)
5878             );
5879             pr "  tok = next;\n";
5880         ) cols;
5881
5882         pr "  if (tok != NULL) {\n";
5883         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5884         pr "    return -1;\n";
5885         pr "  }\n";
5886         pr "  return 0;\n";
5887         pr "}\n";
5888         pr "\n";
5889
5890         pr "guestfs_int_lvm_%s_list *\n" typ;
5891         pr "parse_command_line_%ss (void)\n" typ;
5892         pr "{\n";
5893         pr "  char *out, *err;\n";
5894         pr "  char *p, *pend;\n";
5895         pr "  int r, i;\n";
5896         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5897         pr "  void *newp;\n";
5898         pr "\n";
5899         pr "  ret = malloc (sizeof *ret);\n";
5900         pr "  if (!ret) {\n";
5901         pr "    reply_with_perror (\"malloc\");\n";
5902         pr "    return NULL;\n";
5903         pr "  }\n";
5904         pr "\n";
5905         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5906         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5907         pr "\n";
5908         pr "  r = command (&out, &err,\n";
5909         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5910         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5911         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5912         pr "  if (r == -1) {\n";
5913         pr "    reply_with_error (\"%%s\", err);\n";
5914         pr "    free (out);\n";
5915         pr "    free (err);\n";
5916         pr "    free (ret);\n";
5917         pr "    return NULL;\n";
5918         pr "  }\n";
5919         pr "\n";
5920         pr "  free (err);\n";
5921         pr "\n";
5922         pr "  /* Tokenize each line of the output. */\n";
5923         pr "  p = out;\n";
5924         pr "  i = 0;\n";
5925         pr "  while (p) {\n";
5926         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5927         pr "    if (pend) {\n";
5928         pr "      *pend = '\\0';\n";
5929         pr "      pend++;\n";
5930         pr "    }\n";
5931         pr "\n";
5932         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5933         pr "      p++;\n";
5934         pr "\n";
5935         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5936         pr "      p = pend;\n";
5937         pr "      continue;\n";
5938         pr "    }\n";
5939         pr "\n";
5940         pr "    /* Allocate some space to store this next entry. */\n";
5941         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5942         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5943         pr "    if (newp == NULL) {\n";
5944         pr "      reply_with_perror (\"realloc\");\n";
5945         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5946         pr "      free (ret);\n";
5947         pr "      free (out);\n";
5948         pr "      return NULL;\n";
5949         pr "    }\n";
5950         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5951         pr "\n";
5952         pr "    /* Tokenize the next entry. */\n";
5953         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5954         pr "    if (r == -1) {\n";
5955         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5956         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5957         pr "      free (ret);\n";
5958         pr "      free (out);\n";
5959         pr "      return NULL;\n";
5960         pr "    }\n";
5961         pr "\n";
5962         pr "    ++i;\n";
5963         pr "    p = pend;\n";
5964         pr "  }\n";
5965         pr "\n";
5966         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5967         pr "\n";
5968         pr "  free (out);\n";
5969         pr "  return ret;\n";
5970         pr "}\n"
5971
5972   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5973
5974 (* Generate a list of function names, for debugging in the daemon.. *)
5975 and generate_daemon_names () =
5976   generate_header CStyle GPLv2;
5977
5978   pr "#include <config.h>\n";
5979   pr "\n";
5980   pr "#include \"daemon.h\"\n";
5981   pr "\n";
5982
5983   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5984   pr "const char *function_names[] = {\n";
5985   List.iter (
5986     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5987   ) daemon_functions;
5988   pr "};\n";
5989
5990 (* Generate the optional groups for the daemon to implement
5991  * guestfs_available.
5992  *)
5993 and generate_daemon_optgroups_c () =
5994   generate_header CStyle GPLv2;
5995
5996   pr "#include <config.h>\n";
5997   pr "\n";
5998   pr "#include \"daemon.h\"\n";
5999   pr "#include \"optgroups.h\"\n";
6000   pr "\n";
6001
6002   pr "struct optgroup optgroups[] = {\n";
6003   List.iter (
6004     fun (group, _) ->
6005       pr "  { \"%s\", optgroup_%s_available },\n" group group
6006   ) optgroups;
6007   pr "  { NULL, NULL }\n";
6008   pr "};\n"
6009
6010 and generate_daemon_optgroups_h () =
6011   generate_header CStyle GPLv2;
6012
6013   List.iter (
6014     fun (group, _) ->
6015       pr "extern int optgroup_%s_available (void);\n" group
6016   ) optgroups
6017
6018 (* Generate the tests. *)
6019 and generate_tests () =
6020   generate_header CStyle GPLv2;
6021
6022   pr "\
6023 #include <stdio.h>
6024 #include <stdlib.h>
6025 #include <string.h>
6026 #include <unistd.h>
6027 #include <sys/types.h>
6028 #include <fcntl.h>
6029
6030 #include \"guestfs.h\"
6031 #include \"guestfs-internal.h\"
6032
6033 static guestfs_h *g;
6034 static int suppress_error = 0;
6035
6036 static void print_error (guestfs_h *g, void *data, const char *msg)
6037 {
6038   if (!suppress_error)
6039     fprintf (stderr, \"%%s\\n\", msg);
6040 }
6041
6042 /* FIXME: nearly identical code appears in fish.c */
6043 static void print_strings (char *const *argv)
6044 {
6045   int argc;
6046
6047   for (argc = 0; argv[argc] != NULL; ++argc)
6048     printf (\"\\t%%s\\n\", argv[argc]);
6049 }
6050
6051 /*
6052 static void print_table (char const *const *argv)
6053 {
6054   int i;
6055
6056   for (i = 0; argv[i] != NULL; i += 2)
6057     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6058 }
6059 */
6060
6061 ";
6062
6063   (* Generate a list of commands which are not tested anywhere. *)
6064   pr "static void no_test_warnings (void)\n";
6065   pr "{\n";
6066
6067   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6068   List.iter (
6069     fun (_, _, _, _, tests, _, _) ->
6070       let tests = filter_map (
6071         function
6072         | (_, (Always|If _|Unless _), test) -> Some test
6073         | (_, Disabled, _) -> None
6074       ) tests in
6075       let seq = List.concat (List.map seq_of_test tests) in
6076       let cmds_tested = List.map List.hd seq in
6077       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6078   ) all_functions;
6079
6080   List.iter (
6081     fun (name, _, _, _, _, _, _) ->
6082       if not (Hashtbl.mem hash name) then
6083         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6084   ) all_functions;
6085
6086   pr "}\n";
6087   pr "\n";
6088
6089   (* Generate the actual tests.  Note that we generate the tests
6090    * in reverse order, deliberately, so that (in general) the
6091    * newest tests run first.  This makes it quicker and easier to
6092    * debug them.
6093    *)
6094   let test_names =
6095     List.map (
6096       fun (name, _, _, flags, tests, _, _) ->
6097         mapi (generate_one_test name flags) tests
6098     ) (List.rev all_functions) in
6099   let test_names = List.concat test_names in
6100   let nr_tests = List.length test_names in
6101
6102   pr "\
6103 int main (int argc, char *argv[])
6104 {
6105   char c = 0;
6106   unsigned long int n_failed = 0;
6107   const char *filename;
6108   int fd;
6109   int nr_tests, test_num = 0;
6110
6111   setbuf (stdout, NULL);
6112
6113   no_test_warnings ();
6114
6115   g = guestfs_create ();
6116   if (g == NULL) {
6117     printf (\"guestfs_create FAILED\\n\");
6118     exit (EXIT_FAILURE);
6119   }
6120
6121   guestfs_set_error_handler (g, print_error, NULL);
6122
6123   guestfs_set_path (g, \"../appliance\");
6124
6125   filename = \"test1.img\";
6126   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6127   if (fd == -1) {
6128     perror (filename);
6129     exit (EXIT_FAILURE);
6130   }
6131   if (lseek (fd, %d, SEEK_SET) == -1) {
6132     perror (\"lseek\");
6133     close (fd);
6134     unlink (filename);
6135     exit (EXIT_FAILURE);
6136   }
6137   if (write (fd, &c, 1) == -1) {
6138     perror (\"write\");
6139     close (fd);
6140     unlink (filename);
6141     exit (EXIT_FAILURE);
6142   }
6143   if (close (fd) == -1) {
6144     perror (filename);
6145     unlink (filename);
6146     exit (EXIT_FAILURE);
6147   }
6148   if (guestfs_add_drive (g, filename) == -1) {
6149     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6150     exit (EXIT_FAILURE);
6151   }
6152
6153   filename = \"test2.img\";
6154   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6155   if (fd == -1) {
6156     perror (filename);
6157     exit (EXIT_FAILURE);
6158   }
6159   if (lseek (fd, %d, SEEK_SET) == -1) {
6160     perror (\"lseek\");
6161     close (fd);
6162     unlink (filename);
6163     exit (EXIT_FAILURE);
6164   }
6165   if (write (fd, &c, 1) == -1) {
6166     perror (\"write\");
6167     close (fd);
6168     unlink (filename);
6169     exit (EXIT_FAILURE);
6170   }
6171   if (close (fd) == -1) {
6172     perror (filename);
6173     unlink (filename);
6174     exit (EXIT_FAILURE);
6175   }
6176   if (guestfs_add_drive (g, filename) == -1) {
6177     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6178     exit (EXIT_FAILURE);
6179   }
6180
6181   filename = \"test3.img\";
6182   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6183   if (fd == -1) {
6184     perror (filename);
6185     exit (EXIT_FAILURE);
6186   }
6187   if (lseek (fd, %d, SEEK_SET) == -1) {
6188     perror (\"lseek\");
6189     close (fd);
6190     unlink (filename);
6191     exit (EXIT_FAILURE);
6192   }
6193   if (write (fd, &c, 1) == -1) {
6194     perror (\"write\");
6195     close (fd);
6196     unlink (filename);
6197     exit (EXIT_FAILURE);
6198   }
6199   if (close (fd) == -1) {
6200     perror (filename);
6201     unlink (filename);
6202     exit (EXIT_FAILURE);
6203   }
6204   if (guestfs_add_drive (g, filename) == -1) {
6205     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6206     exit (EXIT_FAILURE);
6207   }
6208
6209   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6210     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6211     exit (EXIT_FAILURE);
6212   }
6213
6214   if (guestfs_launch (g) == -1) {
6215     printf (\"guestfs_launch FAILED\\n\");
6216     exit (EXIT_FAILURE);
6217   }
6218
6219   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6220   alarm (600);
6221
6222   /* Cancel previous alarm. */
6223   alarm (0);
6224
6225   nr_tests = %d;
6226
6227 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6228
6229   iteri (
6230     fun i test_name ->
6231       pr "  test_num++;\n";
6232       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6233       pr "  if (%s () == -1) {\n" test_name;
6234       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6235       pr "    n_failed++;\n";
6236       pr "  }\n";
6237   ) test_names;
6238   pr "\n";
6239
6240   pr "  guestfs_close (g);\n";
6241   pr "  unlink (\"test1.img\");\n";
6242   pr "  unlink (\"test2.img\");\n";
6243   pr "  unlink (\"test3.img\");\n";
6244   pr "\n";
6245
6246   pr "  if (n_failed > 0) {\n";
6247   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6248   pr "    exit (EXIT_FAILURE);\n";
6249   pr "  }\n";
6250   pr "\n";
6251
6252   pr "  exit (EXIT_SUCCESS);\n";
6253   pr "}\n"
6254
6255 and generate_one_test name flags i (init, prereq, test) =
6256   let test_name = sprintf "test_%s_%d" name i in
6257
6258   pr "\
6259 static int %s_skip (void)
6260 {
6261   const char *str;
6262
6263   str = getenv (\"TEST_ONLY\");
6264   if (str)
6265     return strstr (str, \"%s\") == NULL;
6266   str = getenv (\"SKIP_%s\");
6267   if (str && STREQ (str, \"1\")) return 1;
6268   str = getenv (\"SKIP_TEST_%s\");
6269   if (str && STREQ (str, \"1\")) return 1;
6270   return 0;
6271 }
6272
6273 " test_name name (String.uppercase test_name) (String.uppercase name);
6274
6275   (match prereq with
6276    | Disabled | Always -> ()
6277    | If code | Unless code ->
6278        pr "static int %s_prereq (void)\n" test_name;
6279        pr "{\n";
6280        pr "  %s\n" code;
6281        pr "}\n";
6282        pr "\n";
6283   );
6284
6285   pr "\
6286 static int %s (void)
6287 {
6288   if (%s_skip ()) {
6289     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6290     return 0;
6291   }
6292
6293 " test_name test_name test_name;
6294
6295   (* Optional functions should only be tested if the relevant
6296    * support is available in the daemon.
6297    *)
6298   List.iter (
6299     function
6300     | Optional group ->
6301         pr "  {\n";
6302         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6303         pr "    int r;\n";
6304         pr "    suppress_error = 1;\n";
6305         pr "    r = guestfs_available (g, (char **) groups);\n";
6306         pr "    suppress_error = 0;\n";
6307         pr "    if (r == -1) {\n";
6308         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6309         pr "      return 0;\n";
6310         pr "    }\n";
6311         pr "  }\n";
6312     | _ -> ()
6313   ) flags;
6314
6315   (match prereq with
6316    | Disabled ->
6317        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6318    | If _ ->
6319        pr "  if (! %s_prereq ()) {\n" test_name;
6320        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6321        pr "    return 0;\n";
6322        pr "  }\n";
6323        pr "\n";
6324        generate_one_test_body name i test_name init test;
6325    | Unless _ ->
6326        pr "  if (%s_prereq ()) {\n" test_name;
6327        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6328        pr "    return 0;\n";
6329        pr "  }\n";
6330        pr "\n";
6331        generate_one_test_body name i test_name init test;
6332    | Always ->
6333        generate_one_test_body name i test_name init test
6334   );
6335
6336   pr "  return 0;\n";
6337   pr "}\n";
6338   pr "\n";
6339   test_name
6340
6341 and generate_one_test_body name i test_name init test =
6342   (match init with
6343    | InitNone (* XXX at some point, InitNone and InitEmpty became
6344                * folded together as the same thing.  Really we should
6345                * make InitNone do nothing at all, but the tests may
6346                * need to be checked to make sure this is OK.
6347                *)
6348    | InitEmpty ->
6349        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6350        List.iter (generate_test_command_call test_name)
6351          [["blockdev_setrw"; "/dev/sda"];
6352           ["umount_all"];
6353           ["lvm_remove_all"]]
6354    | InitPartition ->
6355        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6356        List.iter (generate_test_command_call test_name)
6357          [["blockdev_setrw"; "/dev/sda"];
6358           ["umount_all"];
6359           ["lvm_remove_all"];
6360           ["part_disk"; "/dev/sda"; "mbr"]]
6361    | InitBasicFS ->
6362        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6363        List.iter (generate_test_command_call test_name)
6364          [["blockdev_setrw"; "/dev/sda"];
6365           ["umount_all"];
6366           ["lvm_remove_all"];
6367           ["part_disk"; "/dev/sda"; "mbr"];
6368           ["mkfs"; "ext2"; "/dev/sda1"];
6369           ["mount"; "/dev/sda1"; "/"]]
6370    | InitBasicFSonLVM ->
6371        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6372          test_name;
6373        List.iter (generate_test_command_call test_name)
6374          [["blockdev_setrw"; "/dev/sda"];
6375           ["umount_all"];
6376           ["lvm_remove_all"];
6377           ["part_disk"; "/dev/sda"; "mbr"];
6378           ["pvcreate"; "/dev/sda1"];
6379           ["vgcreate"; "VG"; "/dev/sda1"];
6380           ["lvcreate"; "LV"; "VG"; "8"];
6381           ["mkfs"; "ext2"; "/dev/VG/LV"];
6382           ["mount"; "/dev/VG/LV"; "/"]]
6383    | InitISOFS ->
6384        pr "  /* InitISOFS for %s */\n" test_name;
6385        List.iter (generate_test_command_call test_name)
6386          [["blockdev_setrw"; "/dev/sda"];
6387           ["umount_all"];
6388           ["lvm_remove_all"];
6389           ["mount_ro"; "/dev/sdd"; "/"]]
6390   );
6391
6392   let get_seq_last = function
6393     | [] ->
6394         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6395           test_name
6396     | seq ->
6397         let seq = List.rev seq in
6398         List.rev (List.tl seq), List.hd seq
6399   in
6400
6401   match test with
6402   | TestRun seq ->
6403       pr "  /* TestRun for %s (%d) */\n" name i;
6404       List.iter (generate_test_command_call test_name) seq
6405   | TestOutput (seq, expected) ->
6406       pr "  /* TestOutput for %s (%d) */\n" name i;
6407       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6408       let seq, last = get_seq_last seq in
6409       let test () =
6410         pr "    if (STRNEQ (r, expected)) {\n";
6411         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6412         pr "      return -1;\n";
6413         pr "    }\n"
6414       in
6415       List.iter (generate_test_command_call test_name) seq;
6416       generate_test_command_call ~test test_name last
6417   | TestOutputList (seq, expected) ->
6418       pr "  /* TestOutputList for %s (%d) */\n" name i;
6419       let seq, last = get_seq_last seq in
6420       let test () =
6421         iteri (
6422           fun i str ->
6423             pr "    if (!r[%d]) {\n" i;
6424             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6425             pr "      print_strings (r);\n";
6426             pr "      return -1;\n";
6427             pr "    }\n";
6428             pr "    {\n";
6429             pr "      const char *expected = \"%s\";\n" (c_quote str);
6430             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6431             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6432             pr "        return -1;\n";
6433             pr "      }\n";
6434             pr "    }\n"
6435         ) expected;
6436         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6437         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6438           test_name;
6439         pr "      print_strings (r);\n";
6440         pr "      return -1;\n";
6441         pr "    }\n"
6442       in
6443       List.iter (generate_test_command_call test_name) seq;
6444       generate_test_command_call ~test test_name last
6445   | TestOutputListOfDevices (seq, expected) ->
6446       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6447       let seq, last = get_seq_last seq in
6448       let test () =
6449         iteri (
6450           fun i str ->
6451             pr "    if (!r[%d]) {\n" i;
6452             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6453             pr "      print_strings (r);\n";
6454             pr "      return -1;\n";
6455             pr "    }\n";
6456             pr "    {\n";
6457             pr "      const char *expected = \"%s\";\n" (c_quote str);
6458             pr "      r[%d][5] = 's';\n" i;
6459             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6460             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6461             pr "        return -1;\n";
6462             pr "      }\n";
6463             pr "    }\n"
6464         ) expected;
6465         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6466         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6467           test_name;
6468         pr "      print_strings (r);\n";
6469         pr "      return -1;\n";
6470         pr "    }\n"
6471       in
6472       List.iter (generate_test_command_call test_name) seq;
6473       generate_test_command_call ~test test_name last
6474   | TestOutputInt (seq, expected) ->
6475       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6476       let seq, last = get_seq_last seq in
6477       let test () =
6478         pr "    if (r != %d) {\n" expected;
6479         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6480           test_name expected;
6481         pr "               (int) r);\n";
6482         pr "      return -1;\n";
6483         pr "    }\n"
6484       in
6485       List.iter (generate_test_command_call test_name) seq;
6486       generate_test_command_call ~test test_name last
6487   | TestOutputIntOp (seq, op, expected) ->
6488       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6489       let seq, last = get_seq_last seq in
6490       let test () =
6491         pr "    if (! (r %s %d)) {\n" op expected;
6492         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6493           test_name op expected;
6494         pr "               (int) r);\n";
6495         pr "      return -1;\n";
6496         pr "    }\n"
6497       in
6498       List.iter (generate_test_command_call test_name) seq;
6499       generate_test_command_call ~test test_name last
6500   | TestOutputTrue seq ->
6501       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6502       let seq, last = get_seq_last seq in
6503       let test () =
6504         pr "    if (!r) {\n";
6505         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6506           test_name;
6507         pr "      return -1;\n";
6508         pr "    }\n"
6509       in
6510       List.iter (generate_test_command_call test_name) seq;
6511       generate_test_command_call ~test test_name last
6512   | TestOutputFalse seq ->
6513       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6514       let seq, last = get_seq_last seq in
6515       let test () =
6516         pr "    if (r) {\n";
6517         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6518           test_name;
6519         pr "      return -1;\n";
6520         pr "    }\n"
6521       in
6522       List.iter (generate_test_command_call test_name) seq;
6523       generate_test_command_call ~test test_name last
6524   | TestOutputLength (seq, expected) ->
6525       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6526       let seq, last = get_seq_last seq in
6527       let test () =
6528         pr "    int j;\n";
6529         pr "    for (j = 0; j < %d; ++j)\n" expected;
6530         pr "      if (r[j] == NULL) {\n";
6531         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6532           test_name;
6533         pr "        print_strings (r);\n";
6534         pr "        return -1;\n";
6535         pr "      }\n";
6536         pr "    if (r[j] != NULL) {\n";
6537         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6538           test_name;
6539         pr "      print_strings (r);\n";
6540         pr "      return -1;\n";
6541         pr "    }\n"
6542       in
6543       List.iter (generate_test_command_call test_name) seq;
6544       generate_test_command_call ~test test_name last
6545   | TestOutputBuffer (seq, expected) ->
6546       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6547       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6548       let seq, last = get_seq_last seq in
6549       let len = String.length expected in
6550       let test () =
6551         pr "    if (size != %d) {\n" len;
6552         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6553         pr "      return -1;\n";
6554         pr "    }\n";
6555         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6556         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6557         pr "      return -1;\n";
6558         pr "    }\n"
6559       in
6560       List.iter (generate_test_command_call test_name) seq;
6561       generate_test_command_call ~test test_name last
6562   | TestOutputStruct (seq, checks) ->
6563       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6564       let seq, last = get_seq_last seq in
6565       let test () =
6566         List.iter (
6567           function
6568           | CompareWithInt (field, expected) ->
6569               pr "    if (r->%s != %d) {\n" field expected;
6570               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6571                 test_name field expected;
6572               pr "               (int) r->%s);\n" field;
6573               pr "      return -1;\n";
6574               pr "    }\n"
6575           | CompareWithIntOp (field, op, expected) ->
6576               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6577               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6578                 test_name field op expected;
6579               pr "               (int) r->%s);\n" field;
6580               pr "      return -1;\n";
6581               pr "    }\n"
6582           | CompareWithString (field, expected) ->
6583               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6584               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6585                 test_name field expected;
6586               pr "               r->%s);\n" field;
6587               pr "      return -1;\n";
6588               pr "    }\n"
6589           | CompareFieldsIntEq (field1, field2) ->
6590               pr "    if (r->%s != r->%s) {\n" field1 field2;
6591               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6592                 test_name field1 field2;
6593               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6594               pr "      return -1;\n";
6595               pr "    }\n"
6596           | CompareFieldsStrEq (field1, field2) ->
6597               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6598               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6599                 test_name field1 field2;
6600               pr "               r->%s, r->%s);\n" field1 field2;
6601               pr "      return -1;\n";
6602               pr "    }\n"
6603         ) checks
6604       in
6605       List.iter (generate_test_command_call test_name) seq;
6606       generate_test_command_call ~test test_name last
6607   | TestLastFail seq ->
6608       pr "  /* TestLastFail for %s (%d) */\n" name i;
6609       let seq, last = get_seq_last seq in
6610       List.iter (generate_test_command_call test_name) seq;
6611       generate_test_command_call test_name ~expect_error:true last
6612
6613 (* Generate the code to run a command, leaving the result in 'r'.
6614  * If you expect to get an error then you should set expect_error:true.
6615  *)
6616 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6617   match cmd with
6618   | [] -> assert false
6619   | name :: args ->
6620       (* Look up the command to find out what args/ret it has. *)
6621       let style =
6622         try
6623           let _, style, _, _, _, _, _ =
6624             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6625           style
6626         with Not_found ->
6627           failwithf "%s: in test, command %s was not found" test_name name in
6628
6629       if List.length (snd style) <> List.length args then
6630         failwithf "%s: in test, wrong number of args given to %s"
6631           test_name name;
6632
6633       pr "  {\n";
6634
6635       List.iter (
6636         function
6637         | OptString n, "NULL" -> ()
6638         | Pathname n, arg
6639         | Device n, arg
6640         | Dev_or_Path n, arg
6641         | String n, arg
6642         | OptString n, arg ->
6643             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6644         | Int _, _
6645         | Int64 _, _
6646         | Bool _, _
6647         | FileIn _, _ | FileOut _, _ -> ()
6648         | StringList n, "" | DeviceList n, "" ->
6649             pr "    const char *const %s[1] = { NULL };\n" n
6650         | StringList n, arg | DeviceList n, arg ->
6651             let strs = string_split " " arg in
6652             iteri (
6653               fun i str ->
6654                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6655             ) strs;
6656             pr "    const char *const %s[] = {\n" n;
6657             iteri (
6658               fun i _ -> pr "      %s_%d,\n" n i
6659             ) strs;
6660             pr "      NULL\n";
6661             pr "    };\n";
6662       ) (List.combine (snd style) args);
6663
6664       let error_code =
6665         match fst style with
6666         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6667         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6668         | RConstString _ | RConstOptString _ ->
6669             pr "    const char *r;\n"; "NULL"
6670         | RString _ -> pr "    char *r;\n"; "NULL"
6671         | RStringList _ | RHashtable _ ->
6672             pr "    char **r;\n";
6673             pr "    int i;\n";
6674             "NULL"
6675         | RStruct (_, typ) ->
6676             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6677         | RStructList (_, typ) ->
6678             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6679         | RBufferOut _ ->
6680             pr "    char *r;\n";
6681             pr "    size_t size;\n";
6682             "NULL" in
6683
6684       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6685       pr "    r = guestfs_%s (g" name;
6686
6687       (* Generate the parameters. *)
6688       List.iter (
6689         function
6690         | OptString _, "NULL" -> pr ", NULL"
6691         | Pathname n, _
6692         | Device n, _ | Dev_or_Path n, _
6693         | String n, _
6694         | OptString n, _ ->
6695             pr ", %s" n
6696         | FileIn _, arg | FileOut _, arg ->
6697             pr ", \"%s\"" (c_quote arg)
6698         | StringList n, _ | DeviceList n, _ ->
6699             pr ", (char **) %s" n
6700         | Int _, arg ->
6701             let i =
6702               try int_of_string arg
6703               with Failure "int_of_string" ->
6704                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6705             pr ", %d" i
6706         | Int64 _, arg ->
6707             let i =
6708               try Int64.of_string arg
6709               with Failure "int_of_string" ->
6710                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6711             pr ", %Ld" i
6712         | Bool _, arg ->
6713             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6714       ) (List.combine (snd style) args);
6715
6716       (match fst style with
6717        | RBufferOut _ -> pr ", &size"
6718        | _ -> ()
6719       );
6720
6721       pr ");\n";
6722
6723       if not expect_error then
6724         pr "    if (r == %s)\n" error_code
6725       else
6726         pr "    if (r != %s)\n" error_code;
6727       pr "      return -1;\n";
6728
6729       (* Insert the test code. *)
6730       (match test with
6731        | None -> ()
6732        | Some f -> f ()
6733       );
6734
6735       (match fst style with
6736        | RErr | RInt _ | RInt64 _ | RBool _
6737        | RConstString _ | RConstOptString _ -> ()
6738        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6739        | RStringList _ | RHashtable _ ->
6740            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6741            pr "      free (r[i]);\n";
6742            pr "    free (r);\n"
6743        | RStruct (_, typ) ->
6744            pr "    guestfs_free_%s (r);\n" typ
6745        | RStructList (_, typ) ->
6746            pr "    guestfs_free_%s_list (r);\n" typ
6747       );
6748
6749       pr "  }\n"
6750
6751 and c_quote str =
6752   let str = replace_str str "\r" "\\r" in
6753   let str = replace_str str "\n" "\\n" in
6754   let str = replace_str str "\t" "\\t" in
6755   let str = replace_str str "\000" "\\0" in
6756   str
6757
6758 (* Generate a lot of different functions for guestfish. *)
6759 and generate_fish_cmds () =
6760   generate_header CStyle GPLv2;
6761
6762   let all_functions =
6763     List.filter (
6764       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6765     ) all_functions in
6766   let all_functions_sorted =
6767     List.filter (
6768       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6769     ) all_functions_sorted in
6770
6771   pr "#include <stdio.h>\n";
6772   pr "#include <stdlib.h>\n";
6773   pr "#include <string.h>\n";
6774   pr "#include <inttypes.h>\n";
6775   pr "\n";
6776   pr "#include <guestfs.h>\n";
6777   pr "#include \"c-ctype.h\"\n";
6778   pr "#include \"fish.h\"\n";
6779   pr "\n";
6780
6781   (* list_commands function, which implements guestfish -h *)
6782   pr "void list_commands (void)\n";
6783   pr "{\n";
6784   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6785   pr "  list_builtin_commands ();\n";
6786   List.iter (
6787     fun (name, _, _, flags, _, shortdesc, _) ->
6788       let name = replace_char name '_' '-' in
6789       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6790         name shortdesc
6791   ) all_functions_sorted;
6792   pr "  printf (\"    %%s\\n\",";
6793   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6794   pr "}\n";
6795   pr "\n";
6796
6797   (* display_command function, which implements guestfish -h cmd *)
6798   pr "void display_command (const char *cmd)\n";
6799   pr "{\n";
6800   List.iter (
6801     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6802       let name2 = replace_char name '_' '-' in
6803       let alias =
6804         try find_map (function FishAlias n -> Some n | _ -> None) flags
6805         with Not_found -> name in
6806       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6807       let synopsis =
6808         match snd style with
6809         | [] -> name2
6810         | args ->
6811             sprintf "%s %s"
6812               name2 (String.concat " " (List.map name_of_argt args)) in
6813
6814       let warnings =
6815         if List.mem ProtocolLimitWarning flags then
6816           ("\n\n" ^ protocol_limit_warning)
6817         else "" in
6818
6819       (* For DangerWillRobinson commands, we should probably have
6820        * guestfish prompt before allowing you to use them (especially
6821        * in interactive mode). XXX
6822        *)
6823       let warnings =
6824         warnings ^
6825           if List.mem DangerWillRobinson flags then
6826             ("\n\n" ^ danger_will_robinson)
6827           else "" in
6828
6829       let warnings =
6830         warnings ^
6831           match deprecation_notice flags with
6832           | None -> ""
6833           | Some txt -> "\n\n" ^ txt in
6834
6835       let describe_alias =
6836         if name <> alias then
6837           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6838         else "" in
6839
6840       pr "  if (";
6841       pr "STRCASEEQ (cmd, \"%s\")" name;
6842       if name <> name2 then
6843         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6844       if name <> alias then
6845         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6846       pr ")\n";
6847       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6848         name2 shortdesc
6849         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6850          "=head1 DESCRIPTION\n\n" ^
6851          longdesc ^ warnings ^ describe_alias);
6852       pr "  else\n"
6853   ) all_functions;
6854   pr "    display_builtin_command (cmd);\n";
6855   pr "}\n";
6856   pr "\n";
6857
6858   let emit_print_list_function typ =
6859     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6860       typ typ typ;
6861     pr "{\n";
6862     pr "  unsigned int i;\n";
6863     pr "\n";
6864     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6865     pr "    printf (\"[%%d] = {\\n\", i);\n";
6866     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6867     pr "    printf (\"}\\n\");\n";
6868     pr "  }\n";
6869     pr "}\n";
6870     pr "\n";
6871   in
6872
6873   (* print_* functions *)
6874   List.iter (
6875     fun (typ, cols) ->
6876       let needs_i =
6877         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6878
6879       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6880       pr "{\n";
6881       if needs_i then (
6882         pr "  unsigned int i;\n";
6883         pr "\n"
6884       );
6885       List.iter (
6886         function
6887         | name, FString ->
6888             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6889         | name, FUUID ->
6890             pr "  printf (\"%%s%s: \", indent);\n" name;
6891             pr "  for (i = 0; i < 32; ++i)\n";
6892             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6893             pr "  printf (\"\\n\");\n"
6894         | name, FBuffer ->
6895             pr "  printf (\"%%s%s: \", indent);\n" name;
6896             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6897             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6898             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6899             pr "    else\n";
6900             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6901             pr "  printf (\"\\n\");\n"
6902         | name, (FUInt64|FBytes) ->
6903             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6904               name typ name
6905         | name, FInt64 ->
6906             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6907               name typ name
6908         | name, FUInt32 ->
6909             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6910               name typ name
6911         | name, FInt32 ->
6912             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6913               name typ name
6914         | name, FChar ->
6915             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6916               name typ name
6917         | name, FOptPercent ->
6918             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6919               typ name name typ name;
6920             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6921       ) cols;
6922       pr "}\n";
6923       pr "\n";
6924   ) structs;
6925
6926   (* Emit a print_TYPE_list function definition only if that function is used. *)
6927   List.iter (
6928     function
6929     | typ, (RStructListOnly | RStructAndList) ->
6930         (* generate the function for typ *)
6931         emit_print_list_function typ
6932     | typ, _ -> () (* empty *)
6933   ) (rstructs_used_by all_functions);
6934
6935   (* Emit a print_TYPE function definition only if that function is used. *)
6936   List.iter (
6937     function
6938     | typ, (RStructOnly | RStructAndList) ->
6939         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6940         pr "{\n";
6941         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6942         pr "}\n";
6943         pr "\n";
6944     | typ, _ -> () (* empty *)
6945   ) (rstructs_used_by all_functions);
6946
6947   (* run_<action> actions *)
6948   List.iter (
6949     fun (name, style, _, flags, _, _, _) ->
6950       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6951       pr "{\n";
6952       (match fst style with
6953        | RErr
6954        | RInt _
6955        | RBool _ -> pr "  int r;\n"
6956        | RInt64 _ -> pr "  int64_t r;\n"
6957        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6958        | RString _ -> pr "  char *r;\n"
6959        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6960        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6961        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6962        | RBufferOut _ ->
6963            pr "  char *r;\n";
6964            pr "  size_t size;\n";
6965       );
6966       List.iter (
6967         function
6968         | Device n
6969         | String n
6970         | OptString n
6971         | FileIn n
6972         | FileOut n -> pr "  const char *%s;\n" n
6973         | Pathname n
6974         | Dev_or_Path n -> pr "  char *%s;\n" n
6975         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6976         | Bool n -> pr "  int %s;\n" n
6977         | Int n -> pr "  int %s;\n" n
6978         | Int64 n -> pr "  int64_t %s;\n" n
6979       ) (snd style);
6980
6981       (* Check and convert parameters. *)
6982       let argc_expected = List.length (snd style) in
6983       pr "  if (argc != %d) {\n" argc_expected;
6984       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6985         argc_expected;
6986       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6987       pr "    return -1;\n";
6988       pr "  }\n";
6989       iteri (
6990         fun i ->
6991           function
6992           | Device name
6993           | String name ->
6994               pr "  %s = argv[%d];\n" name i
6995           | Pathname name
6996           | Dev_or_Path name ->
6997               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6998               pr "  if (%s == NULL) return -1;\n" name
6999           | OptString name ->
7000               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7001                 name i i
7002           | FileIn name ->
7003               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7004                 name i i
7005           | FileOut name ->
7006               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7007                 name i i
7008           | StringList name | DeviceList name ->
7009               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7010               pr "  if (%s == NULL) return -1;\n" name;
7011           | Bool name ->
7012               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7013           | Int name ->
7014               pr "  %s = atoi (argv[%d]);\n" name i
7015           | Int64 name ->
7016               pr "  %s = atoll (argv[%d]);\n" name i
7017       ) (snd style);
7018
7019       (* Call C API function. *)
7020       let fn =
7021         try find_map (function FishAction n -> Some n | _ -> None) flags
7022         with Not_found -> sprintf "guestfs_%s" name in
7023       pr "  r = %s " fn;
7024       generate_c_call_args ~handle:"g" style;
7025       pr ";\n";
7026
7027       List.iter (
7028         function
7029         | Device name | String name
7030         | OptString name | FileIn name | FileOut name | Bool name
7031         | Int name | Int64 name -> ()
7032         | Pathname name | Dev_or_Path name ->
7033             pr "  free (%s);\n" name
7034         | StringList name | DeviceList name ->
7035             pr "  free_strings (%s);\n" name
7036       ) (snd style);
7037
7038       (* Check return value for errors and display command results. *)
7039       (match fst style with
7040        | RErr -> pr "  return r;\n"
7041        | RInt _ ->
7042            pr "  if (r == -1) return -1;\n";
7043            pr "  printf (\"%%d\\n\", r);\n";
7044            pr "  return 0;\n"
7045        | RInt64 _ ->
7046            pr "  if (r == -1) return -1;\n";
7047            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7048            pr "  return 0;\n"
7049        | RBool _ ->
7050            pr "  if (r == -1) return -1;\n";
7051            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7052            pr "  return 0;\n"
7053        | RConstString _ ->
7054            pr "  if (r == NULL) return -1;\n";
7055            pr "  printf (\"%%s\\n\", r);\n";
7056            pr "  return 0;\n"
7057        | RConstOptString _ ->
7058            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7059            pr "  return 0;\n"
7060        | RString _ ->
7061            pr "  if (r == NULL) return -1;\n";
7062            pr "  printf (\"%%s\\n\", r);\n";
7063            pr "  free (r);\n";
7064            pr "  return 0;\n"
7065        | RStringList _ ->
7066            pr "  if (r == NULL) return -1;\n";
7067            pr "  print_strings (r);\n";
7068            pr "  free_strings (r);\n";
7069            pr "  return 0;\n"
7070        | RStruct (_, typ) ->
7071            pr "  if (r == NULL) return -1;\n";
7072            pr "  print_%s (r);\n" typ;
7073            pr "  guestfs_free_%s (r);\n" typ;
7074            pr "  return 0;\n"
7075        | RStructList (_, typ) ->
7076            pr "  if (r == NULL) return -1;\n";
7077            pr "  print_%s_list (r);\n" typ;
7078            pr "  guestfs_free_%s_list (r);\n" typ;
7079            pr "  return 0;\n"
7080        | RHashtable _ ->
7081            pr "  if (r == NULL) return -1;\n";
7082            pr "  print_table (r);\n";
7083            pr "  free_strings (r);\n";
7084            pr "  return 0;\n"
7085        | RBufferOut _ ->
7086            pr "  if (r == NULL) return -1;\n";
7087            pr "  fwrite (r, size, 1, stdout);\n";
7088            pr "  free (r);\n";
7089            pr "  return 0;\n"
7090       );
7091       pr "}\n";
7092       pr "\n"
7093   ) all_functions;
7094
7095   (* run_action function *)
7096   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7097   pr "{\n";
7098   List.iter (
7099     fun (name, _, _, flags, _, _, _) ->
7100       let name2 = replace_char name '_' '-' in
7101       let alias =
7102         try find_map (function FishAlias n -> Some n | _ -> None) flags
7103         with Not_found -> name in
7104       pr "  if (";
7105       pr "STRCASEEQ (cmd, \"%s\")" name;
7106       if name <> name2 then
7107         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7108       if name <> alias then
7109         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7110       pr ")\n";
7111       pr "    return run_%s (cmd, argc, argv);\n" name;
7112       pr "  else\n";
7113   ) all_functions;
7114   pr "    {\n";
7115   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7116   pr "      return -1;\n";
7117   pr "    }\n";
7118   pr "  return 0;\n";
7119   pr "}\n";
7120   pr "\n"
7121
7122 (* Readline completion for guestfish. *)
7123 and generate_fish_completion () =
7124   generate_header CStyle GPLv2;
7125
7126   let all_functions =
7127     List.filter (
7128       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7129     ) all_functions in
7130
7131   pr "\
7132 #include <config.h>
7133
7134 #include <stdio.h>
7135 #include <stdlib.h>
7136 #include <string.h>
7137
7138 #ifdef HAVE_LIBREADLINE
7139 #include <readline/readline.h>
7140 #endif
7141
7142 #include \"fish.h\"
7143
7144 #ifdef HAVE_LIBREADLINE
7145
7146 static const char *const commands[] = {
7147   BUILTIN_COMMANDS_FOR_COMPLETION,
7148 ";
7149
7150   (* Get the commands, including the aliases.  They don't need to be
7151    * sorted - the generator() function just does a dumb linear search.
7152    *)
7153   let commands =
7154     List.map (
7155       fun (name, _, _, flags, _, _, _) ->
7156         let name2 = replace_char name '_' '-' in
7157         let alias =
7158           try find_map (function FishAlias n -> Some n | _ -> None) flags
7159           with Not_found -> name in
7160
7161         if name <> alias then [name2; alias] else [name2]
7162     ) all_functions in
7163   let commands = List.flatten commands in
7164
7165   List.iter (pr "  \"%s\",\n") commands;
7166
7167   pr "  NULL
7168 };
7169
7170 static char *
7171 generator (const char *text, int state)
7172 {
7173   static int index, len;
7174   const char *name;
7175
7176   if (!state) {
7177     index = 0;
7178     len = strlen (text);
7179   }
7180
7181   rl_attempted_completion_over = 1;
7182
7183   while ((name = commands[index]) != NULL) {
7184     index++;
7185     if (STRCASEEQLEN (name, text, len))
7186       return strdup (name);
7187   }
7188
7189   return NULL;
7190 }
7191
7192 #endif /* HAVE_LIBREADLINE */
7193
7194 char **do_completion (const char *text, int start, int end)
7195 {
7196   char **matches = NULL;
7197
7198 #ifdef HAVE_LIBREADLINE
7199   rl_completion_append_character = ' ';
7200
7201   if (start == 0)
7202     matches = rl_completion_matches (text, generator);
7203   else if (complete_dest_paths)
7204     matches = rl_completion_matches (text, complete_dest_paths_generator);
7205 #endif
7206
7207   return matches;
7208 }
7209 ";
7210
7211 (* Generate the POD documentation for guestfish. *)
7212 and generate_fish_actions_pod () =
7213   let all_functions_sorted =
7214     List.filter (
7215       fun (_, _, _, flags, _, _, _) ->
7216         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7217     ) all_functions_sorted in
7218
7219   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7220
7221   List.iter (
7222     fun (name, style, _, flags, _, _, longdesc) ->
7223       let longdesc =
7224         Str.global_substitute rex (
7225           fun s ->
7226             let sub =
7227               try Str.matched_group 1 s
7228               with Not_found ->
7229                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7230             "C<" ^ replace_char sub '_' '-' ^ ">"
7231         ) longdesc in
7232       let name = replace_char name '_' '-' in
7233       let alias =
7234         try find_map (function FishAlias n -> Some n | _ -> None) flags
7235         with Not_found -> name in
7236
7237       pr "=head2 %s" name;
7238       if name <> alias then
7239         pr " | %s" alias;
7240       pr "\n";
7241       pr "\n";
7242       pr " %s" name;
7243       List.iter (
7244         function
7245         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7246         | OptString n -> pr " %s" n
7247         | StringList n | DeviceList n -> pr " '%s ...'" n
7248         | Bool _ -> pr " true|false"
7249         | Int n -> pr " %s" n
7250         | Int64 n -> pr " %s" n
7251         | FileIn n | FileOut n -> pr " (%s|-)" n
7252       ) (snd style);
7253       pr "\n";
7254       pr "\n";
7255       pr "%s\n\n" longdesc;
7256
7257       if List.exists (function FileIn _ | FileOut _ -> true
7258                       | _ -> false) (snd style) then
7259         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7260
7261       if List.mem ProtocolLimitWarning flags then
7262         pr "%s\n\n" protocol_limit_warning;
7263
7264       if List.mem DangerWillRobinson flags then
7265         pr "%s\n\n" danger_will_robinson;
7266
7267       match deprecation_notice flags with
7268       | None -> ()
7269       | Some txt -> pr "%s\n\n" txt
7270   ) all_functions_sorted
7271
7272 (* Generate a C function prototype. *)
7273 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7274     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7275     ?(prefix = "")
7276     ?handle name style =
7277   if extern then pr "extern ";
7278   if static then pr "static ";
7279   (match fst style with
7280    | RErr -> pr "int "
7281    | RInt _ -> pr "int "
7282    | RInt64 _ -> pr "int64_t "
7283    | RBool _ -> pr "int "
7284    | RConstString _ | RConstOptString _ -> pr "const char *"
7285    | RString _ | RBufferOut _ -> pr "char *"
7286    | RStringList _ | RHashtable _ -> pr "char **"
7287    | RStruct (_, typ) ->
7288        if not in_daemon then pr "struct guestfs_%s *" typ
7289        else pr "guestfs_int_%s *" typ
7290    | RStructList (_, typ) ->
7291        if not in_daemon then pr "struct guestfs_%s_list *" typ
7292        else pr "guestfs_int_%s_list *" typ
7293   );
7294   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7295   pr "%s%s (" prefix name;
7296   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7297     pr "void"
7298   else (
7299     let comma = ref false in
7300     (match handle with
7301      | None -> ()
7302      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7303     );
7304     let next () =
7305       if !comma then (
7306         if single_line then pr ", " else pr ",\n\t\t"
7307       );
7308       comma := true
7309     in
7310     List.iter (
7311       function
7312       | Pathname n
7313       | Device n | Dev_or_Path n
7314       | String n
7315       | OptString n ->
7316           next ();
7317           pr "const char *%s" n
7318       | StringList n | DeviceList n ->
7319           next ();
7320           pr "char *const *%s" n
7321       | Bool n -> next (); pr "int %s" n
7322       | Int n -> next (); pr "int %s" n
7323       | Int64 n -> next (); pr "int64_t %s" n
7324       | FileIn n
7325       | FileOut n ->
7326           if not in_daemon then (next (); pr "const char *%s" n)
7327     ) (snd style);
7328     if is_RBufferOut then (next (); pr "size_t *size_r");
7329   );
7330   pr ")";
7331   if semicolon then pr ";";
7332   if newline then pr "\n"
7333
7334 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7335 and generate_c_call_args ?handle ?(decl = false) style =
7336   pr "(";
7337   let comma = ref false in
7338   let next () =
7339     if !comma then pr ", ";
7340     comma := true
7341   in
7342   (match handle with
7343    | None -> ()
7344    | Some handle -> pr "%s" handle; comma := true
7345   );
7346   List.iter (
7347     fun arg ->
7348       next ();
7349       pr "%s" (name_of_argt arg)
7350   ) (snd style);
7351   (* For RBufferOut calls, add implicit &size parameter. *)
7352   if not decl then (
7353     match fst style with
7354     | RBufferOut _ ->
7355         next ();
7356         pr "&size"
7357     | _ -> ()
7358   );
7359   pr ")"
7360
7361 (* Generate the OCaml bindings interface. *)
7362 and generate_ocaml_mli () =
7363   generate_header OCamlStyle LGPLv2;
7364
7365   pr "\
7366 (** For API documentation you should refer to the C API
7367     in the guestfs(3) manual page.  The OCaml API uses almost
7368     exactly the same calls. *)
7369
7370 type t
7371 (** A [guestfs_h] handle. *)
7372
7373 exception Error of string
7374 (** This exception is raised when there is an error. *)
7375
7376 exception Handle_closed of string
7377 (** This exception is raised if you use a {!Guestfs.t} handle
7378     after calling {!close} on it.  The string is the name of
7379     the function. *)
7380
7381 val create : unit -> t
7382 (** Create a {!Guestfs.t} handle. *)
7383
7384 val close : t -> unit
7385 (** Close the {!Guestfs.t} handle and free up all resources used
7386     by it immediately.
7387
7388     Handles are closed by the garbage collector when they become
7389     unreferenced, but callers can call this in order to provide
7390     predictable cleanup. *)
7391
7392 ";
7393   generate_ocaml_structure_decls ();
7394
7395   (* The actions. *)
7396   List.iter (
7397     fun (name, style, _, _, _, shortdesc, _) ->
7398       generate_ocaml_prototype name style;
7399       pr "(** %s *)\n" shortdesc;
7400       pr "\n"
7401   ) all_functions_sorted
7402
7403 (* Generate the OCaml bindings implementation. *)
7404 and generate_ocaml_ml () =
7405   generate_header OCamlStyle LGPLv2;
7406
7407   pr "\
7408 type t
7409
7410 exception Error of string
7411 exception Handle_closed of string
7412
7413 external create : unit -> t = \"ocaml_guestfs_create\"
7414 external close : t -> unit = \"ocaml_guestfs_close\"
7415
7416 (* Give the exceptions names, so they can be raised from the C code. *)
7417 let () =
7418   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7419   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7420
7421 ";
7422
7423   generate_ocaml_structure_decls ();
7424
7425   (* The actions. *)
7426   List.iter (
7427     fun (name, style, _, _, _, shortdesc, _) ->
7428       generate_ocaml_prototype ~is_external:true name style;
7429   ) all_functions_sorted
7430
7431 (* Generate the OCaml bindings C implementation. *)
7432 and generate_ocaml_c () =
7433   generate_header CStyle LGPLv2;
7434
7435   pr "\
7436 #include <stdio.h>
7437 #include <stdlib.h>
7438 #include <string.h>
7439
7440 #include <caml/config.h>
7441 #include <caml/alloc.h>
7442 #include <caml/callback.h>
7443 #include <caml/fail.h>
7444 #include <caml/memory.h>
7445 #include <caml/mlvalues.h>
7446 #include <caml/signals.h>
7447
7448 #include <guestfs.h>
7449
7450 #include \"guestfs_c.h\"
7451
7452 /* Copy a hashtable of string pairs into an assoc-list.  We return
7453  * the list in reverse order, but hashtables aren't supposed to be
7454  * ordered anyway.
7455  */
7456 static CAMLprim value
7457 copy_table (char * const * argv)
7458 {
7459   CAMLparam0 ();
7460   CAMLlocal5 (rv, pairv, kv, vv, cons);
7461   int i;
7462
7463   rv = Val_int (0);
7464   for (i = 0; argv[i] != NULL; i += 2) {
7465     kv = caml_copy_string (argv[i]);
7466     vv = caml_copy_string (argv[i+1]);
7467     pairv = caml_alloc (2, 0);
7468     Store_field (pairv, 0, kv);
7469     Store_field (pairv, 1, vv);
7470     cons = caml_alloc (2, 0);
7471     Store_field (cons, 1, rv);
7472     rv = cons;
7473     Store_field (cons, 0, pairv);
7474   }
7475
7476   CAMLreturn (rv);
7477 }
7478
7479 ";
7480
7481   (* Struct copy functions. *)
7482
7483   let emit_ocaml_copy_list_function typ =
7484     pr "static CAMLprim value\n";
7485     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7486     pr "{\n";
7487     pr "  CAMLparam0 ();\n";
7488     pr "  CAMLlocal2 (rv, v);\n";
7489     pr "  unsigned int i;\n";
7490     pr "\n";
7491     pr "  if (%ss->len == 0)\n" typ;
7492     pr "    CAMLreturn (Atom (0));\n";
7493     pr "  else {\n";
7494     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7495     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7496     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7497     pr "      caml_modify (&Field (rv, i), v);\n";
7498     pr "    }\n";
7499     pr "    CAMLreturn (rv);\n";
7500     pr "  }\n";
7501     pr "}\n";
7502     pr "\n";
7503   in
7504
7505   List.iter (
7506     fun (typ, cols) ->
7507       let has_optpercent_col =
7508         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7509
7510       pr "static CAMLprim value\n";
7511       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7512       pr "{\n";
7513       pr "  CAMLparam0 ();\n";
7514       if has_optpercent_col then
7515         pr "  CAMLlocal3 (rv, v, v2);\n"
7516       else
7517         pr "  CAMLlocal2 (rv, v);\n";
7518       pr "\n";
7519       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7520       iteri (
7521         fun i col ->
7522           (match col with
7523            | name, FString ->
7524                pr "  v = caml_copy_string (%s->%s);\n" typ name
7525            | name, FBuffer ->
7526                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7527                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7528                  typ name typ name
7529            | name, FUUID ->
7530                pr "  v = caml_alloc_string (32);\n";
7531                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7532            | name, (FBytes|FInt64|FUInt64) ->
7533                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7534            | name, (FInt32|FUInt32) ->
7535                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7536            | name, FOptPercent ->
7537                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7538                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7539                pr "    v = caml_alloc (1, 0);\n";
7540                pr "    Store_field (v, 0, v2);\n";
7541                pr "  } else /* None */\n";
7542                pr "    v = Val_int (0);\n";
7543            | name, FChar ->
7544                pr "  v = Val_int (%s->%s);\n" typ name
7545           );
7546           pr "  Store_field (rv, %d, v);\n" i
7547       ) cols;
7548       pr "  CAMLreturn (rv);\n";
7549       pr "}\n";
7550       pr "\n";
7551   ) structs;
7552
7553   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7554   List.iter (
7555     function
7556     | typ, (RStructListOnly | RStructAndList) ->
7557         (* generate the function for typ *)
7558         emit_ocaml_copy_list_function typ
7559     | typ, _ -> () (* empty *)
7560   ) (rstructs_used_by all_functions);
7561
7562   (* The wrappers. *)
7563   List.iter (
7564     fun (name, style, _, _, _, _, _) ->
7565       pr "/* Automatically generated wrapper for function\n";
7566       pr " * ";
7567       generate_ocaml_prototype name style;
7568       pr " */\n";
7569       pr "\n";
7570
7571       let params =
7572         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7573
7574       let needs_extra_vs =
7575         match fst style with RConstOptString _ -> true | _ -> false in
7576
7577       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7578       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7579       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7580       pr "\n";
7581
7582       pr "CAMLprim value\n";
7583       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7584       List.iter (pr ", value %s") (List.tl params);
7585       pr ")\n";
7586       pr "{\n";
7587
7588       (match params with
7589        | [p1; p2; p3; p4; p5] ->
7590            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7591        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7592            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7593            pr "  CAMLxparam%d (%s);\n"
7594              (List.length rest) (String.concat ", " rest)
7595        | ps ->
7596            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7597       );
7598       if not needs_extra_vs then
7599         pr "  CAMLlocal1 (rv);\n"
7600       else
7601         pr "  CAMLlocal3 (rv, v, v2);\n";
7602       pr "\n";
7603
7604       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7605       pr "  if (g == NULL)\n";
7606       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7607       pr "\n";
7608
7609       List.iter (
7610         function
7611         | Pathname n
7612         | Device n | Dev_or_Path n
7613         | String n
7614         | FileIn n
7615         | FileOut n ->
7616             pr "  const char *%s = String_val (%sv);\n" n n
7617         | OptString n ->
7618             pr "  const char *%s =\n" n;
7619             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7620               n n
7621         | StringList n | DeviceList n ->
7622             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7623         | Bool n ->
7624             pr "  int %s = Bool_val (%sv);\n" n n
7625         | Int n ->
7626             pr "  int %s = Int_val (%sv);\n" n n
7627         | Int64 n ->
7628             pr "  int64_t %s = Int64_val (%sv);\n" n n
7629       ) (snd style);
7630       let error_code =
7631         match fst style with
7632         | RErr -> pr "  int r;\n"; "-1"
7633         | RInt _ -> pr "  int r;\n"; "-1"
7634         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7635         | RBool _ -> pr "  int r;\n"; "-1"
7636         | RConstString _ | RConstOptString _ ->
7637             pr "  const char *r;\n"; "NULL"
7638         | RString _ -> pr "  char *r;\n"; "NULL"
7639         | RStringList _ ->
7640             pr "  int i;\n";
7641             pr "  char **r;\n";
7642             "NULL"
7643         | RStruct (_, typ) ->
7644             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7645         | RStructList (_, typ) ->
7646             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7647         | RHashtable _ ->
7648             pr "  int i;\n";
7649             pr "  char **r;\n";
7650             "NULL"
7651         | RBufferOut _ ->
7652             pr "  char *r;\n";
7653             pr "  size_t size;\n";
7654             "NULL" in
7655       pr "\n";
7656
7657       pr "  caml_enter_blocking_section ();\n";
7658       pr "  r = guestfs_%s " name;
7659       generate_c_call_args ~handle:"g" style;
7660       pr ";\n";
7661       pr "  caml_leave_blocking_section ();\n";
7662
7663       List.iter (
7664         function
7665         | StringList n | DeviceList n ->
7666             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7667         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7668         | Bool _ | Int _ | Int64 _
7669         | FileIn _ | FileOut _ -> ()
7670       ) (snd style);
7671
7672       pr "  if (r == %s)\n" error_code;
7673       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7674       pr "\n";
7675
7676       (match fst style with
7677        | RErr -> pr "  rv = Val_unit;\n"
7678        | RInt _ -> pr "  rv = Val_int (r);\n"
7679        | RInt64 _ ->
7680            pr "  rv = caml_copy_int64 (r);\n"
7681        | RBool _ -> pr "  rv = Val_bool (r);\n"
7682        | RConstString _ ->
7683            pr "  rv = caml_copy_string (r);\n"
7684        | RConstOptString _ ->
7685            pr "  if (r) { /* Some string */\n";
7686            pr "    v = caml_alloc (1, 0);\n";
7687            pr "    v2 = caml_copy_string (r);\n";
7688            pr "    Store_field (v, 0, v2);\n";
7689            pr "  } else /* None */\n";
7690            pr "    v = Val_int (0);\n";
7691        | RString _ ->
7692            pr "  rv = caml_copy_string (r);\n";
7693            pr "  free (r);\n"
7694        | RStringList _ ->
7695            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7696            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7697            pr "  free (r);\n"
7698        | RStruct (_, typ) ->
7699            pr "  rv = copy_%s (r);\n" typ;
7700            pr "  guestfs_free_%s (r);\n" typ;
7701        | RStructList (_, typ) ->
7702            pr "  rv = copy_%s_list (r);\n" typ;
7703            pr "  guestfs_free_%s_list (r);\n" typ;
7704        | RHashtable _ ->
7705            pr "  rv = copy_table (r);\n";
7706            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7707            pr "  free (r);\n";
7708        | RBufferOut _ ->
7709            pr "  rv = caml_alloc_string (size);\n";
7710            pr "  memcpy (String_val (rv), r, size);\n";
7711       );
7712
7713       pr "  CAMLreturn (rv);\n";
7714       pr "}\n";
7715       pr "\n";
7716
7717       if List.length params > 5 then (
7718         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7719         pr "CAMLprim value ";
7720         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7721         pr "CAMLprim value\n";
7722         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7723         pr "{\n";
7724         pr "  return ocaml_guestfs_%s (argv[0]" name;
7725         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7726         pr ");\n";
7727         pr "}\n";
7728         pr "\n"
7729       )
7730   ) all_functions_sorted
7731
7732 and generate_ocaml_structure_decls () =
7733   List.iter (
7734     fun (typ, cols) ->
7735       pr "type %s = {\n" typ;
7736       List.iter (
7737         function
7738         | name, FString -> pr "  %s : string;\n" name
7739         | name, FBuffer -> pr "  %s : string;\n" name
7740         | name, FUUID -> pr "  %s : string;\n" name
7741         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7742         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7743         | name, FChar -> pr "  %s : char;\n" name
7744         | name, FOptPercent -> pr "  %s : float option;\n" name
7745       ) cols;
7746       pr "}\n";
7747       pr "\n"
7748   ) structs
7749
7750 and generate_ocaml_prototype ?(is_external = false) name style =
7751   if is_external then pr "external " else pr "val ";
7752   pr "%s : t -> " name;
7753   List.iter (
7754     function
7755     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7756     | OptString _ -> pr "string option -> "
7757     | StringList _ | DeviceList _ -> pr "string array -> "
7758     | Bool _ -> pr "bool -> "
7759     | Int _ -> pr "int -> "
7760     | Int64 _ -> pr "int64 -> "
7761   ) (snd style);
7762   (match fst style with
7763    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7764    | RInt _ -> pr "int"
7765    | RInt64 _ -> pr "int64"
7766    | RBool _ -> pr "bool"
7767    | RConstString _ -> pr "string"
7768    | RConstOptString _ -> pr "string option"
7769    | RString _ | RBufferOut _ -> pr "string"
7770    | RStringList _ -> pr "string array"
7771    | RStruct (_, typ) -> pr "%s" typ
7772    | RStructList (_, typ) -> pr "%s array" typ
7773    | RHashtable _ -> pr "(string * string) list"
7774   );
7775   if is_external then (
7776     pr " = ";
7777     if List.length (snd style) + 1 > 5 then
7778       pr "\"ocaml_guestfs_%s_byte\" " name;
7779     pr "\"ocaml_guestfs_%s\"" name
7780   );
7781   pr "\n"
7782
7783 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7784 and generate_perl_xs () =
7785   generate_header CStyle LGPLv2;
7786
7787   pr "\
7788 #include \"EXTERN.h\"
7789 #include \"perl.h\"
7790 #include \"XSUB.h\"
7791
7792 #include <guestfs.h>
7793
7794 #ifndef PRId64
7795 #define PRId64 \"lld\"
7796 #endif
7797
7798 static SV *
7799 my_newSVll(long long val) {
7800 #ifdef USE_64_BIT_ALL
7801   return newSViv(val);
7802 #else
7803   char buf[100];
7804   int len;
7805   len = snprintf(buf, 100, \"%%\" PRId64, val);
7806   return newSVpv(buf, len);
7807 #endif
7808 }
7809
7810 #ifndef PRIu64
7811 #define PRIu64 \"llu\"
7812 #endif
7813
7814 static SV *
7815 my_newSVull(unsigned long long val) {
7816 #ifdef USE_64_BIT_ALL
7817   return newSVuv(val);
7818 #else
7819   char buf[100];
7820   int len;
7821   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7822   return newSVpv(buf, len);
7823 #endif
7824 }
7825
7826 /* http://www.perlmonks.org/?node_id=680842 */
7827 static char **
7828 XS_unpack_charPtrPtr (SV *arg) {
7829   char **ret;
7830   AV *av;
7831   I32 i;
7832
7833   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7834     croak (\"array reference expected\");
7835
7836   av = (AV *)SvRV (arg);
7837   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7838   if (!ret)
7839     croak (\"malloc failed\");
7840
7841   for (i = 0; i <= av_len (av); i++) {
7842     SV **elem = av_fetch (av, i, 0);
7843
7844     if (!elem || !*elem)
7845       croak (\"missing element in list\");
7846
7847     ret[i] = SvPV_nolen (*elem);
7848   }
7849
7850   ret[i] = NULL;
7851
7852   return ret;
7853 }
7854
7855 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7856
7857 PROTOTYPES: ENABLE
7858
7859 guestfs_h *
7860 _create ()
7861    CODE:
7862       RETVAL = guestfs_create ();
7863       if (!RETVAL)
7864         croak (\"could not create guestfs handle\");
7865       guestfs_set_error_handler (RETVAL, NULL, NULL);
7866  OUTPUT:
7867       RETVAL
7868
7869 void
7870 DESTROY (g)
7871       guestfs_h *g;
7872  PPCODE:
7873       guestfs_close (g);
7874
7875 ";
7876
7877   List.iter (
7878     fun (name, style, _, _, _, _, _) ->
7879       (match fst style with
7880        | RErr -> pr "void\n"
7881        | RInt _ -> pr "SV *\n"
7882        | RInt64 _ -> pr "SV *\n"
7883        | RBool _ -> pr "SV *\n"
7884        | RConstString _ -> pr "SV *\n"
7885        | RConstOptString _ -> pr "SV *\n"
7886        | RString _ -> pr "SV *\n"
7887        | RBufferOut _ -> pr "SV *\n"
7888        | RStringList _
7889        | RStruct _ | RStructList _
7890        | RHashtable _ ->
7891            pr "void\n" (* all lists returned implictly on the stack *)
7892       );
7893       (* Call and arguments. *)
7894       pr "%s " name;
7895       generate_c_call_args ~handle:"g" ~decl:true style;
7896       pr "\n";
7897       pr "      guestfs_h *g;\n";
7898       iteri (
7899         fun i ->
7900           function
7901           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7902               pr "      char *%s;\n" n
7903           | OptString n ->
7904               (* http://www.perlmonks.org/?node_id=554277
7905                * Note that the implicit handle argument means we have
7906                * to add 1 to the ST(x) operator.
7907                *)
7908               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7909           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7910           | Bool n -> pr "      int %s;\n" n
7911           | Int n -> pr "      int %s;\n" n
7912           | Int64 n -> pr "      int64_t %s;\n" n
7913       ) (snd style);
7914
7915       let do_cleanups () =
7916         List.iter (
7917           function
7918           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7919           | Bool _ | Int _ | Int64 _
7920           | FileIn _ | FileOut _ -> ()
7921           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7922         ) (snd style)
7923       in
7924
7925       (* Code. *)
7926       (match fst style with
7927        | RErr ->
7928            pr "PREINIT:\n";
7929            pr "      int r;\n";
7930            pr " PPCODE:\n";
7931            pr "      r = guestfs_%s " name;
7932            generate_c_call_args ~handle:"g" style;
7933            pr ";\n";
7934            do_cleanups ();
7935            pr "      if (r == -1)\n";
7936            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7937        | RInt n
7938        | RBool n ->
7939            pr "PREINIT:\n";
7940            pr "      int %s;\n" n;
7941            pr "   CODE:\n";
7942            pr "      %s = guestfs_%s " n name;
7943            generate_c_call_args ~handle:"g" style;
7944            pr ";\n";
7945            do_cleanups ();
7946            pr "      if (%s == -1)\n" n;
7947            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7948            pr "      RETVAL = newSViv (%s);\n" n;
7949            pr " OUTPUT:\n";
7950            pr "      RETVAL\n"
7951        | RInt64 n ->
7952            pr "PREINIT:\n";
7953            pr "      int64_t %s;\n" n;
7954            pr "   CODE:\n";
7955            pr "      %s = guestfs_%s " n name;
7956            generate_c_call_args ~handle:"g" style;
7957            pr ";\n";
7958            do_cleanups ();
7959            pr "      if (%s == -1)\n" n;
7960            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7961            pr "      RETVAL = my_newSVll (%s);\n" n;
7962            pr " OUTPUT:\n";
7963            pr "      RETVAL\n"
7964        | RConstString n ->
7965            pr "PREINIT:\n";
7966            pr "      const char *%s;\n" n;
7967            pr "   CODE:\n";
7968            pr "      %s = guestfs_%s " n name;
7969            generate_c_call_args ~handle:"g" style;
7970            pr ";\n";
7971            do_cleanups ();
7972            pr "      if (%s == NULL)\n" n;
7973            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7974            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7975            pr " OUTPUT:\n";
7976            pr "      RETVAL\n"
7977        | RConstOptString n ->
7978            pr "PREINIT:\n";
7979            pr "      const char *%s;\n" n;
7980            pr "   CODE:\n";
7981            pr "      %s = guestfs_%s " n name;
7982            generate_c_call_args ~handle:"g" style;
7983            pr ";\n";
7984            do_cleanups ();
7985            pr "      if (%s == NULL)\n" n;
7986            pr "        RETVAL = &PL_sv_undef;\n";
7987            pr "      else\n";
7988            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7989            pr " OUTPUT:\n";
7990            pr "      RETVAL\n"
7991        | RString n ->
7992            pr "PREINIT:\n";
7993            pr "      char *%s;\n" n;
7994            pr "   CODE:\n";
7995            pr "      %s = guestfs_%s " n name;
7996            generate_c_call_args ~handle:"g" style;
7997            pr ";\n";
7998            do_cleanups ();
7999            pr "      if (%s == NULL)\n" n;
8000            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8001            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8002            pr "      free (%s);\n" n;
8003            pr " OUTPUT:\n";
8004            pr "      RETVAL\n"
8005        | RStringList n | RHashtable n ->
8006            pr "PREINIT:\n";
8007            pr "      char **%s;\n" n;
8008            pr "      int i, n;\n";
8009            pr " PPCODE:\n";
8010            pr "      %s = guestfs_%s " n name;
8011            generate_c_call_args ~handle:"g" style;
8012            pr ";\n";
8013            do_cleanups ();
8014            pr "      if (%s == NULL)\n" n;
8015            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8016            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8017            pr "      EXTEND (SP, n);\n";
8018            pr "      for (i = 0; i < n; ++i) {\n";
8019            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8020            pr "        free (%s[i]);\n" n;
8021            pr "      }\n";
8022            pr "      free (%s);\n" n;
8023        | RStruct (n, typ) ->
8024            let cols = cols_of_struct typ in
8025            generate_perl_struct_code typ cols name style n do_cleanups
8026        | RStructList (n, typ) ->
8027            let cols = cols_of_struct typ in
8028            generate_perl_struct_list_code typ cols name style n do_cleanups
8029        | RBufferOut n ->
8030            pr "PREINIT:\n";
8031            pr "      char *%s;\n" n;
8032            pr "      size_t size;\n";
8033            pr "   CODE:\n";
8034            pr "      %s = guestfs_%s " n name;
8035            generate_c_call_args ~handle:"g" style;
8036            pr ";\n";
8037            do_cleanups ();
8038            pr "      if (%s == NULL)\n" n;
8039            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8040            pr "      RETVAL = newSVpv (%s, size);\n" n;
8041            pr "      free (%s);\n" n;
8042            pr " OUTPUT:\n";
8043            pr "      RETVAL\n"
8044       );
8045
8046       pr "\n"
8047   ) all_functions
8048
8049 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8050   pr "PREINIT:\n";
8051   pr "      struct guestfs_%s_list *%s;\n" typ n;
8052   pr "      int i;\n";
8053   pr "      HV *hv;\n";
8054   pr " PPCODE:\n";
8055   pr "      %s = guestfs_%s " n name;
8056   generate_c_call_args ~handle:"g" style;
8057   pr ";\n";
8058   do_cleanups ();
8059   pr "      if (%s == NULL)\n" n;
8060   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8061   pr "      EXTEND (SP, %s->len);\n" n;
8062   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8063   pr "        hv = newHV ();\n";
8064   List.iter (
8065     function
8066     | name, FString ->
8067         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8068           name (String.length name) n name
8069     | name, FUUID ->
8070         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8071           name (String.length name) n name
8072     | name, FBuffer ->
8073         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8074           name (String.length name) n name n name
8075     | name, (FBytes|FUInt64) ->
8076         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8077           name (String.length name) n name
8078     | name, FInt64 ->
8079         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8080           name (String.length name) n name
8081     | name, (FInt32|FUInt32) ->
8082         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8083           name (String.length name) n name
8084     | name, FChar ->
8085         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8086           name (String.length name) n name
8087     | name, FOptPercent ->
8088         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8089           name (String.length name) n name
8090   ) cols;
8091   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8092   pr "      }\n";
8093   pr "      guestfs_free_%s_list (%s);\n" typ n
8094
8095 and generate_perl_struct_code typ cols name style n do_cleanups =
8096   pr "PREINIT:\n";
8097   pr "      struct guestfs_%s *%s;\n" typ n;
8098   pr " PPCODE:\n";
8099   pr "      %s = guestfs_%s " n name;
8100   generate_c_call_args ~handle:"g" style;
8101   pr ";\n";
8102   do_cleanups ();
8103   pr "      if (%s == NULL)\n" n;
8104   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8105   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8106   List.iter (
8107     fun ((name, _) as col) ->
8108       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8109
8110       match col with
8111       | name, FString ->
8112           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8113             n name
8114       | name, FBuffer ->
8115           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8116             n name n name
8117       | name, FUUID ->
8118           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8119             n name
8120       | name, (FBytes|FUInt64) ->
8121           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8122             n name
8123       | name, FInt64 ->
8124           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8125             n name
8126       | name, (FInt32|FUInt32) ->
8127           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8128             n name
8129       | name, FChar ->
8130           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8131             n name
8132       | name, FOptPercent ->
8133           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8134             n name
8135   ) cols;
8136   pr "      free (%s);\n" n
8137
8138 (* Generate Sys/Guestfs.pm. *)
8139 and generate_perl_pm () =
8140   generate_header HashStyle LGPLv2;
8141
8142   pr "\
8143 =pod
8144
8145 =head1 NAME
8146
8147 Sys::Guestfs - Perl bindings for libguestfs
8148
8149 =head1 SYNOPSIS
8150
8151  use Sys::Guestfs;
8152
8153  my $h = Sys::Guestfs->new ();
8154  $h->add_drive ('guest.img');
8155  $h->launch ();
8156  $h->mount ('/dev/sda1', '/');
8157  $h->touch ('/hello');
8158  $h->sync ();
8159
8160 =head1 DESCRIPTION
8161
8162 The C<Sys::Guestfs> module provides a Perl XS binding to the
8163 libguestfs API for examining and modifying virtual machine
8164 disk images.
8165
8166 Amongst the things this is good for: making batch configuration
8167 changes to guests, getting disk used/free statistics (see also:
8168 virt-df), migrating between virtualization systems (see also:
8169 virt-p2v), performing partial backups, performing partial guest
8170 clones, cloning guests and changing registry/UUID/hostname info, and
8171 much else besides.
8172
8173 Libguestfs uses Linux kernel and qemu code, and can access any type of
8174 guest filesystem that Linux and qemu can, including but not limited
8175 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8176 schemes, qcow, qcow2, vmdk.
8177
8178 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8179 LVs, what filesystem is in each LV, etc.).  It can also run commands
8180 in the context of the guest.  Also you can access filesystems over FTP.
8181
8182 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8183 functions for using libguestfs from Perl, including integration
8184 with libvirt.
8185
8186 =head1 ERRORS
8187
8188 All errors turn into calls to C<croak> (see L<Carp(3)>).
8189
8190 =head1 METHODS
8191
8192 =over 4
8193
8194 =cut
8195
8196 package Sys::Guestfs;
8197
8198 use strict;
8199 use warnings;
8200
8201 require XSLoader;
8202 XSLoader::load ('Sys::Guestfs');
8203
8204 =item $h = Sys::Guestfs->new ();
8205
8206 Create a new guestfs handle.
8207
8208 =cut
8209
8210 sub new {
8211   my $proto = shift;
8212   my $class = ref ($proto) || $proto;
8213
8214   my $self = Sys::Guestfs::_create ();
8215   bless $self, $class;
8216   return $self;
8217 }
8218
8219 ";
8220
8221   (* Actions.  We only need to print documentation for these as
8222    * they are pulled in from the XS code automatically.
8223    *)
8224   List.iter (
8225     fun (name, style, _, flags, _, _, longdesc) ->
8226       if not (List.mem NotInDocs flags) then (
8227         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8228         pr "=item ";
8229         generate_perl_prototype name style;
8230         pr "\n\n";
8231         pr "%s\n\n" longdesc;
8232         if List.mem ProtocolLimitWarning flags then
8233           pr "%s\n\n" protocol_limit_warning;
8234         if List.mem DangerWillRobinson flags then
8235           pr "%s\n\n" danger_will_robinson;
8236         match deprecation_notice flags with
8237         | None -> ()
8238         | Some txt -> pr "%s\n\n" txt
8239       )
8240   ) all_functions_sorted;
8241
8242   (* End of file. *)
8243   pr "\
8244 =cut
8245
8246 1;
8247
8248 =back
8249
8250 =head1 COPYRIGHT
8251
8252 Copyright (C) 2009 Red Hat Inc.
8253
8254 =head1 LICENSE
8255
8256 Please see the file COPYING.LIB for the full license.
8257
8258 =head1 SEE ALSO
8259
8260 L<guestfs(3)>,
8261 L<guestfish(1)>,
8262 L<http://libguestfs.org>,
8263 L<Sys::Guestfs::Lib(3)>.
8264
8265 =cut
8266 "
8267
8268 and generate_perl_prototype name style =
8269   (match fst style with
8270    | RErr -> ()
8271    | RBool n
8272    | RInt n
8273    | RInt64 n
8274    | RConstString n
8275    | RConstOptString n
8276    | RString n
8277    | RBufferOut n -> pr "$%s = " n
8278    | RStruct (n,_)
8279    | RHashtable n -> pr "%%%s = " n
8280    | RStringList n
8281    | RStructList (n,_) -> pr "@%s = " n
8282   );
8283   pr "$h->%s (" name;
8284   let comma = ref false in
8285   List.iter (
8286     fun arg ->
8287       if !comma then pr ", ";
8288       comma := true;
8289       match arg with
8290       | Pathname n | Device n | Dev_or_Path n | String n
8291       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8292           pr "$%s" n
8293       | StringList n | DeviceList n ->
8294           pr "\\@%s" n
8295   ) (snd style);
8296   pr ");"
8297
8298 (* Generate Python C module. *)
8299 and generate_python_c () =
8300   generate_header CStyle LGPLv2;
8301
8302   pr "\
8303 #include <Python.h>
8304
8305 #include <stdio.h>
8306 #include <stdlib.h>
8307 #include <assert.h>
8308
8309 #include \"guestfs.h\"
8310
8311 typedef struct {
8312   PyObject_HEAD
8313   guestfs_h *g;
8314 } Pyguestfs_Object;
8315
8316 static guestfs_h *
8317 get_handle (PyObject *obj)
8318 {
8319   assert (obj);
8320   assert (obj != Py_None);
8321   return ((Pyguestfs_Object *) obj)->g;
8322 }
8323
8324 static PyObject *
8325 put_handle (guestfs_h *g)
8326 {
8327   assert (g);
8328   return
8329     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8330 }
8331
8332 /* This list should be freed (but not the strings) after use. */
8333 static char **
8334 get_string_list (PyObject *obj)
8335 {
8336   int i, len;
8337   char **r;
8338
8339   assert (obj);
8340
8341   if (!PyList_Check (obj)) {
8342     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8343     return NULL;
8344   }
8345
8346   len = PyList_Size (obj);
8347   r = malloc (sizeof (char *) * (len+1));
8348   if (r == NULL) {
8349     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8350     return NULL;
8351   }
8352
8353   for (i = 0; i < len; ++i)
8354     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8355   r[len] = NULL;
8356
8357   return r;
8358 }
8359
8360 static PyObject *
8361 put_string_list (char * const * const argv)
8362 {
8363   PyObject *list;
8364   int argc, i;
8365
8366   for (argc = 0; argv[argc] != NULL; ++argc)
8367     ;
8368
8369   list = PyList_New (argc);
8370   for (i = 0; i < argc; ++i)
8371     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8372
8373   return list;
8374 }
8375
8376 static PyObject *
8377 put_table (char * const * const argv)
8378 {
8379   PyObject *list, *item;
8380   int argc, i;
8381
8382   for (argc = 0; argv[argc] != NULL; ++argc)
8383     ;
8384
8385   list = PyList_New (argc >> 1);
8386   for (i = 0; i < argc; i += 2) {
8387     item = PyTuple_New (2);
8388     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8389     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8390     PyList_SetItem (list, i >> 1, item);
8391   }
8392
8393   return list;
8394 }
8395
8396 static void
8397 free_strings (char **argv)
8398 {
8399   int argc;
8400
8401   for (argc = 0; argv[argc] != NULL; ++argc)
8402     free (argv[argc]);
8403   free (argv);
8404 }
8405
8406 static PyObject *
8407 py_guestfs_create (PyObject *self, PyObject *args)
8408 {
8409   guestfs_h *g;
8410
8411   g = guestfs_create ();
8412   if (g == NULL) {
8413     PyErr_SetString (PyExc_RuntimeError,
8414                      \"guestfs.create: failed to allocate handle\");
8415     return NULL;
8416   }
8417   guestfs_set_error_handler (g, NULL, NULL);
8418   return put_handle (g);
8419 }
8420
8421 static PyObject *
8422 py_guestfs_close (PyObject *self, PyObject *args)
8423 {
8424   PyObject *py_g;
8425   guestfs_h *g;
8426
8427   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8428     return NULL;
8429   g = get_handle (py_g);
8430
8431   guestfs_close (g);
8432
8433   Py_INCREF (Py_None);
8434   return Py_None;
8435 }
8436
8437 ";
8438
8439   let emit_put_list_function typ =
8440     pr "static PyObject *\n";
8441     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8442     pr "{\n";
8443     pr "  PyObject *list;\n";
8444     pr "  int i;\n";
8445     pr "\n";
8446     pr "  list = PyList_New (%ss->len);\n" typ;
8447     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8448     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8449     pr "  return list;\n";
8450     pr "};\n";
8451     pr "\n"
8452   in
8453
8454   (* Structures, turned into Python dictionaries. *)
8455   List.iter (
8456     fun (typ, cols) ->
8457       pr "static PyObject *\n";
8458       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8459       pr "{\n";
8460       pr "  PyObject *dict;\n";
8461       pr "\n";
8462       pr "  dict = PyDict_New ();\n";
8463       List.iter (
8464         function
8465         | name, FString ->
8466             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8467             pr "                        PyString_FromString (%s->%s));\n"
8468               typ name
8469         | name, FBuffer ->
8470             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8471             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8472               typ name typ name
8473         | name, FUUID ->
8474             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8475             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8476               typ name
8477         | name, (FBytes|FUInt64) ->
8478             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8479             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8480               typ name
8481         | name, FInt64 ->
8482             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8483             pr "                        PyLong_FromLongLong (%s->%s));\n"
8484               typ name
8485         | name, FUInt32 ->
8486             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8487             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8488               typ name
8489         | name, FInt32 ->
8490             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8491             pr "                        PyLong_FromLong (%s->%s));\n"
8492               typ name
8493         | name, FOptPercent ->
8494             pr "  if (%s->%s >= 0)\n" typ name;
8495             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8496             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8497               typ name;
8498             pr "  else {\n";
8499             pr "    Py_INCREF (Py_None);\n";
8500             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8501             pr "  }\n"
8502         | name, FChar ->
8503             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8504             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8505       ) cols;
8506       pr "  return dict;\n";
8507       pr "};\n";
8508       pr "\n";
8509
8510   ) structs;
8511
8512   (* Emit a put_TYPE_list function definition only if that function is used. *)
8513   List.iter (
8514     function
8515     | typ, (RStructListOnly | RStructAndList) ->
8516         (* generate the function for typ *)
8517         emit_put_list_function typ
8518     | typ, _ -> () (* empty *)
8519   ) (rstructs_used_by all_functions);
8520
8521   (* Python wrapper functions. *)
8522   List.iter (
8523     fun (name, style, _, _, _, _, _) ->
8524       pr "static PyObject *\n";
8525       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8526       pr "{\n";
8527
8528       pr "  PyObject *py_g;\n";
8529       pr "  guestfs_h *g;\n";
8530       pr "  PyObject *py_r;\n";
8531
8532       let error_code =
8533         match fst style with
8534         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8535         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8536         | RConstString _ | RConstOptString _ ->
8537             pr "  const char *r;\n"; "NULL"
8538         | RString _ -> pr "  char *r;\n"; "NULL"
8539         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8540         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8541         | RStructList (_, typ) ->
8542             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8543         | RBufferOut _ ->
8544             pr "  char *r;\n";
8545             pr "  size_t size;\n";
8546             "NULL" in
8547
8548       List.iter (
8549         function
8550         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8551             pr "  const char *%s;\n" n
8552         | OptString n -> pr "  const char *%s;\n" n
8553         | StringList n | DeviceList n ->
8554             pr "  PyObject *py_%s;\n" n;
8555             pr "  char **%s;\n" n
8556         | Bool n -> pr "  int %s;\n" n
8557         | Int n -> pr "  int %s;\n" n
8558         | Int64 n -> pr "  long long %s;\n" n
8559       ) (snd style);
8560
8561       pr "\n";
8562
8563       (* Convert the parameters. *)
8564       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8565       List.iter (
8566         function
8567         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8568         | OptString _ -> pr "z"
8569         | StringList _ | DeviceList _ -> pr "O"
8570         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8571         | Int _ -> pr "i"
8572         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8573                              * emulate C's int/long/long long in Python?
8574                              *)
8575       ) (snd style);
8576       pr ":guestfs_%s\",\n" name;
8577       pr "                         &py_g";
8578       List.iter (
8579         function
8580         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8581         | OptString n -> pr ", &%s" n
8582         | StringList n | DeviceList n -> pr ", &py_%s" n
8583         | Bool n -> pr ", &%s" n
8584         | Int n -> pr ", &%s" n
8585         | Int64 n -> pr ", &%s" n
8586       ) (snd style);
8587
8588       pr "))\n";
8589       pr "    return NULL;\n";
8590
8591       pr "  g = get_handle (py_g);\n";
8592       List.iter (
8593         function
8594         | Pathname _ | Device _ | Dev_or_Path _ | String _
8595         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8596         | StringList n | DeviceList n ->
8597             pr "  %s = get_string_list (py_%s);\n" n n;
8598             pr "  if (!%s) return NULL;\n" n
8599       ) (snd style);
8600
8601       pr "\n";
8602
8603       pr "  r = guestfs_%s " name;
8604       generate_c_call_args ~handle:"g" style;
8605       pr ";\n";
8606
8607       List.iter (
8608         function
8609         | Pathname _ | Device _ | Dev_or_Path _ | String _
8610         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8611         | StringList n | DeviceList n ->
8612             pr "  free (%s);\n" n
8613       ) (snd style);
8614
8615       pr "  if (r == %s) {\n" error_code;
8616       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8617       pr "    return NULL;\n";
8618       pr "  }\n";
8619       pr "\n";
8620
8621       (match fst style with
8622        | RErr ->
8623            pr "  Py_INCREF (Py_None);\n";
8624            pr "  py_r = Py_None;\n"
8625        | RInt _
8626        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8627        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8628        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8629        | RConstOptString _ ->
8630            pr "  if (r)\n";
8631            pr "    py_r = PyString_FromString (r);\n";
8632            pr "  else {\n";
8633            pr "    Py_INCREF (Py_None);\n";
8634            pr "    py_r = Py_None;\n";
8635            pr "  }\n"
8636        | RString _ ->
8637            pr "  py_r = PyString_FromString (r);\n";
8638            pr "  free (r);\n"
8639        | RStringList _ ->
8640            pr "  py_r = put_string_list (r);\n";
8641            pr "  free_strings (r);\n"
8642        | RStruct (_, typ) ->
8643            pr "  py_r = put_%s (r);\n" typ;
8644            pr "  guestfs_free_%s (r);\n" typ
8645        | RStructList (_, typ) ->
8646            pr "  py_r = put_%s_list (r);\n" typ;
8647            pr "  guestfs_free_%s_list (r);\n" typ
8648        | RHashtable n ->
8649            pr "  py_r = put_table (r);\n";
8650            pr "  free_strings (r);\n"
8651        | RBufferOut _ ->
8652            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8653            pr "  free (r);\n"
8654       );
8655
8656       pr "  return py_r;\n";
8657       pr "}\n";
8658       pr "\n"
8659   ) all_functions;
8660
8661   (* Table of functions. *)
8662   pr "static PyMethodDef methods[] = {\n";
8663   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8664   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8665   List.iter (
8666     fun (name, _, _, _, _, _, _) ->
8667       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8668         name name
8669   ) all_functions;
8670   pr "  { NULL, NULL, 0, NULL }\n";
8671   pr "};\n";
8672   pr "\n";
8673
8674   (* Init function. *)
8675   pr "\
8676 void
8677 initlibguestfsmod (void)
8678 {
8679   static int initialized = 0;
8680
8681   if (initialized) return;
8682   Py_InitModule ((char *) \"libguestfsmod\", methods);
8683   initialized = 1;
8684 }
8685 "
8686
8687 (* Generate Python module. *)
8688 and generate_python_py () =
8689   generate_header HashStyle LGPLv2;
8690
8691   pr "\
8692 u\"\"\"Python bindings for libguestfs
8693
8694 import guestfs
8695 g = guestfs.GuestFS ()
8696 g.add_drive (\"guest.img\")
8697 g.launch ()
8698 parts = g.list_partitions ()
8699
8700 The guestfs module provides a Python binding to the libguestfs API
8701 for examining and modifying virtual machine disk images.
8702
8703 Amongst the things this is good for: making batch configuration
8704 changes to guests, getting disk used/free statistics (see also:
8705 virt-df), migrating between virtualization systems (see also:
8706 virt-p2v), performing partial backups, performing partial guest
8707 clones, cloning guests and changing registry/UUID/hostname info, and
8708 much else besides.
8709
8710 Libguestfs uses Linux kernel and qemu code, and can access any type of
8711 guest filesystem that Linux and qemu can, including but not limited
8712 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8713 schemes, qcow, qcow2, vmdk.
8714
8715 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8716 LVs, what filesystem is in each LV, etc.).  It can also run commands
8717 in the context of the guest.  Also you can access filesystems over FTP.
8718
8719 Errors which happen while using the API are turned into Python
8720 RuntimeError exceptions.
8721
8722 To create a guestfs handle you usually have to perform the following
8723 sequence of calls:
8724
8725 # Create the handle, call add_drive at least once, and possibly
8726 # several times if the guest has multiple block devices:
8727 g = guestfs.GuestFS ()
8728 g.add_drive (\"guest.img\")
8729
8730 # Launch the qemu subprocess and wait for it to become ready:
8731 g.launch ()
8732
8733 # Now you can issue commands, for example:
8734 logvols = g.lvs ()
8735
8736 \"\"\"
8737
8738 import libguestfsmod
8739
8740 class GuestFS:
8741     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8742
8743     def __init__ (self):
8744         \"\"\"Create a new libguestfs handle.\"\"\"
8745         self._o = libguestfsmod.create ()
8746
8747     def __del__ (self):
8748         libguestfsmod.close (self._o)
8749
8750 ";
8751
8752   List.iter (
8753     fun (name, style, _, flags, _, _, longdesc) ->
8754       pr "    def %s " name;
8755       generate_py_call_args ~handle:"self" (snd style);
8756       pr ":\n";
8757
8758       if not (List.mem NotInDocs flags) then (
8759         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8760         let doc =
8761           match fst style with
8762           | RErr | RInt _ | RInt64 _ | RBool _
8763           | RConstOptString _ | RConstString _
8764           | RString _ | RBufferOut _ -> doc
8765           | RStringList _ ->
8766               doc ^ "\n\nThis function returns a list of strings."
8767           | RStruct (_, typ) ->
8768               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8769           | RStructList (_, typ) ->
8770               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8771           | RHashtable _ ->
8772               doc ^ "\n\nThis function returns a dictionary." in
8773         let doc =
8774           if List.mem ProtocolLimitWarning flags then
8775             doc ^ "\n\n" ^ protocol_limit_warning
8776           else doc in
8777         let doc =
8778           if List.mem DangerWillRobinson flags then
8779             doc ^ "\n\n" ^ danger_will_robinson
8780           else doc in
8781         let doc =
8782           match deprecation_notice flags with
8783           | None -> doc
8784           | Some txt -> doc ^ "\n\n" ^ txt in
8785         let doc = pod2text ~width:60 name doc in
8786         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8787         let doc = String.concat "\n        " doc in
8788         pr "        u\"\"\"%s\"\"\"\n" doc;
8789       );
8790       pr "        return libguestfsmod.%s " name;
8791       generate_py_call_args ~handle:"self._o" (snd style);
8792       pr "\n";
8793       pr "\n";
8794   ) all_functions
8795
8796 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8797 and generate_py_call_args ~handle args =
8798   pr "(%s" handle;
8799   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8800   pr ")"
8801
8802 (* Useful if you need the longdesc POD text as plain text.  Returns a
8803  * list of lines.
8804  *
8805  * Because this is very slow (the slowest part of autogeneration),
8806  * we memoize the results.
8807  *)
8808 and pod2text ~width name longdesc =
8809   let key = width, name, longdesc in
8810   try Hashtbl.find pod2text_memo key
8811   with Not_found ->
8812     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8813     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8814     close_out chan;
8815     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8816     let chan = open_process_in cmd in
8817     let lines = ref [] in
8818     let rec loop i =
8819       let line = input_line chan in
8820       if i = 1 then             (* discard the first line of output *)
8821         loop (i+1)
8822       else (
8823         let line = triml line in
8824         lines := line :: !lines;
8825         loop (i+1)
8826       ) in
8827     let lines = try loop 1 with End_of_file -> List.rev !lines in
8828     unlink filename;
8829     (match close_process_in chan with
8830      | WEXITED 0 -> ()
8831      | WEXITED i ->
8832          failwithf "pod2text: process exited with non-zero status (%d)" i
8833      | WSIGNALED i | WSTOPPED i ->
8834          failwithf "pod2text: process signalled or stopped by signal %d" i
8835     );
8836     Hashtbl.add pod2text_memo key lines;
8837     pod2text_memo_updated ();
8838     lines
8839
8840 (* Generate ruby bindings. *)
8841 and generate_ruby_c () =
8842   generate_header CStyle LGPLv2;
8843
8844   pr "\
8845 #include <stdio.h>
8846 #include <stdlib.h>
8847
8848 #include <ruby.h>
8849
8850 #include \"guestfs.h\"
8851
8852 #include \"extconf.h\"
8853
8854 /* For Ruby < 1.9 */
8855 #ifndef RARRAY_LEN
8856 #define RARRAY_LEN(r) (RARRAY((r))->len)
8857 #endif
8858
8859 static VALUE m_guestfs;                 /* guestfs module */
8860 static VALUE c_guestfs;                 /* guestfs_h handle */
8861 static VALUE e_Error;                   /* used for all errors */
8862
8863 static void ruby_guestfs_free (void *p)
8864 {
8865   if (!p) return;
8866   guestfs_close ((guestfs_h *) p);
8867 }
8868
8869 static VALUE ruby_guestfs_create (VALUE m)
8870 {
8871   guestfs_h *g;
8872
8873   g = guestfs_create ();
8874   if (!g)
8875     rb_raise (e_Error, \"failed to create guestfs handle\");
8876
8877   /* Don't print error messages to stderr by default. */
8878   guestfs_set_error_handler (g, NULL, NULL);
8879
8880   /* Wrap it, and make sure the close function is called when the
8881    * handle goes away.
8882    */
8883   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8884 }
8885
8886 static VALUE ruby_guestfs_close (VALUE gv)
8887 {
8888   guestfs_h *g;
8889   Data_Get_Struct (gv, guestfs_h, g);
8890
8891   ruby_guestfs_free (g);
8892   DATA_PTR (gv) = NULL;
8893
8894   return Qnil;
8895 }
8896
8897 ";
8898
8899   List.iter (
8900     fun (name, style, _, _, _, _, _) ->
8901       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8902       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8903       pr ")\n";
8904       pr "{\n";
8905       pr "  guestfs_h *g;\n";
8906       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8907       pr "  if (!g)\n";
8908       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8909         name;
8910       pr "\n";
8911
8912       List.iter (
8913         function
8914         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8915             pr "  Check_Type (%sv, T_STRING);\n" n;
8916             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8917             pr "  if (!%s)\n" n;
8918             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8919             pr "              \"%s\", \"%s\");\n" n name
8920         | OptString n ->
8921             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8922         | StringList n | DeviceList n ->
8923             pr "  char **%s;\n" n;
8924             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8925             pr "  {\n";
8926             pr "    int i, len;\n";
8927             pr "    len = RARRAY_LEN (%sv);\n" n;
8928             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8929               n;
8930             pr "    for (i = 0; i < len; ++i) {\n";
8931             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8932             pr "      %s[i] = StringValueCStr (v);\n" n;
8933             pr "    }\n";
8934             pr "    %s[len] = NULL;\n" n;
8935             pr "  }\n";
8936         | Bool n ->
8937             pr "  int %s = RTEST (%sv);\n" n n
8938         | Int n ->
8939             pr "  int %s = NUM2INT (%sv);\n" n n
8940         | Int64 n ->
8941             pr "  long long %s = NUM2LL (%sv);\n" n n
8942       ) (snd style);
8943       pr "\n";
8944
8945       let error_code =
8946         match fst style with
8947         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8948         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8949         | RConstString _ | RConstOptString _ ->
8950             pr "  const char *r;\n"; "NULL"
8951         | RString _ -> pr "  char *r;\n"; "NULL"
8952         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8953         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8954         | RStructList (_, typ) ->
8955             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8956         | RBufferOut _ ->
8957             pr "  char *r;\n";
8958             pr "  size_t size;\n";
8959             "NULL" in
8960       pr "\n";
8961
8962       pr "  r = guestfs_%s " name;
8963       generate_c_call_args ~handle:"g" style;
8964       pr ";\n";
8965
8966       List.iter (
8967         function
8968         | Pathname _ | Device _ | Dev_or_Path _ | String _
8969         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8970         | StringList n | DeviceList n ->
8971             pr "  free (%s);\n" n
8972       ) (snd style);
8973
8974       pr "  if (r == %s)\n" error_code;
8975       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8976       pr "\n";
8977
8978       (match fst style with
8979        | RErr ->
8980            pr "  return Qnil;\n"
8981        | RInt _ | RBool _ ->
8982            pr "  return INT2NUM (r);\n"
8983        | RInt64 _ ->
8984            pr "  return ULL2NUM (r);\n"
8985        | RConstString _ ->
8986            pr "  return rb_str_new2 (r);\n";
8987        | RConstOptString _ ->
8988            pr "  if (r)\n";
8989            pr "    return rb_str_new2 (r);\n";
8990            pr "  else\n";
8991            pr "    return Qnil;\n";
8992        | RString _ ->
8993            pr "  VALUE rv = rb_str_new2 (r);\n";
8994            pr "  free (r);\n";
8995            pr "  return rv;\n";
8996        | RStringList _ ->
8997            pr "  int i, len = 0;\n";
8998            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8999            pr "  VALUE rv = rb_ary_new2 (len);\n";
9000            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9001            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9002            pr "    free (r[i]);\n";
9003            pr "  }\n";
9004            pr "  free (r);\n";
9005            pr "  return rv;\n"
9006        | RStruct (_, typ) ->
9007            let cols = cols_of_struct typ in
9008            generate_ruby_struct_code typ cols
9009        | RStructList (_, typ) ->
9010            let cols = cols_of_struct typ in
9011            generate_ruby_struct_list_code typ cols
9012        | RHashtable _ ->
9013            pr "  VALUE rv = rb_hash_new ();\n";
9014            pr "  int i;\n";
9015            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9016            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9017            pr "    free (r[i]);\n";
9018            pr "    free (r[i+1]);\n";
9019            pr "  }\n";
9020            pr "  free (r);\n";
9021            pr "  return rv;\n"
9022        | RBufferOut _ ->
9023            pr "  VALUE rv = rb_str_new (r, size);\n";
9024            pr "  free (r);\n";
9025            pr "  return rv;\n";
9026       );
9027
9028       pr "}\n";
9029       pr "\n"
9030   ) all_functions;
9031
9032   pr "\
9033 /* Initialize the module. */
9034 void Init__guestfs ()
9035 {
9036   m_guestfs = rb_define_module (\"Guestfs\");
9037   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9038   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9039
9040   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9041   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9042
9043 ";
9044   (* Define the rest of the methods. *)
9045   List.iter (
9046     fun (name, style, _, _, _, _, _) ->
9047       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9048       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9049   ) all_functions;
9050
9051   pr "}\n"
9052
9053 (* Ruby code to return a struct. *)
9054 and generate_ruby_struct_code typ cols =
9055   pr "  VALUE rv = rb_hash_new ();\n";
9056   List.iter (
9057     function
9058     | name, FString ->
9059         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9060     | name, FBuffer ->
9061         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9062     | name, FUUID ->
9063         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9064     | name, (FBytes|FUInt64) ->
9065         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9066     | name, FInt64 ->
9067         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9068     | name, FUInt32 ->
9069         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9070     | name, FInt32 ->
9071         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9072     | name, FOptPercent ->
9073         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9074     | name, FChar -> (* XXX wrong? *)
9075         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9076   ) cols;
9077   pr "  guestfs_free_%s (r);\n" typ;
9078   pr "  return rv;\n"
9079
9080 (* Ruby code to return a struct list. *)
9081 and generate_ruby_struct_list_code typ cols =
9082   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9083   pr "  int i;\n";
9084   pr "  for (i = 0; i < r->len; ++i) {\n";
9085   pr "    VALUE hv = rb_hash_new ();\n";
9086   List.iter (
9087     function
9088     | name, FString ->
9089         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9090     | name, FBuffer ->
9091         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
9092     | name, FUUID ->
9093         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9094     | name, (FBytes|FUInt64) ->
9095         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9096     | name, FInt64 ->
9097         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9098     | name, FUInt32 ->
9099         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9100     | name, FInt32 ->
9101         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9102     | name, FOptPercent ->
9103         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9104     | name, FChar -> (* XXX wrong? *)
9105         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9106   ) cols;
9107   pr "    rb_ary_push (rv, hv);\n";
9108   pr "  }\n";
9109   pr "  guestfs_free_%s_list (r);\n" typ;
9110   pr "  return rv;\n"
9111
9112 (* Generate Java bindings GuestFS.java file. *)
9113 and generate_java_java () =
9114   generate_header CStyle LGPLv2;
9115
9116   pr "\
9117 package com.redhat.et.libguestfs;
9118
9119 import java.util.HashMap;
9120 import com.redhat.et.libguestfs.LibGuestFSException;
9121 import com.redhat.et.libguestfs.PV;
9122 import com.redhat.et.libguestfs.VG;
9123 import com.redhat.et.libguestfs.LV;
9124 import com.redhat.et.libguestfs.Stat;
9125 import com.redhat.et.libguestfs.StatVFS;
9126 import com.redhat.et.libguestfs.IntBool;
9127 import com.redhat.et.libguestfs.Dirent;
9128
9129 /**
9130  * The GuestFS object is a libguestfs handle.
9131  *
9132  * @author rjones
9133  */
9134 public class GuestFS {
9135   // Load the native code.
9136   static {
9137     System.loadLibrary (\"guestfs_jni\");
9138   }
9139
9140   /**
9141    * The native guestfs_h pointer.
9142    */
9143   long g;
9144
9145   /**
9146    * Create a libguestfs handle.
9147    *
9148    * @throws LibGuestFSException
9149    */
9150   public GuestFS () throws LibGuestFSException
9151   {
9152     g = _create ();
9153   }
9154   private native long _create () throws LibGuestFSException;
9155
9156   /**
9157    * Close a libguestfs handle.
9158    *
9159    * You can also leave handles to be collected by the garbage
9160    * collector, but this method ensures that the resources used
9161    * by the handle are freed up immediately.  If you call any
9162    * other methods after closing the handle, you will get an
9163    * exception.
9164    *
9165    * @throws LibGuestFSException
9166    */
9167   public void close () throws LibGuestFSException
9168   {
9169     if (g != 0)
9170       _close (g);
9171     g = 0;
9172   }
9173   private native void _close (long g) throws LibGuestFSException;
9174
9175   public void finalize () throws LibGuestFSException
9176   {
9177     close ();
9178   }
9179
9180 ";
9181
9182   List.iter (
9183     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9184       if not (List.mem NotInDocs flags); then (
9185         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9186         let doc =
9187           if List.mem ProtocolLimitWarning flags then
9188             doc ^ "\n\n" ^ protocol_limit_warning
9189           else doc in
9190         let doc =
9191           if List.mem DangerWillRobinson flags then
9192             doc ^ "\n\n" ^ danger_will_robinson
9193           else doc in
9194         let doc =
9195           match deprecation_notice flags with
9196           | None -> doc
9197           | Some txt -> doc ^ "\n\n" ^ txt in
9198         let doc = pod2text ~width:60 name doc in
9199         let doc = List.map (            (* RHBZ#501883 *)
9200           function
9201           | "" -> "<p>"
9202           | nonempty -> nonempty
9203         ) doc in
9204         let doc = String.concat "\n   * " doc in
9205
9206         pr "  /**\n";
9207         pr "   * %s\n" shortdesc;
9208         pr "   * <p>\n";
9209         pr "   * %s\n" doc;
9210         pr "   * @throws LibGuestFSException\n";
9211         pr "   */\n";
9212         pr "  ";
9213       );
9214       generate_java_prototype ~public:true ~semicolon:false name style;
9215       pr "\n";
9216       pr "  {\n";
9217       pr "    if (g == 0)\n";
9218       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9219         name;
9220       pr "    ";
9221       if fst style <> RErr then pr "return ";
9222       pr "_%s " name;
9223       generate_java_call_args ~handle:"g" (snd style);
9224       pr ";\n";
9225       pr "  }\n";
9226       pr "  ";
9227       generate_java_prototype ~privat:true ~native:true name style;
9228       pr "\n";
9229       pr "\n";
9230   ) all_functions;
9231
9232   pr "}\n"
9233
9234 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9235 and generate_java_call_args ~handle args =
9236   pr "(%s" handle;
9237   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9238   pr ")"
9239
9240 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9241     ?(semicolon=true) name style =
9242   if privat then pr "private ";
9243   if public then pr "public ";
9244   if native then pr "native ";
9245
9246   (* return type *)
9247   (match fst style with
9248    | RErr -> pr "void ";
9249    | RInt _ -> pr "int ";
9250    | RInt64 _ -> pr "long ";
9251    | RBool _ -> pr "boolean ";
9252    | RConstString _ | RConstOptString _ | RString _
9253    | RBufferOut _ -> pr "String ";
9254    | RStringList _ -> pr "String[] ";
9255    | RStruct (_, typ) ->
9256        let name = java_name_of_struct typ in
9257        pr "%s " name;
9258    | RStructList (_, typ) ->
9259        let name = java_name_of_struct typ in
9260        pr "%s[] " name;
9261    | RHashtable _ -> pr "HashMap<String,String> ";
9262   );
9263
9264   if native then pr "_%s " name else pr "%s " name;
9265   pr "(";
9266   let needs_comma = ref false in
9267   if native then (
9268     pr "long g";
9269     needs_comma := true
9270   );
9271
9272   (* args *)
9273   List.iter (
9274     fun arg ->
9275       if !needs_comma then pr ", ";
9276       needs_comma := true;
9277
9278       match arg with
9279       | Pathname n
9280       | Device n | Dev_or_Path n
9281       | String n
9282       | OptString n
9283       | FileIn n
9284       | FileOut n ->
9285           pr "String %s" n
9286       | StringList n | DeviceList n ->
9287           pr "String[] %s" n
9288       | Bool n ->
9289           pr "boolean %s" n
9290       | Int n ->
9291           pr "int %s" n
9292       | Int64 n ->
9293           pr "long %s" n
9294   ) (snd style);
9295
9296   pr ")\n";
9297   pr "    throws LibGuestFSException";
9298   if semicolon then pr ";"
9299
9300 and generate_java_struct jtyp cols =
9301   generate_header CStyle LGPLv2;
9302
9303   pr "\
9304 package com.redhat.et.libguestfs;
9305
9306 /**
9307  * Libguestfs %s structure.
9308  *
9309  * @author rjones
9310  * @see GuestFS
9311  */
9312 public class %s {
9313 " jtyp jtyp;
9314
9315   List.iter (
9316     function
9317     | name, FString
9318     | name, FUUID
9319     | name, FBuffer -> pr "  public String %s;\n" name
9320     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9321     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9322     | name, FChar -> pr "  public char %s;\n" name
9323     | name, FOptPercent ->
9324         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9325         pr "  public float %s;\n" name
9326   ) cols;
9327
9328   pr "}\n"
9329
9330 and generate_java_c () =
9331   generate_header CStyle LGPLv2;
9332
9333   pr "\
9334 #include <stdio.h>
9335 #include <stdlib.h>
9336 #include <string.h>
9337
9338 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9339 #include \"guestfs.h\"
9340
9341 /* Note that this function returns.  The exception is not thrown
9342  * until after the wrapper function returns.
9343  */
9344 static void
9345 throw_exception (JNIEnv *env, const char *msg)
9346 {
9347   jclass cl;
9348   cl = (*env)->FindClass (env,
9349                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9350   (*env)->ThrowNew (env, cl, msg);
9351 }
9352
9353 JNIEXPORT jlong JNICALL
9354 Java_com_redhat_et_libguestfs_GuestFS__1create
9355   (JNIEnv *env, jobject obj)
9356 {
9357   guestfs_h *g;
9358
9359   g = guestfs_create ();
9360   if (g == NULL) {
9361     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9362     return 0;
9363   }
9364   guestfs_set_error_handler (g, NULL, NULL);
9365   return (jlong) (long) g;
9366 }
9367
9368 JNIEXPORT void JNICALL
9369 Java_com_redhat_et_libguestfs_GuestFS__1close
9370   (JNIEnv *env, jobject obj, jlong jg)
9371 {
9372   guestfs_h *g = (guestfs_h *) (long) jg;
9373   guestfs_close (g);
9374 }
9375
9376 ";
9377
9378   List.iter (
9379     fun (name, style, _, _, _, _, _) ->
9380       pr "JNIEXPORT ";
9381       (match fst style with
9382        | RErr -> pr "void ";
9383        | RInt _ -> pr "jint ";
9384        | RInt64 _ -> pr "jlong ";
9385        | RBool _ -> pr "jboolean ";
9386        | RConstString _ | RConstOptString _ | RString _
9387        | RBufferOut _ -> pr "jstring ";
9388        | RStruct _ | RHashtable _ ->
9389            pr "jobject ";
9390        | RStringList _ | RStructList _ ->
9391            pr "jobjectArray ";
9392       );
9393       pr "JNICALL\n";
9394       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9395       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9396       pr "\n";
9397       pr "  (JNIEnv *env, jobject obj, jlong jg";
9398       List.iter (
9399         function
9400         | Pathname n
9401         | Device n | Dev_or_Path n
9402         | String n
9403         | OptString n
9404         | FileIn n
9405         | FileOut n ->
9406             pr ", jstring j%s" n
9407         | StringList n | DeviceList n ->
9408             pr ", jobjectArray j%s" n
9409         | Bool n ->
9410             pr ", jboolean j%s" n
9411         | Int n ->
9412             pr ", jint j%s" n
9413         | Int64 n ->
9414             pr ", jlong j%s" n
9415       ) (snd style);
9416       pr ")\n";
9417       pr "{\n";
9418       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9419       let error_code, no_ret =
9420         match fst style with
9421         | RErr -> pr "  int r;\n"; "-1", ""
9422         | RBool _
9423         | RInt _ -> pr "  int r;\n"; "-1", "0"
9424         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9425         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9426         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9427         | RString _ ->
9428             pr "  jstring jr;\n";
9429             pr "  char *r;\n"; "NULL", "NULL"
9430         | RStringList _ ->
9431             pr "  jobjectArray jr;\n";
9432             pr "  int r_len;\n";
9433             pr "  jclass cl;\n";
9434             pr "  jstring jstr;\n";
9435             pr "  char **r;\n"; "NULL", "NULL"
9436         | RStruct (_, typ) ->
9437             pr "  jobject jr;\n";
9438             pr "  jclass cl;\n";
9439             pr "  jfieldID fl;\n";
9440             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9441         | RStructList (_, typ) ->
9442             pr "  jobjectArray jr;\n";
9443             pr "  jclass cl;\n";
9444             pr "  jfieldID fl;\n";
9445             pr "  jobject jfl;\n";
9446             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9447         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9448         | RBufferOut _ ->
9449             pr "  jstring jr;\n";
9450             pr "  char *r;\n";
9451             pr "  size_t size;\n";
9452             "NULL", "NULL" in
9453       List.iter (
9454         function
9455         | Pathname n
9456         | Device n | Dev_or_Path n
9457         | String n
9458         | OptString n
9459         | FileIn n
9460         | FileOut n ->
9461             pr "  const char *%s;\n" n
9462         | StringList n | DeviceList n ->
9463             pr "  int %s_len;\n" n;
9464             pr "  const char **%s;\n" n
9465         | Bool n
9466         | Int n ->
9467             pr "  int %s;\n" n
9468         | Int64 n ->
9469             pr "  int64_t %s;\n" n
9470       ) (snd style);
9471
9472       let needs_i =
9473         (match fst style with
9474          | RStringList _ | RStructList _ -> true
9475          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9476          | RConstOptString _
9477          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9478           List.exists (function
9479                        | StringList _ -> true
9480                        | DeviceList _ -> true
9481                        | _ -> false) (snd style) in
9482       if needs_i then
9483         pr "  int i;\n";
9484
9485       pr "\n";
9486
9487       (* Get the parameters. *)
9488       List.iter (
9489         function
9490         | Pathname n
9491         | Device n | Dev_or_Path n
9492         | String n
9493         | FileIn n
9494         | FileOut n ->
9495             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9496         | OptString n ->
9497             (* This is completely undocumented, but Java null becomes
9498              * a NULL parameter.
9499              *)
9500             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9501         | StringList n | DeviceList n ->
9502             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9503             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9504             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9505             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9506               n;
9507             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9508             pr "  }\n";
9509             pr "  %s[%s_len] = NULL;\n" n n;
9510         | Bool n
9511         | Int n
9512         | Int64 n ->
9513             pr "  %s = j%s;\n" n n
9514       ) (snd style);
9515
9516       (* Make the call. *)
9517       pr "  r = guestfs_%s " name;
9518       generate_c_call_args ~handle:"g" style;
9519       pr ";\n";
9520
9521       (* Release the parameters. *)
9522       List.iter (
9523         function
9524         | Pathname n
9525         | Device n | Dev_or_Path n
9526         | String n
9527         | FileIn n
9528         | FileOut n ->
9529             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9530         | OptString n ->
9531             pr "  if (j%s)\n" n;
9532             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9533         | StringList n | DeviceList n ->
9534             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9535             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9536               n;
9537             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9538             pr "  }\n";
9539             pr "  free (%s);\n" n
9540         | Bool n
9541         | Int n
9542         | Int64 n -> ()
9543       ) (snd style);
9544
9545       (* Check for errors. *)
9546       pr "  if (r == %s) {\n" error_code;
9547       pr "    throw_exception (env, guestfs_last_error (g));\n";
9548       pr "    return %s;\n" no_ret;
9549       pr "  }\n";
9550
9551       (* Return value. *)
9552       (match fst style with
9553        | RErr -> ()
9554        | RInt _ -> pr "  return (jint) r;\n"
9555        | RBool _ -> pr "  return (jboolean) r;\n"
9556        | RInt64 _ -> pr "  return (jlong) r;\n"
9557        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9558        | RConstOptString _ ->
9559            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9560        | RString _ ->
9561            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9562            pr "  free (r);\n";
9563            pr "  return jr;\n"
9564        | RStringList _ ->
9565            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9566            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9567            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9568            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9569            pr "  for (i = 0; i < r_len; ++i) {\n";
9570            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9571            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9572            pr "    free (r[i]);\n";
9573            pr "  }\n";
9574            pr "  free (r);\n";
9575            pr "  return jr;\n"
9576        | RStruct (_, typ) ->
9577            let jtyp = java_name_of_struct typ in
9578            let cols = cols_of_struct typ in
9579            generate_java_struct_return typ jtyp cols
9580        | RStructList (_, typ) ->
9581            let jtyp = java_name_of_struct typ in
9582            let cols = cols_of_struct typ in
9583            generate_java_struct_list_return typ jtyp cols
9584        | RHashtable _ ->
9585            (* XXX *)
9586            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9587            pr "  return NULL;\n"
9588        | RBufferOut _ ->
9589            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9590            pr "  free (r);\n";
9591            pr "  return jr;\n"
9592       );
9593
9594       pr "}\n";
9595       pr "\n"
9596   ) all_functions
9597
9598 and generate_java_struct_return typ jtyp cols =
9599   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9600   pr "  jr = (*env)->AllocObject (env, cl);\n";
9601   List.iter (
9602     function
9603     | name, FString ->
9604         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9605         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9606     | name, FUUID ->
9607         pr "  {\n";
9608         pr "    char s[33];\n";
9609         pr "    memcpy (s, r->%s, 32);\n" name;
9610         pr "    s[32] = 0;\n";
9611         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9612         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9613         pr "  }\n";
9614     | name, FBuffer ->
9615         pr "  {\n";
9616         pr "    int len = r->%s_len;\n" name;
9617         pr "    char s[len+1];\n";
9618         pr "    memcpy (s, r->%s, len);\n" name;
9619         pr "    s[len] = 0;\n";
9620         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9621         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9622         pr "  }\n";
9623     | name, (FBytes|FUInt64|FInt64) ->
9624         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9625         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9626     | name, (FUInt32|FInt32) ->
9627         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9628         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9629     | name, FOptPercent ->
9630         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9631         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9632     | name, FChar ->
9633         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9634         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9635   ) cols;
9636   pr "  free (r);\n";
9637   pr "  return jr;\n"
9638
9639 and generate_java_struct_list_return typ jtyp cols =
9640   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9641   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9642   pr "  for (i = 0; i < r->len; ++i) {\n";
9643   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9644   List.iter (
9645     function
9646     | name, FString ->
9647         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9648         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9649     | name, FUUID ->
9650         pr "    {\n";
9651         pr "      char s[33];\n";
9652         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9653         pr "      s[32] = 0;\n";
9654         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9655         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9656         pr "    }\n";
9657     | name, FBuffer ->
9658         pr "    {\n";
9659         pr "      int len = r->val[i].%s_len;\n" name;
9660         pr "      char s[len+1];\n";
9661         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9662         pr "      s[len] = 0;\n";
9663         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9664         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9665         pr "    }\n";
9666     | name, (FBytes|FUInt64|FInt64) ->
9667         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9668         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9669     | name, (FUInt32|FInt32) ->
9670         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9671         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9672     | name, FOptPercent ->
9673         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9674         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9675     | name, FChar ->
9676         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9677         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9678   ) cols;
9679   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9680   pr "  }\n";
9681   pr "  guestfs_free_%s_list (r);\n" typ;
9682   pr "  return jr;\n"
9683
9684 and generate_java_makefile_inc () =
9685   generate_header HashStyle GPLv2;
9686
9687   pr "java_built_sources = \\\n";
9688   List.iter (
9689     fun (typ, jtyp) ->
9690         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9691   ) java_structs;
9692   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9693
9694 and generate_haskell_hs () =
9695   generate_header HaskellStyle LGPLv2;
9696
9697   (* XXX We only know how to generate partial FFI for Haskell
9698    * at the moment.  Please help out!
9699    *)
9700   let can_generate style =
9701     match style with
9702     | RErr, _
9703     | RInt _, _
9704     | RInt64 _, _ -> true
9705     | RBool _, _
9706     | RConstString _, _
9707     | RConstOptString _, _
9708     | RString _, _
9709     | RStringList _, _
9710     | RStruct _, _
9711     | RStructList _, _
9712     | RHashtable _, _
9713     | RBufferOut _, _ -> false in
9714
9715   pr "\
9716 {-# INCLUDE <guestfs.h> #-}
9717 {-# LANGUAGE ForeignFunctionInterface #-}
9718
9719 module Guestfs (
9720   create";
9721
9722   (* List out the names of the actions we want to export. *)
9723   List.iter (
9724     fun (name, style, _, _, _, _, _) ->
9725       if can_generate style then pr ",\n  %s" name
9726   ) all_functions;
9727
9728   pr "
9729   ) where
9730
9731 -- Unfortunately some symbols duplicate ones already present
9732 -- in Prelude.  We don't know which, so we hard-code a list
9733 -- here.
9734 import Prelude hiding (truncate)
9735
9736 import Foreign
9737 import Foreign.C
9738 import Foreign.C.Types
9739 import IO
9740 import Control.Exception
9741 import Data.Typeable
9742
9743 data GuestfsS = GuestfsS            -- represents the opaque C struct
9744 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9745 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9746
9747 -- XXX define properly later XXX
9748 data PV = PV
9749 data VG = VG
9750 data LV = LV
9751 data IntBool = IntBool
9752 data Stat = Stat
9753 data StatVFS = StatVFS
9754 data Hashtable = Hashtable
9755
9756 foreign import ccall unsafe \"guestfs_create\" c_create
9757   :: IO GuestfsP
9758 foreign import ccall unsafe \"&guestfs_close\" c_close
9759   :: FunPtr (GuestfsP -> IO ())
9760 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9761   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9762
9763 create :: IO GuestfsH
9764 create = do
9765   p <- c_create
9766   c_set_error_handler p nullPtr nullPtr
9767   h <- newForeignPtr c_close p
9768   return h
9769
9770 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9771   :: GuestfsP -> IO CString
9772
9773 -- last_error :: GuestfsH -> IO (Maybe String)
9774 -- last_error h = do
9775 --   str <- withForeignPtr h (\\p -> c_last_error p)
9776 --   maybePeek peekCString str
9777
9778 last_error :: GuestfsH -> IO (String)
9779 last_error h = do
9780   str <- withForeignPtr h (\\p -> c_last_error p)
9781   if (str == nullPtr)
9782     then return \"no error\"
9783     else peekCString str
9784
9785 ";
9786
9787   (* Generate wrappers for each foreign function. *)
9788   List.iter (
9789     fun (name, style, _, _, _, _, _) ->
9790       if can_generate style then (
9791         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9792         pr "  :: ";
9793         generate_haskell_prototype ~handle:"GuestfsP" style;
9794         pr "\n";
9795         pr "\n";
9796         pr "%s :: " name;
9797         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9798         pr "\n";
9799         pr "%s %s = do\n" name
9800           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9801         pr "  r <- ";
9802         (* Convert pointer arguments using with* functions. *)
9803         List.iter (
9804           function
9805           | FileIn n
9806           | FileOut n
9807           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9808           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9809           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9810           | Bool _ | Int _ | Int64 _ -> ()
9811         ) (snd style);
9812         (* Convert integer arguments. *)
9813         let args =
9814           List.map (
9815             function
9816             | Bool n -> sprintf "(fromBool %s)" n
9817             | Int n -> sprintf "(fromIntegral %s)" n
9818             | Int64 n -> sprintf "(fromIntegral %s)" n
9819             | FileIn n | FileOut n
9820             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9821           ) (snd style) in
9822         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9823           (String.concat " " ("p" :: args));
9824         (match fst style with
9825          | RErr | RInt _ | RInt64 _ | RBool _ ->
9826              pr "  if (r == -1)\n";
9827              pr "    then do\n";
9828              pr "      err <- last_error h\n";
9829              pr "      fail err\n";
9830          | RConstString _ | RConstOptString _ | RString _
9831          | RStringList _ | RStruct _
9832          | RStructList _ | RHashtable _ | RBufferOut _ ->
9833              pr "  if (r == nullPtr)\n";
9834              pr "    then do\n";
9835              pr "      err <- last_error h\n";
9836              pr "      fail err\n";
9837         );
9838         (match fst style with
9839          | RErr ->
9840              pr "    else return ()\n"
9841          | RInt _ ->
9842              pr "    else return (fromIntegral r)\n"
9843          | RInt64 _ ->
9844              pr "    else return (fromIntegral r)\n"
9845          | RBool _ ->
9846              pr "    else return (toBool r)\n"
9847          | RConstString _
9848          | RConstOptString _
9849          | RString _
9850          | RStringList _
9851          | RStruct _
9852          | RStructList _
9853          | RHashtable _
9854          | RBufferOut _ ->
9855              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9856         );
9857         pr "\n";
9858       )
9859   ) all_functions
9860
9861 and generate_haskell_prototype ~handle ?(hs = false) style =
9862   pr "%s -> " handle;
9863   let string = if hs then "String" else "CString" in
9864   let int = if hs then "Int" else "CInt" in
9865   let bool = if hs then "Bool" else "CInt" in
9866   let int64 = if hs then "Integer" else "Int64" in
9867   List.iter (
9868     fun arg ->
9869       (match arg with
9870        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9871        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9872        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9873        | Bool _ -> pr "%s" bool
9874        | Int _ -> pr "%s" int
9875        | Int64 _ -> pr "%s" int
9876        | FileIn _ -> pr "%s" string
9877        | FileOut _ -> pr "%s" string
9878       );
9879       pr " -> ";
9880   ) (snd style);
9881   pr "IO (";
9882   (match fst style with
9883    | RErr -> if not hs then pr "CInt"
9884    | RInt _ -> pr "%s" int
9885    | RInt64 _ -> pr "%s" int64
9886    | RBool _ -> pr "%s" bool
9887    | RConstString _ -> pr "%s" string
9888    | RConstOptString _ -> pr "Maybe %s" string
9889    | RString _ -> pr "%s" string
9890    | RStringList _ -> pr "[%s]" string
9891    | RStruct (_, typ) ->
9892        let name = java_name_of_struct typ in
9893        pr "%s" name
9894    | RStructList (_, typ) ->
9895        let name = java_name_of_struct typ in
9896        pr "[%s]" name
9897    | RHashtable _ -> pr "Hashtable"
9898    | RBufferOut _ -> pr "%s" string
9899   );
9900   pr ")"
9901
9902 and generate_bindtests () =
9903   generate_header CStyle LGPLv2;
9904
9905   pr "\
9906 #include <stdio.h>
9907 #include <stdlib.h>
9908 #include <inttypes.h>
9909 #include <string.h>
9910
9911 #include \"guestfs.h\"
9912 #include \"guestfs-internal.h\"
9913 #include \"guestfs-internal-actions.h\"
9914 #include \"guestfs_protocol.h\"
9915
9916 #define error guestfs_error
9917 #define safe_calloc guestfs_safe_calloc
9918 #define safe_malloc guestfs_safe_malloc
9919
9920 static void
9921 print_strings (char *const *argv)
9922 {
9923   int argc;
9924
9925   printf (\"[\");
9926   for (argc = 0; argv[argc] != NULL; ++argc) {
9927     if (argc > 0) printf (\", \");
9928     printf (\"\\\"%%s\\\"\", argv[argc]);
9929   }
9930   printf (\"]\\n\");
9931 }
9932
9933 /* The test0 function prints its parameters to stdout. */
9934 ";
9935
9936   let test0, tests =
9937     match test_functions with
9938     | [] -> assert false
9939     | test0 :: tests -> test0, tests in
9940
9941   let () =
9942     let (name, style, _, _, _, _, _) = test0 in
9943     generate_prototype ~extern:false ~semicolon:false ~newline:true
9944       ~handle:"g" ~prefix:"guestfs__" name style;
9945     pr "{\n";
9946     List.iter (
9947       function
9948       | Pathname n
9949       | Device n | Dev_or_Path n
9950       | String n
9951       | FileIn n
9952       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9953       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9954       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9955       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9956       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9957       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9958     ) (snd style);
9959     pr "  /* Java changes stdout line buffering so we need this: */\n";
9960     pr "  fflush (stdout);\n";
9961     pr "  return 0;\n";
9962     pr "}\n";
9963     pr "\n" in
9964
9965   List.iter (
9966     fun (name, style, _, _, _, _, _) ->
9967       if String.sub name (String.length name - 3) 3 <> "err" then (
9968         pr "/* Test normal return. */\n";
9969         generate_prototype ~extern:false ~semicolon:false ~newline:true
9970           ~handle:"g" ~prefix:"guestfs__" name style;
9971         pr "{\n";
9972         (match fst style with
9973          | RErr ->
9974              pr "  return 0;\n"
9975          | RInt _ ->
9976              pr "  int r;\n";
9977              pr "  sscanf (val, \"%%d\", &r);\n";
9978              pr "  return r;\n"
9979          | RInt64 _ ->
9980              pr "  int64_t r;\n";
9981              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9982              pr "  return r;\n"
9983          | RBool _ ->
9984              pr "  return STREQ (val, \"true\");\n"
9985          | RConstString _
9986          | RConstOptString _ ->
9987              (* Can't return the input string here.  Return a static
9988               * string so we ensure we get a segfault if the caller
9989               * tries to free it.
9990               *)
9991              pr "  return \"static string\";\n"
9992          | RString _ ->
9993              pr "  return strdup (val);\n"
9994          | RStringList _ ->
9995              pr "  char **strs;\n";
9996              pr "  int n, i;\n";
9997              pr "  sscanf (val, \"%%d\", &n);\n";
9998              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9999              pr "  for (i = 0; i < n; ++i) {\n";
10000              pr "    strs[i] = safe_malloc (g, 16);\n";
10001              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10002              pr "  }\n";
10003              pr "  strs[n] = NULL;\n";
10004              pr "  return strs;\n"
10005          | RStruct (_, typ) ->
10006              pr "  struct guestfs_%s *r;\n" typ;
10007              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10008              pr "  return r;\n"
10009          | RStructList (_, typ) ->
10010              pr "  struct guestfs_%s_list *r;\n" typ;
10011              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10012              pr "  sscanf (val, \"%%d\", &r->len);\n";
10013              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10014              pr "  return r;\n"
10015          | RHashtable _ ->
10016              pr "  char **strs;\n";
10017              pr "  int n, i;\n";
10018              pr "  sscanf (val, \"%%d\", &n);\n";
10019              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10020              pr "  for (i = 0; i < n; ++i) {\n";
10021              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10022              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10023              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10024              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10025              pr "  }\n";
10026              pr "  strs[n*2] = NULL;\n";
10027              pr "  return strs;\n"
10028          | RBufferOut _ ->
10029              pr "  return strdup (val);\n"
10030         );
10031         pr "}\n";
10032         pr "\n"
10033       ) else (
10034         pr "/* Test error return. */\n";
10035         generate_prototype ~extern:false ~semicolon:false ~newline:true
10036           ~handle:"g" ~prefix:"guestfs__" name style;
10037         pr "{\n";
10038         pr "  error (g, \"error\");\n";
10039         (match fst style with
10040          | RErr | RInt _ | RInt64 _ | RBool _ ->
10041              pr "  return -1;\n"
10042          | RConstString _ | RConstOptString _
10043          | RString _ | RStringList _ | RStruct _
10044          | RStructList _
10045          | RHashtable _
10046          | RBufferOut _ ->
10047              pr "  return NULL;\n"
10048         );
10049         pr "}\n";
10050         pr "\n"
10051       )
10052   ) tests
10053
10054 and generate_ocaml_bindtests () =
10055   generate_header OCamlStyle GPLv2;
10056
10057   pr "\
10058 let () =
10059   let g = Guestfs.create () in
10060 ";
10061
10062   let mkargs args =
10063     String.concat " " (
10064       List.map (
10065         function
10066         | CallString s -> "\"" ^ s ^ "\""
10067         | CallOptString None -> "None"
10068         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10069         | CallStringList xs ->
10070             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10071         | CallInt i when i >= 0 -> string_of_int i
10072         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10073         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10074         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10075         | CallBool b -> string_of_bool b
10076       ) args
10077     )
10078   in
10079
10080   generate_lang_bindtests (
10081     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10082   );
10083
10084   pr "print_endline \"EOF\"\n"
10085
10086 and generate_perl_bindtests () =
10087   pr "#!/usr/bin/perl -w\n";
10088   generate_header HashStyle GPLv2;
10089
10090   pr "\
10091 use strict;
10092
10093 use Sys::Guestfs;
10094
10095 my $g = Sys::Guestfs->new ();
10096 ";
10097
10098   let mkargs args =
10099     String.concat ", " (
10100       List.map (
10101         function
10102         | CallString s -> "\"" ^ s ^ "\""
10103         | CallOptString None -> "undef"
10104         | CallOptString (Some s) -> sprintf "\"%s\"" s
10105         | CallStringList xs ->
10106             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10107         | CallInt i -> string_of_int i
10108         | CallInt64 i -> Int64.to_string i
10109         | CallBool b -> if b then "1" else "0"
10110       ) args
10111     )
10112   in
10113
10114   generate_lang_bindtests (
10115     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10116   );
10117
10118   pr "print \"EOF\\n\"\n"
10119
10120 and generate_python_bindtests () =
10121   generate_header HashStyle GPLv2;
10122
10123   pr "\
10124 import guestfs
10125
10126 g = guestfs.GuestFS ()
10127 ";
10128
10129   let mkargs args =
10130     String.concat ", " (
10131       List.map (
10132         function
10133         | CallString s -> "\"" ^ s ^ "\""
10134         | CallOptString None -> "None"
10135         | CallOptString (Some s) -> sprintf "\"%s\"" s
10136         | CallStringList xs ->
10137             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10138         | CallInt i -> string_of_int i
10139         | CallInt64 i -> Int64.to_string i
10140         | CallBool b -> if b then "1" else "0"
10141       ) args
10142     )
10143   in
10144
10145   generate_lang_bindtests (
10146     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10147   );
10148
10149   pr "print \"EOF\"\n"
10150
10151 and generate_ruby_bindtests () =
10152   generate_header HashStyle GPLv2;
10153
10154   pr "\
10155 require 'guestfs'
10156
10157 g = Guestfs::create()
10158 ";
10159
10160   let mkargs args =
10161     String.concat ", " (
10162       List.map (
10163         function
10164         | CallString s -> "\"" ^ s ^ "\""
10165         | CallOptString None -> "nil"
10166         | CallOptString (Some s) -> sprintf "\"%s\"" s
10167         | CallStringList xs ->
10168             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10169         | CallInt i -> string_of_int i
10170         | CallInt64 i -> Int64.to_string i
10171         | CallBool b -> string_of_bool b
10172       ) args
10173     )
10174   in
10175
10176   generate_lang_bindtests (
10177     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10178   );
10179
10180   pr "print \"EOF\\n\"\n"
10181
10182 and generate_java_bindtests () =
10183   generate_header CStyle GPLv2;
10184
10185   pr "\
10186 import com.redhat.et.libguestfs.*;
10187
10188 public class Bindtests {
10189     public static void main (String[] argv)
10190     {
10191         try {
10192             GuestFS g = new GuestFS ();
10193 ";
10194
10195   let mkargs args =
10196     String.concat ", " (
10197       List.map (
10198         function
10199         | CallString s -> "\"" ^ s ^ "\""
10200         | CallOptString None -> "null"
10201         | CallOptString (Some s) -> sprintf "\"%s\"" s
10202         | CallStringList xs ->
10203             "new String[]{" ^
10204               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10205         | CallInt i -> string_of_int i
10206         | CallInt64 i -> Int64.to_string i
10207         | CallBool b -> string_of_bool b
10208       ) args
10209     )
10210   in
10211
10212   generate_lang_bindtests (
10213     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10214   );
10215
10216   pr "
10217             System.out.println (\"EOF\");
10218         }
10219         catch (Exception exn) {
10220             System.err.println (exn);
10221             System.exit (1);
10222         }
10223     }
10224 }
10225 "
10226
10227 and generate_haskell_bindtests () =
10228   generate_header HaskellStyle GPLv2;
10229
10230   pr "\
10231 module Bindtests where
10232 import qualified Guestfs
10233
10234 main = do
10235   g <- Guestfs.create
10236 ";
10237
10238   let mkargs args =
10239     String.concat " " (
10240       List.map (
10241         function
10242         | CallString s -> "\"" ^ s ^ "\""
10243         | CallOptString None -> "Nothing"
10244         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10245         | CallStringList xs ->
10246             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10247         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10248         | CallInt i -> string_of_int i
10249         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10250         | CallInt64 i -> Int64.to_string i
10251         | CallBool true -> "True"
10252         | CallBool false -> "False"
10253       ) args
10254     )
10255   in
10256
10257   generate_lang_bindtests (
10258     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10259   );
10260
10261   pr "  putStrLn \"EOF\"\n"
10262
10263 (* Language-independent bindings tests - we do it this way to
10264  * ensure there is parity in testing bindings across all languages.
10265  *)
10266 and generate_lang_bindtests call =
10267   call "test0" [CallString "abc"; CallOptString (Some "def");
10268                 CallStringList []; CallBool false;
10269                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10270   call "test0" [CallString "abc"; CallOptString None;
10271                 CallStringList []; CallBool false;
10272                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10273   call "test0" [CallString ""; CallOptString (Some "def");
10274                 CallStringList []; CallBool false;
10275                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10276   call "test0" [CallString ""; CallOptString (Some "");
10277                 CallStringList []; CallBool false;
10278                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10279   call "test0" [CallString "abc"; CallOptString (Some "def");
10280                 CallStringList ["1"]; CallBool false;
10281                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10282   call "test0" [CallString "abc"; CallOptString (Some "def");
10283                 CallStringList ["1"; "2"]; CallBool false;
10284                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10285   call "test0" [CallString "abc"; CallOptString (Some "def");
10286                 CallStringList ["1"]; CallBool true;
10287                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10288   call "test0" [CallString "abc"; CallOptString (Some "def");
10289                 CallStringList ["1"]; CallBool false;
10290                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10291   call "test0" [CallString "abc"; CallOptString (Some "def");
10292                 CallStringList ["1"]; CallBool false;
10293                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10294   call "test0" [CallString "abc"; CallOptString (Some "def");
10295                 CallStringList ["1"]; CallBool false;
10296                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10297   call "test0" [CallString "abc"; CallOptString (Some "def");
10298                 CallStringList ["1"]; CallBool false;
10299                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10300   call "test0" [CallString "abc"; CallOptString (Some "def");
10301                 CallStringList ["1"]; CallBool false;
10302                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10303   call "test0" [CallString "abc"; CallOptString (Some "def");
10304                 CallStringList ["1"]; CallBool false;
10305                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10306
10307 (* XXX Add here tests of the return and error functions. *)
10308
10309 (* This is used to generate the src/MAX_PROC_NR file which
10310  * contains the maximum procedure number, a surrogate for the
10311  * ABI version number.  See src/Makefile.am for the details.
10312  *)
10313 and generate_max_proc_nr () =
10314   let proc_nrs = List.map (
10315     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10316   ) daemon_functions in
10317
10318   let max_proc_nr = List.fold_left max 0 proc_nrs in
10319
10320   pr "%d\n" max_proc_nr
10321
10322 let output_to filename =
10323   let filename_new = filename ^ ".new" in
10324   chan := open_out filename_new;
10325   let close () =
10326     close_out !chan;
10327     chan := Pervasives.stdout;
10328
10329     (* Is the new file different from the current file? *)
10330     if Sys.file_exists filename && files_equal filename filename_new then
10331       unlink filename_new               (* same, so skip it *)
10332     else (
10333       (* different, overwrite old one *)
10334       (try chmod filename 0o644 with Unix_error _ -> ());
10335       rename filename_new filename;
10336       chmod filename 0o444;
10337       printf "written %s\n%!" filename;
10338     )
10339   in
10340   close
10341
10342 let perror msg = function
10343   | Unix_error (err, _, _) ->
10344       eprintf "%s: %s\n" msg (error_message err)
10345   | exn ->
10346       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10347
10348 (* Main program. *)
10349 let () =
10350   let lock_fd =
10351     try openfile "HACKING" [O_RDWR] 0
10352     with
10353     | Unix_error (ENOENT, _, _) ->
10354         eprintf "\
10355 You are probably running this from the wrong directory.
10356 Run it from the top source directory using the command
10357   src/generator.ml
10358 ";
10359         exit 1
10360     | exn ->
10361         perror "open: HACKING" exn;
10362         exit 1 in
10363
10364   (* Acquire a lock so parallel builds won't try to run the generator
10365    * twice at the same time.  Subsequent builds will wait for the first
10366    * one to finish.  Note the lock is released implicitly when the
10367    * program exits.
10368    *)
10369   (try lockf lock_fd F_LOCK 1
10370    with exn ->
10371      perror "lock: HACKING" exn;
10372      exit 1);
10373
10374   check_functions ();
10375
10376   let close = output_to "src/guestfs_protocol.x" in
10377   generate_xdr ();
10378   close ();
10379
10380   let close = output_to "src/guestfs-structs.h" in
10381   generate_structs_h ();
10382   close ();
10383
10384   let close = output_to "src/guestfs-actions.h" in
10385   generate_actions_h ();
10386   close ();
10387
10388   let close = output_to "src/guestfs-internal-actions.h" in
10389   generate_internal_actions_h ();
10390   close ();
10391
10392   let close = output_to "src/guestfs-actions.c" in
10393   generate_client_actions ();
10394   close ();
10395
10396   let close = output_to "daemon/actions.h" in
10397   generate_daemon_actions_h ();
10398   close ();
10399
10400   let close = output_to "daemon/stubs.c" in
10401   generate_daemon_actions ();
10402   close ();
10403
10404   let close = output_to "daemon/names.c" in
10405   generate_daemon_names ();
10406   close ();
10407
10408   let close = output_to "daemon/optgroups.c" in
10409   generate_daemon_optgroups_c ();
10410   close ();
10411
10412   let close = output_to "daemon/optgroups.h" in
10413   generate_daemon_optgroups_h ();
10414   close ();
10415
10416   let close = output_to "capitests/tests.c" in
10417   generate_tests ();
10418   close ();
10419
10420   let close = output_to "src/guestfs-bindtests.c" in
10421   generate_bindtests ();
10422   close ();
10423
10424   let close = output_to "fish/cmds.c" in
10425   generate_fish_cmds ();
10426   close ();
10427
10428   let close = output_to "fish/completion.c" in
10429   generate_fish_completion ();
10430   close ();
10431
10432   let close = output_to "guestfs-structs.pod" in
10433   generate_structs_pod ();
10434   close ();
10435
10436   let close = output_to "guestfs-actions.pod" in
10437   generate_actions_pod ();
10438   close ();
10439
10440   let close = output_to "guestfs-availability.pod" in
10441   generate_availability_pod ();
10442   close ();
10443
10444   let close = output_to "guestfish-actions.pod" in
10445   generate_fish_actions_pod ();
10446   close ();
10447
10448   let close = output_to "ocaml/guestfs.mli" in
10449   generate_ocaml_mli ();
10450   close ();
10451
10452   let close = output_to "ocaml/guestfs.ml" in
10453   generate_ocaml_ml ();
10454   close ();
10455
10456   let close = output_to "ocaml/guestfs_c_actions.c" in
10457   generate_ocaml_c ();
10458   close ();
10459
10460   let close = output_to "ocaml/bindtests.ml" in
10461   generate_ocaml_bindtests ();
10462   close ();
10463
10464   let close = output_to "perl/Guestfs.xs" in
10465   generate_perl_xs ();
10466   close ();
10467
10468   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10469   generate_perl_pm ();
10470   close ();
10471
10472   let close = output_to "perl/bindtests.pl" in
10473   generate_perl_bindtests ();
10474   close ();
10475
10476   let close = output_to "python/guestfs-py.c" in
10477   generate_python_c ();
10478   close ();
10479
10480   let close = output_to "python/guestfs.py" in
10481   generate_python_py ();
10482   close ();
10483
10484   let close = output_to "python/bindtests.py" in
10485   generate_python_bindtests ();
10486   close ();
10487
10488   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10489   generate_ruby_c ();
10490   close ();
10491
10492   let close = output_to "ruby/bindtests.rb" in
10493   generate_ruby_bindtests ();
10494   close ();
10495
10496   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10497   generate_java_java ();
10498   close ();
10499
10500   List.iter (
10501     fun (typ, jtyp) ->
10502       let cols = cols_of_struct typ in
10503       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10504       let close = output_to filename in
10505       generate_java_struct jtyp cols;
10506       close ();
10507   ) java_structs;
10508
10509   let close = output_to "java/Makefile.inc" in
10510   generate_java_makefile_inc ();
10511   close ();
10512
10513   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10514   generate_java_c ();
10515   close ();
10516
10517   let close = output_to "java/Bindtests.java" in
10518   generate_java_bindtests ();
10519   close ();
10520
10521   let close = output_to "haskell/Guestfs.hs" in
10522   generate_haskell_hs ();
10523   close ();
10524
10525   let close = output_to "haskell/Bindtests.hs" in
10526   generate_haskell_bindtests ();
10527   close ();
10528
10529   let close = output_to "src/MAX_PROC_NR" in
10530   generate_max_proc_nr ();
10531   close ();
10532
10533   (* Always generate this file last, and unconditionally.  It's used
10534    * by the Makefile to know when we must re-run the generator.
10535    *)
10536   let chan = open_out "src/stamp-generator" in
10537   fprintf chan "1\n";
10538   close_out chan