fish: Improve output of guestfish -h cmd
[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 Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145   | Int64 of string     (* any 64 bit int *)
146     (* These are treated as filenames (simple string parameters) in
147      * the C API and bindings.  But in the RPC protocol, we transfer
148      * the actual file content up to or down from the daemon.
149      * FileIn: local machine -> daemon (in request)
150      * FileOut: daemon -> local machine (in reply)
151      * In guestfish (only), the special name "-" means read from
152      * stdin or write to stdout.
153      *)
154   | FileIn of string
155   | FileOut of string
156 (* Not implemented:
157     (* Opaque buffer which can contain arbitrary 8 bit data.
158      * In the C API, this is expressed as <char *, int> pair.
159      * Most other languages have a string type which can contain
160      * ASCII NUL.  We use whatever type is appropriate for each
161      * language.
162      * Buffers are limited by the total message size.  To transfer
163      * large blocks of data, use FileIn/FileOut parameters instead.
164      * To return an arbitrary buffer, use RBufferOut.
165      *)
166   | BufferIn of string
167 *)
168
169 type flags =
170   | ProtocolLimitWarning  (* display warning about protocol size limits *)
171   | DangerWillRobinson    (* flags particularly dangerous commands *)
172   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
173   | FishAction of string  (* call this function in guestfish *)
174   | NotInFish             (* do not export via guestfish *)
175   | NotInDocs             (* do not add this function to documentation *)
176   | DeprecatedBy of string (* function is deprecated, use .. instead *)
177
178 (* You can supply zero or as many tests as you want per API call.
179  *
180  * Note that the test environment has 3 block devices, of size 500MB,
181  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
182  * a fourth ISO block device with some known files on it (/dev/sdd).
183  *
184  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
185  * Number of cylinders was 63 for IDE emulated disks with precisely
186  * the same size.  How exactly this is calculated is a mystery.
187  *
188  * The ISO block device (/dev/sdd) comes from images/test.iso.
189  *
190  * To be able to run the tests in a reasonable amount of time,
191  * the virtual machine and block devices are reused between tests.
192  * So don't try testing kill_subprocess :-x
193  *
194  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
195  *
196  * Don't assume anything about the previous contents of the block
197  * devices.  Use 'Init*' to create some initial scenarios.
198  *
199  * You can add a prerequisite clause to any individual test.  This
200  * is a run-time check, which, if it fails, causes the test to be
201  * skipped.  Useful if testing a command which might not work on
202  * all variations of libguestfs builds.  A test that has prerequisite
203  * of 'Always' is run unconditionally.
204  *
205  * In addition, packagers can skip individual tests by setting the
206  * environment variables:     eg:
207  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
208  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
209  *)
210 type tests = (test_init * test_prereq * test) list
211 and test =
212     (* Run the command sequence and just expect nothing to fail. *)
213   | TestRun of seq
214
215     (* Run the command sequence and expect the output of the final
216      * command to be the string.
217      *)
218   | TestOutput of seq * string
219
220     (* Run the command sequence and expect the output of the final
221      * command to be the list of strings.
222      *)
223   | TestOutputList of seq * string list
224
225     (* Run the command sequence and expect the output of the final
226      * command to be the list of block devices (could be either
227      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
228      * character of each string).
229      *)
230   | TestOutputListOfDevices of seq * string list
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the integer.
234      *)
235   | TestOutputInt of seq * int
236
237     (* Run the command sequence and expect the output of the final
238      * command to be <op> <int>, eg. ">=", "1".
239      *)
240   | TestOutputIntOp of seq * string * int
241
242     (* Run the command sequence and expect the output of the final
243      * command to be a true value (!= 0 or != NULL).
244      *)
245   | TestOutputTrue of seq
246
247     (* Run the command sequence and expect the output of the final
248      * command to be a false value (== 0 or == NULL, but not an error).
249      *)
250   | TestOutputFalse of seq
251
252     (* Run the command sequence and expect the output of the final
253      * command to be a list of the given length (but don't care about
254      * content).
255      *)
256   | TestOutputLength of seq * int
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a buffer (RBufferOut), ie. string + size.
260      *)
261   | TestOutputBuffer of seq * string
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a structure.
265      *)
266   | TestOutputStruct of seq * test_field_compare list
267
268     (* Run the command sequence and expect the final command (only)
269      * to fail.
270      *)
271   | TestLastFail of seq
272
273 and test_field_compare =
274   | CompareWithInt of string * int
275   | CompareWithIntOp of string * string * int
276   | CompareWithString of string * string
277   | CompareFieldsIntEq of string * string
278   | CompareFieldsStrEq of string * string
279
280 (* Test prerequisites. *)
281 and test_prereq =
282     (* Test always runs. *)
283   | Always
284
285     (* Test is currently disabled - eg. it fails, or it tests some
286      * unimplemented feature.
287      *)
288   | Disabled
289
290     (* 'string' is some C code (a function body) that should return
291      * true or false.  The test will run if the code returns true.
292      *)
293   | If of string
294
295     (* As for 'If' but the test runs _unless_ the code returns true. *)
296   | Unless of string
297
298 (* Some initial scenarios for testing. *)
299 and test_init =
300     (* Do nothing, block devices could contain random stuff including
301      * LVM PVs, and some filesystems might be mounted.  This is usually
302      * a bad idea.
303      *)
304   | InitNone
305
306     (* Block devices are empty and no filesystems are mounted. *)
307   | InitEmpty
308
309     (* /dev/sda contains a single partition /dev/sda1, with random
310      * content.  /dev/sdb and /dev/sdc may have random content.
311      * No LVM.
312      *)
313   | InitPartition
314
315     (* /dev/sda contains a single partition /dev/sda1, which is formatted
316      * as ext2, empty [except for lost+found] and mounted on /.
317      * /dev/sdb and /dev/sdc may have random content.
318      * No LVM.
319      *)
320   | InitBasicFS
321
322     (* /dev/sda:
323      *   /dev/sda1 (is a PV):
324      *     /dev/VG/LV (size 8MB):
325      *       formatted as ext2, empty [except for lost+found], mounted on /
326      * /dev/sdb and /dev/sdc may have random content.
327      *)
328   | InitBasicFSonLVM
329
330     (* /dev/sdd (the ISO, see images/ directory in source)
331      * is mounted on /
332      *)
333   | InitISOFS
334
335 (* Sequence of commands for testing. *)
336 and seq = cmd list
337 and cmd = string list
338
339 (* Note about long descriptions: When referring to another
340  * action, use the format C<guestfs_other> (ie. the full name of
341  * the C function).  This will be replaced as appropriate in other
342  * language bindings.
343  *
344  * Apart from that, long descriptions are just perldoc paragraphs.
345  *)
346
347 (* Generate a random UUID (used in tests). *)
348 let uuidgen () =
349   let chan = Unix.open_process_in "uuidgen" in
350   let uuid = input_line chan in
351   (match Unix.close_process_in chan with
352    | Unix.WEXITED 0 -> ()
353    | Unix.WEXITED _ ->
354        failwith "uuidgen: process exited with non-zero status"
355    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
356        failwith "uuidgen: process signalled or stopped by signal"
357   );
358   uuid
359
360 (* These test functions are used in the language binding tests. *)
361
362 let test_all_args = [
363   String "str";
364   OptString "optstr";
365   StringList "strlist";
366   Bool "b";
367   Int "integer";
368   Int64 "integer64";
369   FileIn "filein";
370   FileOut "fileout";
371 ]
372
373 let test_all_rets = [
374   (* except for RErr, which is tested thoroughly elsewhere *)
375   "test0rint",         RInt "valout";
376   "test0rint64",       RInt64 "valout";
377   "test0rbool",        RBool "valout";
378   "test0rconststring", RConstString "valout";
379   "test0rconstoptstring", RConstOptString "valout";
380   "test0rstring",      RString "valout";
381   "test0rstringlist",  RStringList "valout";
382   "test0rstruct",      RStruct ("valout", "lvm_pv");
383   "test0rstructlist",  RStructList ("valout", "lvm_pv");
384   "test0rhashtable",   RHashtable "valout";
385 ]
386
387 let test_functions = [
388   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
389    [],
390    "internal test function - do not use",
391    "\
392 This is an internal test function which is used to test whether
393 the automatically generated bindings can handle every possible
394 parameter type correctly.
395
396 It echos the contents of each parameter to stdout.
397
398 You probably don't want to call this function.");
399 ] @ List.flatten (
400   List.map (
401     fun (name, ret) ->
402       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
403         [],
404         "internal test function - do not use",
405         "\
406 This is an internal test function which is used to test whether
407 the automatically generated bindings can handle every possible
408 return type correctly.
409
410 It converts string C<val> to the return type.
411
412 You probably don't want to call this function.");
413        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
414         [],
415         "internal test function - do not use",
416         "\
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
420
421 This function always returns an error.
422
423 You probably don't want to call this function.")]
424   ) test_all_rets
425 )
426
427 (* non_daemon_functions are any functions which don't get processed
428  * in the daemon, eg. functions for setting and getting local
429  * configuration values.
430  *)
431
432 let non_daemon_functions = test_functions @ [
433   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
434    [],
435    "launch the qemu subprocess",
436    "\
437 Internally libguestfs is implemented by running a virtual machine
438 using L<qemu(1)>.
439
440 You should call this after configuring the handle
441 (eg. adding drives) but before performing any actions.");
442
443   ("wait_ready", (RErr, []), -1, [NotInFish],
444    [],
445    "wait until the qemu subprocess launches (no op)",
446    "\
447 This function is a no op.
448
449 In versions of the API E<lt> 1.0.71 you had to call this function
450 just after calling C<guestfs_launch> to wait for the launch
451 to complete.  However this is no longer necessary because
452 C<guestfs_launch> now does the waiting.
453
454 If you see any calls to this function in code then you can just
455 remove them, unless you want to retain compatibility with older
456 versions of the API.");
457
458   ("kill_subprocess", (RErr, []), -1, [],
459    [],
460    "kill the qemu subprocess",
461    "\
462 This kills the qemu subprocess.  You should never need to call this.");
463
464   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
465    [],
466    "add an image to examine or modify",
467    "\
468 This function adds a virtual machine disk image C<filename> to the
469 guest.  The first time you call this function, the disk appears as IDE
470 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
471 so on.
472
473 You don't necessarily need to be root when using libguestfs.  However
474 you obviously do need sufficient permissions to access the filename
475 for whatever operations you want to perform (ie. read access if you
476 just want to read the image or write access if you want to modify the
477 image).
478
479 This is equivalent to the qemu parameter
480 C<-drive file=filename,cache=off,if=...>.
481 C<cache=off> is omitted in cases where it is not supported by
482 the underlying filesystem.
483
484 Note that this call checks for the existence of C<filename>.  This
485 stops you from specifying other types of drive which are supported
486 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
487 the general C<guestfs_config> call instead.");
488
489   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
490    [],
491    "add a CD-ROM disk image to examine",
492    "\
493 This function adds a virtual CD-ROM disk image to the guest.
494
495 This is equivalent to the qemu parameter C<-cdrom filename>.
496
497 Note that this call checks for the existence of C<filename>.  This
498 stops you from specifying other types of drive which are supported
499 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
500 the general C<guestfs_config> call instead.");
501
502   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
503    [],
504    "add a drive in snapshot mode (read-only)",
505    "\
506 This adds a drive in snapshot mode, making it effectively
507 read-only.
508
509 Note that writes to the device are allowed, and will be seen for
510 the duration of the guestfs handle, but they are written
511 to a temporary file which is discarded as soon as the guestfs
512 handle is closed.  We don't currently have any method to enable
513 changes to be committed, although qemu can support this.
514
515 This is equivalent to the qemu parameter
516 C<-drive file=filename,snapshot=on,if=...>.
517
518 Note that this call checks for the existence of C<filename>.  This
519 stops you from specifying other types of drive which are supported
520 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
521 the general C<guestfs_config> call instead.");
522
523   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
524    [],
525    "add qemu parameters",
526    "\
527 This can be used to add arbitrary qemu command line parameters
528 of the form C<-param value>.  Actually it's not quite arbitrary - we
529 prevent you from setting some parameters which would interfere with
530 parameters that we use.
531
532 The first character of C<param> string must be a C<-> (dash).
533
534 C<value> can be NULL.");
535
536   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
537    [],
538    "set the qemu binary",
539    "\
540 Set the qemu binary that we will use.
541
542 The default is chosen when the library was compiled by the
543 configure script.
544
545 You can also override this by setting the C<LIBGUESTFS_QEMU>
546 environment variable.
547
548 Setting C<qemu> to C<NULL> restores the default qemu binary.");
549
550   ("get_qemu", (RConstString "qemu", []), -1, [],
551    [InitNone, Always, TestRun (
552       [["get_qemu"]])],
553    "get the qemu binary",
554    "\
555 Return the current qemu binary.
556
557 This is always non-NULL.  If it wasn't set already, then this will
558 return the default qemu binary name.");
559
560   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
561    [],
562    "set the search path",
563    "\
564 Set the path that libguestfs searches for kernel and initrd.img.
565
566 The default is C<$libdir/guestfs> unless overridden by setting
567 C<LIBGUESTFS_PATH> environment variable.
568
569 Setting C<path> to C<NULL> restores the default path.");
570
571   ("get_path", (RConstString "path", []), -1, [],
572    [InitNone, Always, TestRun (
573       [["get_path"]])],
574    "get the search path",
575    "\
576 Return the current search path.
577
578 This is always non-NULL.  If it wasn't set already, then this will
579 return the default path.");
580
581   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
582    [],
583    "add options to kernel command line",
584    "\
585 This function is used to add additional options to the
586 guest kernel command line.
587
588 The default is C<NULL> unless overridden by setting
589 C<LIBGUESTFS_APPEND> environment variable.
590
591 Setting C<append> to C<NULL> means I<no> additional options
592 are passed (libguestfs always adds a few of its own).");
593
594   ("get_append", (RConstOptString "append", []), -1, [],
595    (* This cannot be tested with the current framework.  The
596     * function can return NULL in normal operations, which the
597     * test framework interprets as an error.
598     *)
599    [],
600    "get the additional kernel options",
601    "\
602 Return the additional kernel options which are added to the
603 guest kernel command line.
604
605 If C<NULL> then no options are added.");
606
607   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
608    [],
609    "set autosync mode",
610    "\
611 If C<autosync> is true, this enables autosync.  Libguestfs will make a
612 best effort attempt to run C<guestfs_umount_all> followed by
613 C<guestfs_sync> when the handle is closed
614 (also if the program exits without closing handles).
615
616 This is disabled by default (except in guestfish where it is
617 enabled by default).");
618
619   ("get_autosync", (RBool "autosync", []), -1, [],
620    [InitNone, Always, TestRun (
621       [["get_autosync"]])],
622    "get autosync mode",
623    "\
624 Get the autosync flag.");
625
626   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
627    [],
628    "set verbose mode",
629    "\
630 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
631
632 Verbose messages are disabled unless the environment variable
633 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
634
635   ("get_verbose", (RBool "verbose", []), -1, [],
636    [],
637    "get verbose mode",
638    "\
639 This returns the verbose messages flag.");
640
641   ("is_ready", (RBool "ready", []), -1, [],
642    [InitNone, Always, TestOutputTrue (
643       [["is_ready"]])],
644    "is ready to accept commands",
645    "\
646 This returns true iff this handle is ready to accept commands
647 (in the C<READY> state).
648
649 For more information on states, see L<guestfs(3)>.");
650
651   ("is_config", (RBool "config", []), -1, [],
652    [InitNone, Always, TestOutputFalse (
653       [["is_config"]])],
654    "is in configuration state",
655    "\
656 This returns true iff this handle is being configured
657 (in the C<CONFIG> state).
658
659 For more information on states, see L<guestfs(3)>.");
660
661   ("is_launching", (RBool "launching", []), -1, [],
662    [InitNone, Always, TestOutputFalse (
663       [["is_launching"]])],
664    "is launching subprocess",
665    "\
666 This returns true iff this handle is launching the subprocess
667 (in the C<LAUNCHING> state).
668
669 For more information on states, see L<guestfs(3)>.");
670
671   ("is_busy", (RBool "busy", []), -1, [],
672    [InitNone, Always, TestOutputFalse (
673       [["is_busy"]])],
674    "is busy processing a command",
675    "\
676 This returns true iff this handle is busy processing a command
677 (in the C<BUSY> state).
678
679 For more information on states, see L<guestfs(3)>.");
680
681   ("get_state", (RInt "state", []), -1, [],
682    [],
683    "get the current state",
684    "\
685 This returns the current state as an opaque integer.  This is
686 only useful for printing debug and internal error messages.
687
688 For more information on states, see L<guestfs(3)>.");
689
690   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
691    [InitNone, Always, TestOutputInt (
692       [["set_memsize"; "500"];
693        ["get_memsize"]], 500)],
694    "set memory allocated to the qemu subprocess",
695    "\
696 This sets the memory size in megabytes allocated to the
697 qemu subprocess.  This only has any effect if called before
698 C<guestfs_launch>.
699
700 You can also change this by setting the environment
701 variable C<LIBGUESTFS_MEMSIZE> before the handle is
702 created.
703
704 For more information on the architecture of libguestfs,
705 see L<guestfs(3)>.");
706
707   ("get_memsize", (RInt "memsize", []), -1, [],
708    [InitNone, Always, TestOutputIntOp (
709       [["get_memsize"]], ">=", 256)],
710    "get memory allocated to the qemu subprocess",
711    "\
712 This gets the memory size in megabytes allocated to the
713 qemu subprocess.
714
715 If C<guestfs_set_memsize> was not called
716 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
717 then this returns the compiled-in default value for memsize.
718
719 For more information on the architecture of libguestfs,
720 see L<guestfs(3)>.");
721
722   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
723    [InitNone, Always, TestOutputIntOp (
724       [["get_pid"]], ">=", 1)],
725    "get PID of qemu subprocess",
726    "\
727 Return the process ID of the qemu subprocess.  If there is no
728 qemu subprocess, then this will return an error.
729
730 This is an internal call used for debugging and testing.");
731
732   ("version", (RStruct ("version", "version"), []), -1, [],
733    [InitNone, Always, TestOutputStruct (
734       [["version"]], [CompareWithInt ("major", 1)])],
735    "get the library version number",
736    "\
737 Return the libguestfs version number that the program is linked
738 against.
739
740 Note that because of dynamic linking this is not necessarily
741 the version of libguestfs that you compiled against.  You can
742 compile the program, and then at runtime dynamically link
743 against a completely different C<libguestfs.so> library.
744
745 This call was added in version C<1.0.58>.  In previous
746 versions of libguestfs there was no way to get the version
747 number.  From C code you can use ELF weak linking tricks to find out if
748 this symbol exists (if it doesn't, then it's an earlier version).
749
750 The call returns a structure with four elements.  The first
751 three (C<major>, C<minor> and C<release>) are numbers and
752 correspond to the usual version triplet.  The fourth element
753 (C<extra>) is a string and is normally empty, but may be
754 used for distro-specific information.
755
756 To construct the original version string:
757 C<$major.$minor.$release$extra>
758
759 I<Note:> Don't use this call to test for availability
760 of features.  Distro backports makes this unreliable.");
761
762   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
763    [InitNone, Always, TestOutputTrue (
764       [["set_selinux"; "true"];
765        ["get_selinux"]])],
766    "set SELinux enabled or disabled at appliance boot",
767    "\
768 This sets the selinux flag that is passed to the appliance
769 at boot time.  The default is C<selinux=0> (disabled).
770
771 Note that if SELinux is enabled, it is always in
772 Permissive mode (C<enforcing=0>).
773
774 For more information on the architecture of libguestfs,
775 see L<guestfs(3)>.");
776
777   ("get_selinux", (RBool "selinux", []), -1, [],
778    [],
779    "get SELinux enabled flag",
780    "\
781 This returns the current setting of the selinux flag which
782 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
783
784 For more information on the architecture of libguestfs,
785 see L<guestfs(3)>.");
786
787   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
788    [InitNone, Always, TestOutputFalse (
789       [["set_trace"; "false"];
790        ["get_trace"]])],
791    "enable or disable command traces",
792    "\
793 If the command trace flag is set to 1, then commands are
794 printed on stdout before they are executed in a format
795 which is very similar to the one used by guestfish.  In
796 other words, you can run a program with this enabled, and
797 you will get out a script which you can feed to guestfish
798 to perform the same set of actions.
799
800 If you want to trace C API calls into libguestfs (and
801 other libraries) then possibly a better way is to use
802 the external ltrace(1) command.
803
804 Command traces are disabled unless the environment variable
805 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
806
807   ("get_trace", (RBool "trace", []), -1, [],
808    [],
809    "get command trace enabled flag",
810    "\
811 Return the command trace flag.");
812
813   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
814    [InitNone, Always, TestOutputFalse (
815       [["set_direct"; "false"];
816        ["get_direct"]])],
817    "enable or disable direct appliance mode",
818    "\
819 If the direct appliance mode flag is enabled, then stdin and
820 stdout are passed directly through to the appliance once it
821 is launched.
822
823 One consequence of this is that log messages aren't caught
824 by the library and handled by C<guestfs_set_log_message_callback>,
825 but go straight to stdout.
826
827 You probably don't want to use this unless you know what you
828 are doing.
829
830 The default is disabled.");
831
832   ("get_direct", (RBool "direct", []), -1, [],
833    [],
834    "get direct appliance mode flag",
835    "\
836 Return the direct appliance mode flag.");
837
838   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
839    [InitNone, Always, TestOutputTrue (
840       [["set_recovery_proc"; "true"];
841        ["get_recovery_proc"]])],
842    "enable or disable the recovery process",
843    "\
844 If this is called with the parameter C<false> then
845 C<guestfs_launch> does not create a recovery process.  The
846 purpose of the recovery process is to stop runaway qemu
847 processes in the case where the main program aborts abruptly.
848
849 This only has any effect if called before C<guestfs_launch>,
850 and the default is true.
851
852 About the only time when you would want to disable this is
853 if the main process will fork itself into the background
854 (\"daemonize\" itself).  In this case the recovery process
855 thinks that the main program has disappeared and so kills
856 qemu, which is not very helpful.");
857
858   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
859    [],
860    "get recovery process enabled flag",
861    "\
862 Return the recovery process enabled flag.");
863
864 ]
865
866 (* daemon_functions are any functions which cause some action
867  * to take place in the daemon.
868  *)
869
870 let daemon_functions = [
871   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
872    [InitEmpty, Always, TestOutput (
873       [["part_disk"; "/dev/sda"; "mbr"];
874        ["mkfs"; "ext2"; "/dev/sda1"];
875        ["mount"; "/dev/sda1"; "/"];
876        ["write_file"; "/new"; "new file contents"; "0"];
877        ["cat"; "/new"]], "new file contents")],
878    "mount a guest disk at a position in the filesystem",
879    "\
880 Mount a guest disk at a position in the filesystem.  Block devices
881 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
882 the guest.  If those block devices contain partitions, they will have
883 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
884 names can be used.
885
886 The rules are the same as for L<mount(2)>:  A filesystem must
887 first be mounted on C</> before others can be mounted.  Other
888 filesystems can only be mounted on directories which already
889 exist.
890
891 The mounted filesystem is writable, if we have sufficient permissions
892 on the underlying device.
893
894 The filesystem options C<sync> and C<noatime> are set with this
895 call, in order to improve reliability.");
896
897   ("sync", (RErr, []), 2, [],
898    [ InitEmpty, Always, TestRun [["sync"]]],
899    "sync disks, writes are flushed through to the disk image",
900    "\
901 This syncs the disk, so that any writes are flushed through to the
902 underlying disk image.
903
904 You should always call this if you have modified a disk image, before
905 closing the handle.");
906
907   ("touch", (RErr, [Pathname "path"]), 3, [],
908    [InitBasicFS, Always, TestOutputTrue (
909       [["touch"; "/new"];
910        ["exists"; "/new"]])],
911    "update file timestamps or create a new file",
912    "\
913 Touch acts like the L<touch(1)> command.  It can be used to
914 update the timestamps on a file, or, if the file does not exist,
915 to create a new zero-length file.");
916
917   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
918    [InitISOFS, Always, TestOutput (
919       [["cat"; "/known-2"]], "abcdef\n")],
920    "list the contents of a file",
921    "\
922 Return the contents of the file named C<path>.
923
924 Note that this function cannot correctly handle binary files
925 (specifically, files containing C<\\0> character which is treated
926 as end of string).  For those you need to use the C<guestfs_read_file>
927 or C<guestfs_download> functions which have a more complex interface.");
928
929   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
930    [], (* XXX Tricky to test because it depends on the exact format
931         * of the 'ls -l' command, which changes between F10 and F11.
932         *)
933    "list the files in a directory (long format)",
934    "\
935 List the files in C<directory> (relative to the root directory,
936 there is no cwd) in the format of 'ls -la'.
937
938 This command is mostly useful for interactive sessions.  It
939 is I<not> intended that you try to parse the output string.");
940
941   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
942    [InitBasicFS, Always, TestOutputList (
943       [["touch"; "/new"];
944        ["touch"; "/newer"];
945        ["touch"; "/newest"];
946        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
947    "list the files in a directory",
948    "\
949 List the files in C<directory> (relative to the root directory,
950 there is no cwd).  The '.' and '..' entries are not returned, but
951 hidden files are shown.
952
953 This command is mostly useful for interactive sessions.  Programs
954 should probably use C<guestfs_readdir> instead.");
955
956   ("list_devices", (RStringList "devices", []), 7, [],
957    [InitEmpty, Always, TestOutputListOfDevices (
958       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
959    "list the block devices",
960    "\
961 List all the block devices.
962
963 The full block device names are returned, eg. C</dev/sda>");
964
965   ("list_partitions", (RStringList "partitions", []), 8, [],
966    [InitBasicFS, Always, TestOutputListOfDevices (
967       [["list_partitions"]], ["/dev/sda1"]);
968     InitEmpty, Always, TestOutputListOfDevices (
969       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
970        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
971    "list the partitions",
972    "\
973 List all the partitions detected on all block devices.
974
975 The full partition device names are returned, eg. C</dev/sda1>
976
977 This does not return logical volumes.  For that you will need to
978 call C<guestfs_lvs>.");
979
980   ("pvs", (RStringList "physvols", []), 9, [],
981    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
982       [["pvs"]], ["/dev/sda1"]);
983     InitEmpty, Always, TestOutputListOfDevices (
984       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
985        ["pvcreate"; "/dev/sda1"];
986        ["pvcreate"; "/dev/sda2"];
987        ["pvcreate"; "/dev/sda3"];
988        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
989    "list the LVM physical volumes (PVs)",
990    "\
991 List all the physical volumes detected.  This is the equivalent
992 of the L<pvs(8)> command.
993
994 This returns a list of just the device names that contain
995 PVs (eg. C</dev/sda2>).
996
997 See also C<guestfs_pvs_full>.");
998
999   ("vgs", (RStringList "volgroups", []), 10, [],
1000    [InitBasicFSonLVM, Always, TestOutputList (
1001       [["vgs"]], ["VG"]);
1002     InitEmpty, Always, TestOutputList (
1003       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1004        ["pvcreate"; "/dev/sda1"];
1005        ["pvcreate"; "/dev/sda2"];
1006        ["pvcreate"; "/dev/sda3"];
1007        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1008        ["vgcreate"; "VG2"; "/dev/sda3"];
1009        ["vgs"]], ["VG1"; "VG2"])],
1010    "list the LVM volume groups (VGs)",
1011    "\
1012 List all the volumes groups detected.  This is the equivalent
1013 of the L<vgs(8)> command.
1014
1015 This returns a list of just the volume group names that were
1016 detected (eg. C<VolGroup00>).
1017
1018 See also C<guestfs_vgs_full>.");
1019
1020   ("lvs", (RStringList "logvols", []), 11, [],
1021    [InitBasicFSonLVM, Always, TestOutputList (
1022       [["lvs"]], ["/dev/VG/LV"]);
1023     InitEmpty, Always, TestOutputList (
1024       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1025        ["pvcreate"; "/dev/sda1"];
1026        ["pvcreate"; "/dev/sda2"];
1027        ["pvcreate"; "/dev/sda3"];
1028        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1029        ["vgcreate"; "VG2"; "/dev/sda3"];
1030        ["lvcreate"; "LV1"; "VG1"; "50"];
1031        ["lvcreate"; "LV2"; "VG1"; "50"];
1032        ["lvcreate"; "LV3"; "VG2"; "50"];
1033        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1034    "list the LVM logical volumes (LVs)",
1035    "\
1036 List all the logical volumes detected.  This is the equivalent
1037 of the L<lvs(8)> command.
1038
1039 This returns a list of the logical volume device names
1040 (eg. C</dev/VolGroup00/LogVol00>).
1041
1042 See also C<guestfs_lvs_full>.");
1043
1044   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1045    [], (* XXX how to test? *)
1046    "list the LVM physical volumes (PVs)",
1047    "\
1048 List all the physical volumes detected.  This is the equivalent
1049 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1050
1051   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1052    [], (* XXX how to test? *)
1053    "list the LVM volume groups (VGs)",
1054    "\
1055 List all the volumes groups detected.  This is the equivalent
1056 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1057
1058   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1059    [], (* XXX how to test? *)
1060    "list the LVM logical volumes (LVs)",
1061    "\
1062 List all the logical volumes detected.  This is the equivalent
1063 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1064
1065   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1066    [InitISOFS, Always, TestOutputList (
1067       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1068     InitISOFS, Always, TestOutputList (
1069       [["read_lines"; "/empty"]], [])],
1070    "read file as lines",
1071    "\
1072 Return the contents of the file named C<path>.
1073
1074 The file contents are returned as a list of lines.  Trailing
1075 C<LF> and C<CRLF> character sequences are I<not> returned.
1076
1077 Note that this function cannot correctly handle binary files
1078 (specifically, files containing C<\\0> character which is treated
1079 as end of line).  For those you need to use the C<guestfs_read_file>
1080 function which has a more complex interface.");
1081
1082   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1083    [], (* XXX Augeas code needs tests. *)
1084    "create a new Augeas handle",
1085    "\
1086 Create a new Augeas handle for editing configuration files.
1087 If there was any previous Augeas handle associated with this
1088 guestfs session, then it is closed.
1089
1090 You must call this before using any other C<guestfs_aug_*>
1091 commands.
1092
1093 C<root> is the filesystem root.  C<root> must not be NULL,
1094 use C</> instead.
1095
1096 The flags are the same as the flags defined in
1097 E<lt>augeas.hE<gt>, the logical I<or> of the following
1098 integers:
1099
1100 =over 4
1101
1102 =item C<AUG_SAVE_BACKUP> = 1
1103
1104 Keep the original file with a C<.augsave> extension.
1105
1106 =item C<AUG_SAVE_NEWFILE> = 2
1107
1108 Save changes into a file with extension C<.augnew>, and
1109 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1110
1111 =item C<AUG_TYPE_CHECK> = 4
1112
1113 Typecheck lenses (can be expensive).
1114
1115 =item C<AUG_NO_STDINC> = 8
1116
1117 Do not use standard load path for modules.
1118
1119 =item C<AUG_SAVE_NOOP> = 16
1120
1121 Make save a no-op, just record what would have been changed.
1122
1123 =item C<AUG_NO_LOAD> = 32
1124
1125 Do not load the tree in C<guestfs_aug_init>.
1126
1127 =back
1128
1129 To close the handle, you can call C<guestfs_aug_close>.
1130
1131 To find out more about Augeas, see L<http://augeas.net/>.");
1132
1133   ("aug_close", (RErr, []), 26, [],
1134    [], (* XXX Augeas code needs tests. *)
1135    "close the current Augeas handle",
1136    "\
1137 Close the current Augeas handle and free up any resources
1138 used by it.  After calling this, you have to call
1139 C<guestfs_aug_init> again before you can use any other
1140 Augeas functions.");
1141
1142   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1143    [], (* XXX Augeas code needs tests. *)
1144    "define an Augeas variable",
1145    "\
1146 Defines an Augeas variable C<name> whose value is the result
1147 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1148 undefined.
1149
1150 On success this returns the number of nodes in C<expr>, or
1151 C<0> if C<expr> evaluates to something which is not a nodeset.");
1152
1153   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1154    [], (* XXX Augeas code needs tests. *)
1155    "define an Augeas node",
1156    "\
1157 Defines a variable C<name> whose value is the result of
1158 evaluating C<expr>.
1159
1160 If C<expr> evaluates to an empty nodeset, a node is created,
1161 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1162 C<name> will be the nodeset containing that single node.
1163
1164 On success this returns a pair containing the
1165 number of nodes in the nodeset, and a boolean flag
1166 if a node was created.");
1167
1168   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1169    [], (* XXX Augeas code needs tests. *)
1170    "look up the value of an Augeas path",
1171    "\
1172 Look up the value associated with C<path>.  If C<path>
1173 matches exactly one node, the C<value> is returned.");
1174
1175   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1176    [], (* XXX Augeas code needs tests. *)
1177    "set Augeas path to value",
1178    "\
1179 Set the value associated with C<path> to C<value>.");
1180
1181   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1182    [], (* XXX Augeas code needs tests. *)
1183    "insert a sibling Augeas node",
1184    "\
1185 Create a new sibling C<label> for C<path>, inserting it into
1186 the tree before or after C<path> (depending on the boolean
1187 flag C<before>).
1188
1189 C<path> must match exactly one existing node in the tree, and
1190 C<label> must be a label, ie. not contain C</>, C<*> or end
1191 with a bracketed index C<[N]>.");
1192
1193   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1194    [], (* XXX Augeas code needs tests. *)
1195    "remove an Augeas path",
1196    "\
1197 Remove C<path> and all of its children.
1198
1199 On success this returns the number of entries which were removed.");
1200
1201   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1202    [], (* XXX Augeas code needs tests. *)
1203    "move Augeas node",
1204    "\
1205 Move the node C<src> to C<dest>.  C<src> must match exactly
1206 one node.  C<dest> is overwritten if it exists.");
1207
1208   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1209    [], (* XXX Augeas code needs tests. *)
1210    "return Augeas nodes which match augpath",
1211    "\
1212 Returns a list of paths which match the path expression C<path>.
1213 The returned paths are sufficiently qualified so that they match
1214 exactly one node in the current tree.");
1215
1216   ("aug_save", (RErr, []), 25, [],
1217    [], (* XXX Augeas code needs tests. *)
1218    "write all pending Augeas changes to disk",
1219    "\
1220 This writes all pending changes to disk.
1221
1222 The flags which were passed to C<guestfs_aug_init> affect exactly
1223 how files are saved.");
1224
1225   ("aug_load", (RErr, []), 27, [],
1226    [], (* XXX Augeas code needs tests. *)
1227    "load files into the tree",
1228    "\
1229 Load files into the tree.
1230
1231 See C<aug_load> in the Augeas documentation for the full gory
1232 details.");
1233
1234   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1235    [], (* XXX Augeas code needs tests. *)
1236    "list Augeas nodes under augpath",
1237    "\
1238 This is just a shortcut for listing C<guestfs_aug_match>
1239 C<path/*> and sorting the resulting nodes into alphabetical order.");
1240
1241   ("rm", (RErr, [Pathname "path"]), 29, [],
1242    [InitBasicFS, Always, TestRun
1243       [["touch"; "/new"];
1244        ["rm"; "/new"]];
1245     InitBasicFS, Always, TestLastFail
1246       [["rm"; "/new"]];
1247     InitBasicFS, Always, TestLastFail
1248       [["mkdir"; "/new"];
1249        ["rm"; "/new"]]],
1250    "remove a file",
1251    "\
1252 Remove the single file C<path>.");
1253
1254   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1255    [InitBasicFS, Always, TestRun
1256       [["mkdir"; "/new"];
1257        ["rmdir"; "/new"]];
1258     InitBasicFS, Always, TestLastFail
1259       [["rmdir"; "/new"]];
1260     InitBasicFS, Always, TestLastFail
1261       [["touch"; "/new"];
1262        ["rmdir"; "/new"]]],
1263    "remove a directory",
1264    "\
1265 Remove the single directory C<path>.");
1266
1267   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1268    [InitBasicFS, Always, TestOutputFalse
1269       [["mkdir"; "/new"];
1270        ["mkdir"; "/new/foo"];
1271        ["touch"; "/new/foo/bar"];
1272        ["rm_rf"; "/new"];
1273        ["exists"; "/new"]]],
1274    "remove a file or directory recursively",
1275    "\
1276 Remove the file or directory C<path>, recursively removing the
1277 contents if its a directory.  This is like the C<rm -rf> shell
1278 command.");
1279
1280   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1281    [InitBasicFS, Always, TestOutputTrue
1282       [["mkdir"; "/new"];
1283        ["is_dir"; "/new"]];
1284     InitBasicFS, Always, TestLastFail
1285       [["mkdir"; "/new/foo/bar"]]],
1286    "create a directory",
1287    "\
1288 Create a directory named C<path>.");
1289
1290   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1291    [InitBasicFS, Always, TestOutputTrue
1292       [["mkdir_p"; "/new/foo/bar"];
1293        ["is_dir"; "/new/foo/bar"]];
1294     InitBasicFS, Always, TestOutputTrue
1295       [["mkdir_p"; "/new/foo/bar"];
1296        ["is_dir"; "/new/foo"]];
1297     InitBasicFS, Always, TestOutputTrue
1298       [["mkdir_p"; "/new/foo/bar"];
1299        ["is_dir"; "/new"]];
1300     (* Regression tests for RHBZ#503133: *)
1301     InitBasicFS, Always, TestRun
1302       [["mkdir"; "/new"];
1303        ["mkdir_p"; "/new"]];
1304     InitBasicFS, Always, TestLastFail
1305       [["touch"; "/new"];
1306        ["mkdir_p"; "/new"]]],
1307    "create a directory and parents",
1308    "\
1309 Create a directory named C<path>, creating any parent directories
1310 as necessary.  This is like the C<mkdir -p> shell command.");
1311
1312   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1313    [], (* XXX Need stat command to test *)
1314    "change file mode",
1315    "\
1316 Change the mode (permissions) of C<path> to C<mode>.  Only
1317 numeric modes are supported.");
1318
1319   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1320    [], (* XXX Need stat command to test *)
1321    "change file owner and group",
1322    "\
1323 Change the file owner to C<owner> and group to C<group>.
1324
1325 Only numeric uid and gid are supported.  If you want to use
1326 names, you will need to locate and parse the password file
1327 yourself (Augeas support makes this relatively easy).");
1328
1329   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1330    [InitISOFS, Always, TestOutputTrue (
1331       [["exists"; "/empty"]]);
1332     InitISOFS, Always, TestOutputTrue (
1333       [["exists"; "/directory"]])],
1334    "test if file or directory exists",
1335    "\
1336 This returns C<true> if and only if there is a file, directory
1337 (or anything) with the given C<path> name.
1338
1339 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1340
1341   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1342    [InitISOFS, Always, TestOutputTrue (
1343       [["is_file"; "/known-1"]]);
1344     InitISOFS, Always, TestOutputFalse (
1345       [["is_file"; "/directory"]])],
1346    "test if file exists",
1347    "\
1348 This returns C<true> if and only if there is a file
1349 with the given C<path> name.  Note that it returns false for
1350 other objects like directories.
1351
1352 See also C<guestfs_stat>.");
1353
1354   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1355    [InitISOFS, Always, TestOutputFalse (
1356       [["is_dir"; "/known-3"]]);
1357     InitISOFS, Always, TestOutputTrue (
1358       [["is_dir"; "/directory"]])],
1359    "test if file exists",
1360    "\
1361 This returns C<true> if and only if there is a directory
1362 with the given C<path> name.  Note that it returns false for
1363 other objects like files.
1364
1365 See also C<guestfs_stat>.");
1366
1367   ("pvcreate", (RErr, [Device "device"]), 39, [],
1368    [InitEmpty, Always, TestOutputListOfDevices (
1369       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1370        ["pvcreate"; "/dev/sda1"];
1371        ["pvcreate"; "/dev/sda2"];
1372        ["pvcreate"; "/dev/sda3"];
1373        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1374    "create an LVM physical volume",
1375    "\
1376 This creates an LVM physical volume on the named C<device>,
1377 where C<device> should usually be a partition name such
1378 as C</dev/sda1>.");
1379
1380   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1381    [InitEmpty, Always, TestOutputList (
1382       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1383        ["pvcreate"; "/dev/sda1"];
1384        ["pvcreate"; "/dev/sda2"];
1385        ["pvcreate"; "/dev/sda3"];
1386        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1387        ["vgcreate"; "VG2"; "/dev/sda3"];
1388        ["vgs"]], ["VG1"; "VG2"])],
1389    "create an LVM volume group",
1390    "\
1391 This creates an LVM volume group called C<volgroup>
1392 from the non-empty list of physical volumes C<physvols>.");
1393
1394   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1395    [InitEmpty, Always, TestOutputList (
1396       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1397        ["pvcreate"; "/dev/sda1"];
1398        ["pvcreate"; "/dev/sda2"];
1399        ["pvcreate"; "/dev/sda3"];
1400        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1401        ["vgcreate"; "VG2"; "/dev/sda3"];
1402        ["lvcreate"; "LV1"; "VG1"; "50"];
1403        ["lvcreate"; "LV2"; "VG1"; "50"];
1404        ["lvcreate"; "LV3"; "VG2"; "50"];
1405        ["lvcreate"; "LV4"; "VG2"; "50"];
1406        ["lvcreate"; "LV5"; "VG2"; "50"];
1407        ["lvs"]],
1408       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1409        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1410    "create an LVM volume group",
1411    "\
1412 This creates an LVM volume group called C<logvol>
1413 on the volume group C<volgroup>, with C<size> megabytes.");
1414
1415   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1416    [InitEmpty, Always, TestOutput (
1417       [["part_disk"; "/dev/sda"; "mbr"];
1418        ["mkfs"; "ext2"; "/dev/sda1"];
1419        ["mount"; "/dev/sda1"; "/"];
1420        ["write_file"; "/new"; "new file contents"; "0"];
1421        ["cat"; "/new"]], "new file contents")],
1422    "make a filesystem",
1423    "\
1424 This creates a filesystem on C<device> (usually a partition
1425 or LVM logical volume).  The filesystem type is C<fstype>, for
1426 example C<ext3>.");
1427
1428   ("sfdisk", (RErr, [Device "device";
1429                      Int "cyls"; Int "heads"; Int "sectors";
1430                      StringList "lines"]), 43, [DangerWillRobinson],
1431    [],
1432    "create partitions on a block device",
1433    "\
1434 This is a direct interface to the L<sfdisk(8)> program for creating
1435 partitions on block devices.
1436
1437 C<device> should be a block device, for example C</dev/sda>.
1438
1439 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1440 and sectors on the device, which are passed directly to sfdisk as
1441 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1442 of these, then the corresponding parameter is omitted.  Usually for
1443 'large' disks, you can just pass C<0> for these, but for small
1444 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1445 out the right geometry and you will need to tell it.
1446
1447 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1448 information refer to the L<sfdisk(8)> manpage.
1449
1450 To create a single partition occupying the whole disk, you would
1451 pass C<lines> as a single element list, when the single element being
1452 the string C<,> (comma).
1453
1454 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1455 C<guestfs_part_init>");
1456
1457   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1458    [InitBasicFS, Always, TestOutput (
1459       [["write_file"; "/new"; "new file contents"; "0"];
1460        ["cat"; "/new"]], "new file contents");
1461     InitBasicFS, Always, TestOutput (
1462       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1463        ["cat"; "/new"]], "\nnew file contents\n");
1464     InitBasicFS, Always, TestOutput (
1465       [["write_file"; "/new"; "\n\n"; "0"];
1466        ["cat"; "/new"]], "\n\n");
1467     InitBasicFS, Always, TestOutput (
1468       [["write_file"; "/new"; ""; "0"];
1469        ["cat"; "/new"]], "");
1470     InitBasicFS, Always, TestOutput (
1471       [["write_file"; "/new"; "\n\n\n"; "0"];
1472        ["cat"; "/new"]], "\n\n\n");
1473     InitBasicFS, Always, TestOutput (
1474       [["write_file"; "/new"; "\n"; "0"];
1475        ["cat"; "/new"]], "\n")],
1476    "create a file",
1477    "\
1478 This call creates a file called C<path>.  The contents of the
1479 file is the string C<content> (which can contain any 8 bit data),
1480 with length C<size>.
1481
1482 As a special case, if C<size> is C<0>
1483 then the length is calculated using C<strlen> (so in this case
1484 the content cannot contain embedded ASCII NULs).
1485
1486 I<NB.> Owing to a bug, writing content containing ASCII NUL
1487 characters does I<not> work, even if the length is specified.
1488 We hope to resolve this bug in a future version.  In the meantime
1489 use C<guestfs_upload>.");
1490
1491   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1492    [InitEmpty, Always, TestOutputListOfDevices (
1493       [["part_disk"; "/dev/sda"; "mbr"];
1494        ["mkfs"; "ext2"; "/dev/sda1"];
1495        ["mount"; "/dev/sda1"; "/"];
1496        ["mounts"]], ["/dev/sda1"]);
1497     InitEmpty, Always, TestOutputList (
1498       [["part_disk"; "/dev/sda"; "mbr"];
1499        ["mkfs"; "ext2"; "/dev/sda1"];
1500        ["mount"; "/dev/sda1"; "/"];
1501        ["umount"; "/"];
1502        ["mounts"]], [])],
1503    "unmount a filesystem",
1504    "\
1505 This unmounts the given filesystem.  The filesystem may be
1506 specified either by its mountpoint (path) or the device which
1507 contains the filesystem.");
1508
1509   ("mounts", (RStringList "devices", []), 46, [],
1510    [InitBasicFS, Always, TestOutputListOfDevices (
1511       [["mounts"]], ["/dev/sda1"])],
1512    "show mounted filesystems",
1513    "\
1514 This returns the list of currently mounted filesystems.  It returns
1515 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1516
1517 Some internal mounts are not shown.
1518
1519 See also: C<guestfs_mountpoints>");
1520
1521   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1522    [InitBasicFS, Always, TestOutputList (
1523       [["umount_all"];
1524        ["mounts"]], []);
1525     (* check that umount_all can unmount nested mounts correctly: *)
1526     InitEmpty, Always, TestOutputList (
1527       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1528        ["mkfs"; "ext2"; "/dev/sda1"];
1529        ["mkfs"; "ext2"; "/dev/sda2"];
1530        ["mkfs"; "ext2"; "/dev/sda3"];
1531        ["mount"; "/dev/sda1"; "/"];
1532        ["mkdir"; "/mp1"];
1533        ["mount"; "/dev/sda2"; "/mp1"];
1534        ["mkdir"; "/mp1/mp2"];
1535        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1536        ["mkdir"; "/mp1/mp2/mp3"];
1537        ["umount_all"];
1538        ["mounts"]], [])],
1539    "unmount all filesystems",
1540    "\
1541 This unmounts all mounted filesystems.
1542
1543 Some internal mounts are not unmounted by this call.");
1544
1545   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1546    [],
1547    "remove all LVM LVs, VGs and PVs",
1548    "\
1549 This command removes all LVM logical volumes, volume groups
1550 and physical volumes.");
1551
1552   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1553    [InitISOFS, Always, TestOutput (
1554       [["file"; "/empty"]], "empty");
1555     InitISOFS, Always, TestOutput (
1556       [["file"; "/known-1"]], "ASCII text");
1557     InitISOFS, Always, TestLastFail (
1558       [["file"; "/notexists"]])],
1559    "determine file type",
1560    "\
1561 This call uses the standard L<file(1)> command to determine
1562 the type or contents of the file.  This also works on devices,
1563 for example to find out whether a partition contains a filesystem.
1564
1565 This call will also transparently look inside various types
1566 of compressed file.
1567
1568 The exact command which runs is C<file -zbsL path>.  Note in
1569 particular that the filename is not prepended to the output
1570 (the C<-b> option).");
1571
1572   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1573    [InitBasicFS, Always, TestOutput (
1574       [["upload"; "test-command"; "/test-command"];
1575        ["chmod"; "0o755"; "/test-command"];
1576        ["command"; "/test-command 1"]], "Result1");
1577     InitBasicFS, Always, TestOutput (
1578       [["upload"; "test-command"; "/test-command"];
1579        ["chmod"; "0o755"; "/test-command"];
1580        ["command"; "/test-command 2"]], "Result2\n");
1581     InitBasicFS, Always, TestOutput (
1582       [["upload"; "test-command"; "/test-command"];
1583        ["chmod"; "0o755"; "/test-command"];
1584        ["command"; "/test-command 3"]], "\nResult3");
1585     InitBasicFS, Always, TestOutput (
1586       [["upload"; "test-command"; "/test-command"];
1587        ["chmod"; "0o755"; "/test-command"];
1588        ["command"; "/test-command 4"]], "\nResult4\n");
1589     InitBasicFS, Always, TestOutput (
1590       [["upload"; "test-command"; "/test-command"];
1591        ["chmod"; "0o755"; "/test-command"];
1592        ["command"; "/test-command 5"]], "\nResult5\n\n");
1593     InitBasicFS, Always, TestOutput (
1594       [["upload"; "test-command"; "/test-command"];
1595        ["chmod"; "0o755"; "/test-command"];
1596        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1597     InitBasicFS, Always, TestOutput (
1598       [["upload"; "test-command"; "/test-command"];
1599        ["chmod"; "0o755"; "/test-command"];
1600        ["command"; "/test-command 7"]], "");
1601     InitBasicFS, Always, TestOutput (
1602       [["upload"; "test-command"; "/test-command"];
1603        ["chmod"; "0o755"; "/test-command"];
1604        ["command"; "/test-command 8"]], "\n");
1605     InitBasicFS, Always, TestOutput (
1606       [["upload"; "test-command"; "/test-command"];
1607        ["chmod"; "0o755"; "/test-command"];
1608        ["command"; "/test-command 9"]], "\n\n");
1609     InitBasicFS, Always, TestOutput (
1610       [["upload"; "test-command"; "/test-command"];
1611        ["chmod"; "0o755"; "/test-command"];
1612        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1613     InitBasicFS, Always, TestOutput (
1614       [["upload"; "test-command"; "/test-command"];
1615        ["chmod"; "0o755"; "/test-command"];
1616        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1617     InitBasicFS, Always, TestLastFail (
1618       [["upload"; "test-command"; "/test-command"];
1619        ["chmod"; "0o755"; "/test-command"];
1620        ["command"; "/test-command"]])],
1621    "run a command from the guest filesystem",
1622    "\
1623 This call runs a command from the guest filesystem.  The
1624 filesystem must be mounted, and must contain a compatible
1625 operating system (ie. something Linux, with the same
1626 or compatible processor architecture).
1627
1628 The single parameter is an argv-style list of arguments.
1629 The first element is the name of the program to run.
1630 Subsequent elements are parameters.  The list must be
1631 non-empty (ie. must contain a program name).  Note that
1632 the command runs directly, and is I<not> invoked via
1633 the shell (see C<guestfs_sh>).
1634
1635 The return value is anything printed to I<stdout> by
1636 the command.
1637
1638 If the command returns a non-zero exit status, then
1639 this function returns an error message.  The error message
1640 string is the content of I<stderr> from the command.
1641
1642 The C<$PATH> environment variable will contain at least
1643 C</usr/bin> and C</bin>.  If you require a program from
1644 another location, you should provide the full path in the
1645 first parameter.
1646
1647 Shared libraries and data files required by the program
1648 must be available on filesystems which are mounted in the
1649 correct places.  It is the caller's responsibility to ensure
1650 all filesystems that are needed are mounted at the right
1651 locations.");
1652
1653   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1654    [InitBasicFS, Always, TestOutputList (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command_lines"; "/test-command 1"]], ["Result1"]);
1658     InitBasicFS, Always, TestOutputList (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command_lines"; "/test-command 2"]], ["Result2"]);
1662     InitBasicFS, Always, TestOutputList (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1666     InitBasicFS, Always, TestOutputList (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1670     InitBasicFS, Always, TestOutputList (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1674     InitBasicFS, Always, TestOutputList (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1678     InitBasicFS, Always, TestOutputList (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command_lines"; "/test-command 7"]], []);
1682     InitBasicFS, Always, TestOutputList (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command_lines"; "/test-command 8"]], [""]);
1686     InitBasicFS, Always, TestOutputList (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command_lines"; "/test-command 9"]], ["";""]);
1690     InitBasicFS, Always, TestOutputList (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1694     InitBasicFS, Always, TestOutputList (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1698    "run a command, returning lines",
1699    "\
1700 This is the same as C<guestfs_command>, but splits the
1701 result into a list of lines.
1702
1703 See also: C<guestfs_sh_lines>");
1704
1705   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1706    [InitISOFS, Always, TestOutputStruct (
1707       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1708    "get file information",
1709    "\
1710 Returns file information for the given C<path>.
1711
1712 This is the same as the C<stat(2)> system call.");
1713
1714   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1715    [InitISOFS, Always, TestOutputStruct (
1716       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1717    "get file information for a symbolic link",
1718    "\
1719 Returns file information for the given C<path>.
1720
1721 This is the same as C<guestfs_stat> except that if C<path>
1722 is a symbolic link, then the link is stat-ed, not the file it
1723 refers to.
1724
1725 This is the same as the C<lstat(2)> system call.");
1726
1727   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1728    [InitISOFS, Always, TestOutputStruct (
1729       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1730    "get file system statistics",
1731    "\
1732 Returns file system statistics for any mounted file system.
1733 C<path> should be a file or directory in the mounted file system
1734 (typically it is the mount point itself, but it doesn't need to be).
1735
1736 This is the same as the C<statvfs(2)> system call.");
1737
1738   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1739    [], (* XXX test *)
1740    "get ext2/ext3/ext4 superblock details",
1741    "\
1742 This returns the contents of the ext2, ext3 or ext4 filesystem
1743 superblock on C<device>.
1744
1745 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1746 manpage for more details.  The list of fields returned isn't
1747 clearly defined, and depends on both the version of C<tune2fs>
1748 that libguestfs was built against, and the filesystem itself.");
1749
1750   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1751    [InitEmpty, Always, TestOutputTrue (
1752       [["blockdev_setro"; "/dev/sda"];
1753        ["blockdev_getro"; "/dev/sda"]])],
1754    "set block device to read-only",
1755    "\
1756 Sets the block device named C<device> to read-only.
1757
1758 This uses the L<blockdev(8)> command.");
1759
1760   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1761    [InitEmpty, Always, TestOutputFalse (
1762       [["blockdev_setrw"; "/dev/sda"];
1763        ["blockdev_getro"; "/dev/sda"]])],
1764    "set block device to read-write",
1765    "\
1766 Sets the block device named C<device> to read-write.
1767
1768 This uses the L<blockdev(8)> command.");
1769
1770   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1771    [InitEmpty, Always, TestOutputTrue (
1772       [["blockdev_setro"; "/dev/sda"];
1773        ["blockdev_getro"; "/dev/sda"]])],
1774    "is block device set to read-only",
1775    "\
1776 Returns a boolean indicating if the block device is read-only
1777 (true if read-only, false if not).
1778
1779 This uses the L<blockdev(8)> command.");
1780
1781   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1782    [InitEmpty, Always, TestOutputInt (
1783       [["blockdev_getss"; "/dev/sda"]], 512)],
1784    "get sectorsize of block device",
1785    "\
1786 This returns the size of sectors on a block device.
1787 Usually 512, but can be larger for modern devices.
1788
1789 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1790 for that).
1791
1792 This uses the L<blockdev(8)> command.");
1793
1794   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1795    [InitEmpty, Always, TestOutputInt (
1796       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1797    "get blocksize of block device",
1798    "\
1799 This returns the block size of a device.
1800
1801 (Note this is different from both I<size in blocks> and
1802 I<filesystem block size>).
1803
1804 This uses the L<blockdev(8)> command.");
1805
1806   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1807    [], (* XXX test *)
1808    "set blocksize of block device",
1809    "\
1810 This sets the block size of a device.
1811
1812 (Note this is different from both I<size in blocks> and
1813 I<filesystem block size>).
1814
1815 This uses the L<blockdev(8)> command.");
1816
1817   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1818    [InitEmpty, Always, TestOutputInt (
1819       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1820    "get total size of device in 512-byte sectors",
1821    "\
1822 This returns the size of the device in units of 512-byte sectors
1823 (even if the sectorsize isn't 512 bytes ... weird).
1824
1825 See also C<guestfs_blockdev_getss> for the real sector size of
1826 the device, and C<guestfs_blockdev_getsize64> for the more
1827 useful I<size in bytes>.
1828
1829 This uses the L<blockdev(8)> command.");
1830
1831   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1832    [InitEmpty, Always, TestOutputInt (
1833       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1834    "get total size of device in bytes",
1835    "\
1836 This returns the size of the device in bytes.
1837
1838 See also C<guestfs_blockdev_getsz>.
1839
1840 This uses the L<blockdev(8)> command.");
1841
1842   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1843    [InitEmpty, Always, TestRun
1844       [["blockdev_flushbufs"; "/dev/sda"]]],
1845    "flush device buffers",
1846    "\
1847 This tells the kernel to flush internal buffers associated
1848 with C<device>.
1849
1850 This uses the L<blockdev(8)> command.");
1851
1852   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1853    [InitEmpty, Always, TestRun
1854       [["blockdev_rereadpt"; "/dev/sda"]]],
1855    "reread partition table",
1856    "\
1857 Reread the partition table on C<device>.
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1862    [InitBasicFS, Always, TestOutput (
1863       (* Pick a file from cwd which isn't likely to change. *)
1864       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1865        ["checksum"; "md5"; "/COPYING.LIB"]],
1866         Digest.to_hex (Digest.file "COPYING.LIB"))],
1867    "upload a file from the local machine",
1868    "\
1869 Upload local file C<filename> to C<remotefilename> on the
1870 filesystem.
1871
1872 C<filename> can also be a named pipe.
1873
1874 See also C<guestfs_download>.");
1875
1876   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1877    [InitBasicFS, Always, TestOutput (
1878       (* Pick a file from cwd which isn't likely to change. *)
1879       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1880        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1881        ["upload"; "testdownload.tmp"; "/upload"];
1882        ["checksum"; "md5"; "/upload"]],
1883         Digest.to_hex (Digest.file "COPYING.LIB"))],
1884    "download a file to the local machine",
1885    "\
1886 Download file C<remotefilename> and save it as C<filename>
1887 on the local machine.
1888
1889 C<filename> can also be a named pipe.
1890
1891 See also C<guestfs_upload>, C<guestfs_cat>.");
1892
1893   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1894    [InitISOFS, Always, TestOutput (
1895       [["checksum"; "crc"; "/known-3"]], "2891671662");
1896     InitISOFS, Always, TestLastFail (
1897       [["checksum"; "crc"; "/notexists"]]);
1898     InitISOFS, Always, TestOutput (
1899       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1900     InitISOFS, Always, TestOutput (
1901       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1902     InitISOFS, Always, TestOutput (
1903       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1904     InitISOFS, Always, TestOutput (
1905       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1906     InitISOFS, Always, TestOutput (
1907       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1908     InitISOFS, Always, TestOutput (
1909       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1910    "compute MD5, SHAx or CRC checksum of file",
1911    "\
1912 This call computes the MD5, SHAx or CRC checksum of the
1913 file named C<path>.
1914
1915 The type of checksum to compute is given by the C<csumtype>
1916 parameter which must have one of the following values:
1917
1918 =over 4
1919
1920 =item C<crc>
1921
1922 Compute the cyclic redundancy check (CRC) specified by POSIX
1923 for the C<cksum> command.
1924
1925 =item C<md5>
1926
1927 Compute the MD5 hash (using the C<md5sum> program).
1928
1929 =item C<sha1>
1930
1931 Compute the SHA1 hash (using the C<sha1sum> program).
1932
1933 =item C<sha224>
1934
1935 Compute the SHA224 hash (using the C<sha224sum> program).
1936
1937 =item C<sha256>
1938
1939 Compute the SHA256 hash (using the C<sha256sum> program).
1940
1941 =item C<sha384>
1942
1943 Compute the SHA384 hash (using the C<sha384sum> program).
1944
1945 =item C<sha512>
1946
1947 Compute the SHA512 hash (using the C<sha512sum> program).
1948
1949 =back
1950
1951 The checksum is returned as a printable string.");
1952
1953   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1954    [InitBasicFS, Always, TestOutput (
1955       [["tar_in"; "../images/helloworld.tar"; "/"];
1956        ["cat"; "/hello"]], "hello\n")],
1957    "unpack tarfile to directory",
1958    "\
1959 This command uploads and unpacks local file C<tarfile> (an
1960 I<uncompressed> tar file) into C<directory>.
1961
1962 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1963
1964   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1965    [],
1966    "pack directory into tarfile",
1967    "\
1968 This command packs the contents of C<directory> and downloads
1969 it to local file C<tarfile>.
1970
1971 To download a compressed tarball, use C<guestfs_tgz_out>.");
1972
1973   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1974    [InitBasicFS, Always, TestOutput (
1975       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1976        ["cat"; "/hello"]], "hello\n")],
1977    "unpack compressed tarball to directory",
1978    "\
1979 This command uploads and unpacks local file C<tarball> (a
1980 I<gzip compressed> tar file) into C<directory>.
1981
1982 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1983
1984   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1985    [],
1986    "pack directory into compressed tarball",
1987    "\
1988 This command packs the contents of C<directory> and downloads
1989 it to local file C<tarball>.
1990
1991 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1992
1993   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1994    [InitBasicFS, Always, TestLastFail (
1995       [["umount"; "/"];
1996        ["mount_ro"; "/dev/sda1"; "/"];
1997        ["touch"; "/new"]]);
1998     InitBasicFS, Always, TestOutput (
1999       [["write_file"; "/new"; "data"; "0"];
2000        ["umount"; "/"];
2001        ["mount_ro"; "/dev/sda1"; "/"];
2002        ["cat"; "/new"]], "data")],
2003    "mount a guest disk, read-only",
2004    "\
2005 This is the same as the C<guestfs_mount> command, but it
2006 mounts the filesystem with the read-only (I<-o ro>) flag.");
2007
2008   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2009    [],
2010    "mount a guest disk with mount options",
2011    "\
2012 This is the same as the C<guestfs_mount> command, but it
2013 allows you to set the mount options as for the
2014 L<mount(8)> I<-o> flag.");
2015
2016   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2017    [],
2018    "mount a guest disk with mount options and vfstype",
2019    "\
2020 This is the same as the C<guestfs_mount> command, but it
2021 allows you to set both the mount options and the vfstype
2022 as for the L<mount(8)> I<-o> and I<-t> flags.");
2023
2024   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2025    [],
2026    "debugging and internals",
2027    "\
2028 The C<guestfs_debug> command exposes some internals of
2029 C<guestfsd> (the guestfs daemon) that runs inside the
2030 qemu subprocess.
2031
2032 There is no comprehensive help for this command.  You have
2033 to look at the file C<daemon/debug.c> in the libguestfs source
2034 to find out what you can do.");
2035
2036   ("lvremove", (RErr, [Device "device"]), 77, [],
2037    [InitEmpty, Always, TestOutputList (
2038       [["part_disk"; "/dev/sda"; "mbr"];
2039        ["pvcreate"; "/dev/sda1"];
2040        ["vgcreate"; "VG"; "/dev/sda1"];
2041        ["lvcreate"; "LV1"; "VG"; "50"];
2042        ["lvcreate"; "LV2"; "VG"; "50"];
2043        ["lvremove"; "/dev/VG/LV1"];
2044        ["lvs"]], ["/dev/VG/LV2"]);
2045     InitEmpty, Always, TestOutputList (
2046       [["part_disk"; "/dev/sda"; "mbr"];
2047        ["pvcreate"; "/dev/sda1"];
2048        ["vgcreate"; "VG"; "/dev/sda1"];
2049        ["lvcreate"; "LV1"; "VG"; "50"];
2050        ["lvcreate"; "LV2"; "VG"; "50"];
2051        ["lvremove"; "/dev/VG"];
2052        ["lvs"]], []);
2053     InitEmpty, Always, TestOutputList (
2054       [["part_disk"; "/dev/sda"; "mbr"];
2055        ["pvcreate"; "/dev/sda1"];
2056        ["vgcreate"; "VG"; "/dev/sda1"];
2057        ["lvcreate"; "LV1"; "VG"; "50"];
2058        ["lvcreate"; "LV2"; "VG"; "50"];
2059        ["lvremove"; "/dev/VG"];
2060        ["vgs"]], ["VG"])],
2061    "remove an LVM logical volume",
2062    "\
2063 Remove an LVM logical volume C<device>, where C<device> is
2064 the path to the LV, such as C</dev/VG/LV>.
2065
2066 You can also remove all LVs in a volume group by specifying
2067 the VG name, C</dev/VG>.");
2068
2069   ("vgremove", (RErr, [String "vgname"]), 78, [],
2070    [InitEmpty, Always, TestOutputList (
2071       [["part_disk"; "/dev/sda"; "mbr"];
2072        ["pvcreate"; "/dev/sda1"];
2073        ["vgcreate"; "VG"; "/dev/sda1"];
2074        ["lvcreate"; "LV1"; "VG"; "50"];
2075        ["lvcreate"; "LV2"; "VG"; "50"];
2076        ["vgremove"; "VG"];
2077        ["lvs"]], []);
2078     InitEmpty, Always, TestOutputList (
2079       [["part_disk"; "/dev/sda"; "mbr"];
2080        ["pvcreate"; "/dev/sda1"];
2081        ["vgcreate"; "VG"; "/dev/sda1"];
2082        ["lvcreate"; "LV1"; "VG"; "50"];
2083        ["lvcreate"; "LV2"; "VG"; "50"];
2084        ["vgremove"; "VG"];
2085        ["vgs"]], [])],
2086    "remove an LVM volume group",
2087    "\
2088 Remove an LVM volume group C<vgname>, (for example C<VG>).
2089
2090 This also forcibly removes all logical volumes in the volume
2091 group (if any).");
2092
2093   ("pvremove", (RErr, [Device "device"]), 79, [],
2094    [InitEmpty, Always, TestOutputListOfDevices (
2095       [["part_disk"; "/dev/sda"; "mbr"];
2096        ["pvcreate"; "/dev/sda1"];
2097        ["vgcreate"; "VG"; "/dev/sda1"];
2098        ["lvcreate"; "LV1"; "VG"; "50"];
2099        ["lvcreate"; "LV2"; "VG"; "50"];
2100        ["vgremove"; "VG"];
2101        ["pvremove"; "/dev/sda1"];
2102        ["lvs"]], []);
2103     InitEmpty, Always, TestOutputListOfDevices (
2104       [["part_disk"; "/dev/sda"; "mbr"];
2105        ["pvcreate"; "/dev/sda1"];
2106        ["vgcreate"; "VG"; "/dev/sda1"];
2107        ["lvcreate"; "LV1"; "VG"; "50"];
2108        ["lvcreate"; "LV2"; "VG"; "50"];
2109        ["vgremove"; "VG"];
2110        ["pvremove"; "/dev/sda1"];
2111        ["vgs"]], []);
2112     InitEmpty, Always, TestOutputListOfDevices (
2113       [["part_disk"; "/dev/sda"; "mbr"];
2114        ["pvcreate"; "/dev/sda1"];
2115        ["vgcreate"; "VG"; "/dev/sda1"];
2116        ["lvcreate"; "LV1"; "VG"; "50"];
2117        ["lvcreate"; "LV2"; "VG"; "50"];
2118        ["vgremove"; "VG"];
2119        ["pvremove"; "/dev/sda1"];
2120        ["pvs"]], [])],
2121    "remove an LVM physical volume",
2122    "\
2123 This wipes a physical volume C<device> so that LVM will no longer
2124 recognise it.
2125
2126 The implementation uses the C<pvremove> command which refuses to
2127 wipe physical volumes that contain any volume groups, so you have
2128 to remove those first.");
2129
2130   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2131    [InitBasicFS, Always, TestOutput (
2132       [["set_e2label"; "/dev/sda1"; "testlabel"];
2133        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2134    "set the ext2/3/4 filesystem label",
2135    "\
2136 This sets the ext2/3/4 filesystem label of the filesystem on
2137 C<device> to C<label>.  Filesystem labels are limited to
2138 16 characters.
2139
2140 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2141 to return the existing label on a filesystem.");
2142
2143   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2144    [],
2145    "get the ext2/3/4 filesystem label",
2146    "\
2147 This returns the ext2/3/4 filesystem label of the filesystem on
2148 C<device>.");
2149
2150   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2151    (let uuid = uuidgen () in
2152     [InitBasicFS, Always, TestOutput (
2153        [["set_e2uuid"; "/dev/sda1"; uuid];
2154         ["get_e2uuid"; "/dev/sda1"]], uuid);
2155      InitBasicFS, Always, TestOutput (
2156        [["set_e2uuid"; "/dev/sda1"; "clear"];
2157         ["get_e2uuid"; "/dev/sda1"]], "");
2158      (* We can't predict what UUIDs will be, so just check the commands run. *)
2159      InitBasicFS, Always, TestRun (
2160        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2161      InitBasicFS, Always, TestRun (
2162        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2163    "set the ext2/3/4 filesystem UUID",
2164    "\
2165 This sets the ext2/3/4 filesystem UUID of the filesystem on
2166 C<device> to C<uuid>.  The format of the UUID and alternatives
2167 such as C<clear>, C<random> and C<time> are described in the
2168 L<tune2fs(8)> manpage.
2169
2170 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2171 to return the existing UUID of a filesystem.");
2172
2173   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2174    [],
2175    "get the ext2/3/4 filesystem UUID",
2176    "\
2177 This returns the ext2/3/4 filesystem UUID of the filesystem on
2178 C<device>.");
2179
2180   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2181    [InitBasicFS, Always, TestOutputInt (
2182       [["umount"; "/dev/sda1"];
2183        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2184     InitBasicFS, Always, TestOutputInt (
2185       [["umount"; "/dev/sda1"];
2186        ["zero"; "/dev/sda1"];
2187        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2188    "run the filesystem checker",
2189    "\
2190 This runs the filesystem checker (fsck) on C<device> which
2191 should have filesystem type C<fstype>.
2192
2193 The returned integer is the status.  See L<fsck(8)> for the
2194 list of status codes from C<fsck>.
2195
2196 Notes:
2197
2198 =over 4
2199
2200 =item *
2201
2202 Multiple status codes can be summed together.
2203
2204 =item *
2205
2206 A non-zero return code can mean \"success\", for example if
2207 errors have been corrected on the filesystem.
2208
2209 =item *
2210
2211 Checking or repairing NTFS volumes is not supported
2212 (by linux-ntfs).
2213
2214 =back
2215
2216 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2217
2218   ("zero", (RErr, [Device "device"]), 85, [],
2219    [InitBasicFS, Always, TestOutput (
2220       [["umount"; "/dev/sda1"];
2221        ["zero"; "/dev/sda1"];
2222        ["file"; "/dev/sda1"]], "data")],
2223    "write zeroes to the device",
2224    "\
2225 This command writes zeroes over the first few blocks of C<device>.
2226
2227 How many blocks are zeroed isn't specified (but it's I<not> enough
2228 to securely wipe the device).  It should be sufficient to remove
2229 any partition tables, filesystem superblocks and so on.
2230
2231 See also: C<guestfs_scrub_device>.");
2232
2233   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2234    (* Test disabled because grub-install incompatible with virtio-blk driver.
2235     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2236     *)
2237    [InitBasicFS, Disabled, TestOutputTrue (
2238       [["grub_install"; "/"; "/dev/sda1"];
2239        ["is_dir"; "/boot"]])],
2240    "install GRUB",
2241    "\
2242 This command installs GRUB (the Grand Unified Bootloader) on
2243 C<device>, with the root directory being C<root>.");
2244
2245   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2246    [InitBasicFS, Always, TestOutput (
2247       [["write_file"; "/old"; "file content"; "0"];
2248        ["cp"; "/old"; "/new"];
2249        ["cat"; "/new"]], "file content");
2250     InitBasicFS, Always, TestOutputTrue (
2251       [["write_file"; "/old"; "file content"; "0"];
2252        ["cp"; "/old"; "/new"];
2253        ["is_file"; "/old"]]);
2254     InitBasicFS, Always, TestOutput (
2255       [["write_file"; "/old"; "file content"; "0"];
2256        ["mkdir"; "/dir"];
2257        ["cp"; "/old"; "/dir/new"];
2258        ["cat"; "/dir/new"]], "file content")],
2259    "copy a file",
2260    "\
2261 This copies a file from C<src> to C<dest> where C<dest> is
2262 either a destination filename or destination directory.");
2263
2264   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2265    [InitBasicFS, Always, TestOutput (
2266       [["mkdir"; "/olddir"];
2267        ["mkdir"; "/newdir"];
2268        ["write_file"; "/olddir/file"; "file content"; "0"];
2269        ["cp_a"; "/olddir"; "/newdir"];
2270        ["cat"; "/newdir/olddir/file"]], "file content")],
2271    "copy a file or directory recursively",
2272    "\
2273 This copies a file or directory from C<src> to C<dest>
2274 recursively using the C<cp -a> command.");
2275
2276   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2277    [InitBasicFS, Always, TestOutput (
2278       [["write_file"; "/old"; "file content"; "0"];
2279        ["mv"; "/old"; "/new"];
2280        ["cat"; "/new"]], "file content");
2281     InitBasicFS, Always, TestOutputFalse (
2282       [["write_file"; "/old"; "file content"; "0"];
2283        ["mv"; "/old"; "/new"];
2284        ["is_file"; "/old"]])],
2285    "move a file",
2286    "\
2287 This moves a file from C<src> to C<dest> where C<dest> is
2288 either a destination filename or destination directory.");
2289
2290   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2291    [InitEmpty, Always, TestRun (
2292       [["drop_caches"; "3"]])],
2293    "drop kernel page cache, dentries and inodes",
2294    "\
2295 This instructs the guest kernel to drop its page cache,
2296 and/or dentries and inode caches.  The parameter C<whattodrop>
2297 tells the kernel what precisely to drop, see
2298 L<http://linux-mm.org/Drop_Caches>
2299
2300 Setting C<whattodrop> to 3 should drop everything.
2301
2302 This automatically calls L<sync(2)> before the operation,
2303 so that the maximum guest memory is freed.");
2304
2305   ("dmesg", (RString "kmsgs", []), 91, [],
2306    [InitEmpty, Always, TestRun (
2307       [["dmesg"]])],
2308    "return kernel messages",
2309    "\
2310 This returns the kernel messages (C<dmesg> output) from
2311 the guest kernel.  This is sometimes useful for extended
2312 debugging of problems.
2313
2314 Another way to get the same information is to enable
2315 verbose messages with C<guestfs_set_verbose> or by setting
2316 the environment variable C<LIBGUESTFS_DEBUG=1> before
2317 running the program.");
2318
2319   ("ping_daemon", (RErr, []), 92, [],
2320    [InitEmpty, Always, TestRun (
2321       [["ping_daemon"]])],
2322    "ping the guest daemon",
2323    "\
2324 This is a test probe into the guestfs daemon running inside
2325 the qemu subprocess.  Calling this function checks that the
2326 daemon responds to the ping message, without affecting the daemon
2327 or attached block device(s) in any other way.");
2328
2329   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2330    [InitBasicFS, Always, TestOutputTrue (
2331       [["write_file"; "/file1"; "contents of a file"; "0"];
2332        ["cp"; "/file1"; "/file2"];
2333        ["equal"; "/file1"; "/file2"]]);
2334     InitBasicFS, Always, TestOutputFalse (
2335       [["write_file"; "/file1"; "contents of a file"; "0"];
2336        ["write_file"; "/file2"; "contents of another file"; "0"];
2337        ["equal"; "/file1"; "/file2"]]);
2338     InitBasicFS, Always, TestLastFail (
2339       [["equal"; "/file1"; "/file2"]])],
2340    "test if two files have equal contents",
2341    "\
2342 This compares the two files C<file1> and C<file2> and returns
2343 true if their content is exactly equal, or false otherwise.
2344
2345 The external L<cmp(1)> program is used for the comparison.");
2346
2347   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2348    [InitISOFS, Always, TestOutputList (
2349       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2350     InitISOFS, Always, TestOutputList (
2351       [["strings"; "/empty"]], [])],
2352    "print the printable strings in a file",
2353    "\
2354 This runs the L<strings(1)> command on a file and returns
2355 the list of printable strings found.");
2356
2357   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2358    [InitISOFS, Always, TestOutputList (
2359       [["strings_e"; "b"; "/known-5"]], []);
2360     InitBasicFS, Disabled, TestOutputList (
2361       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2362        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2363    "print the printable strings in a file",
2364    "\
2365 This is like the C<guestfs_strings> command, but allows you to
2366 specify the encoding.
2367
2368 See the L<strings(1)> manpage for the full list of encodings.
2369
2370 Commonly useful encodings are C<l> (lower case L) which will
2371 show strings inside Windows/x86 files.
2372
2373 The returned strings are transcoded to UTF-8.");
2374
2375   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2376    [InitISOFS, Always, TestOutput (
2377       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2378     (* Test for RHBZ#501888c2 regression which caused large hexdump
2379      * commands to segfault.
2380      *)
2381     InitISOFS, Always, TestRun (
2382       [["hexdump"; "/100krandom"]])],
2383    "dump a file in hexadecimal",
2384    "\
2385 This runs C<hexdump -C> on the given C<path>.  The result is
2386 the human-readable, canonical hex dump of the file.");
2387
2388   ("zerofree", (RErr, [Device "device"]), 97, [],
2389    [InitNone, Always, TestOutput (
2390       [["part_disk"; "/dev/sda"; "mbr"];
2391        ["mkfs"; "ext3"; "/dev/sda1"];
2392        ["mount"; "/dev/sda1"; "/"];
2393        ["write_file"; "/new"; "test file"; "0"];
2394        ["umount"; "/dev/sda1"];
2395        ["zerofree"; "/dev/sda1"];
2396        ["mount"; "/dev/sda1"; "/"];
2397        ["cat"; "/new"]], "test file")],
2398    "zero unused inodes and disk blocks on ext2/3 filesystem",
2399    "\
2400 This runs the I<zerofree> program on C<device>.  This program
2401 claims to zero unused inodes and disk blocks on an ext2/3
2402 filesystem, thus making it possible to compress the filesystem
2403 more effectively.
2404
2405 You should B<not> run this program if the filesystem is
2406 mounted.
2407
2408 It is possible that using this program can damage the filesystem
2409 or data on the filesystem.");
2410
2411   ("pvresize", (RErr, [Device "device"]), 98, [],
2412    [],
2413    "resize an LVM physical volume",
2414    "\
2415 This resizes (expands or shrinks) an existing LVM physical
2416 volume to match the new size of the underlying device.");
2417
2418   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2419                        Int "cyls"; Int "heads"; Int "sectors";
2420                        String "line"]), 99, [DangerWillRobinson],
2421    [],
2422    "modify a single partition on a block device",
2423    "\
2424 This runs L<sfdisk(8)> option to modify just the single
2425 partition C<n> (note: C<n> counts from 1).
2426
2427 For other parameters, see C<guestfs_sfdisk>.  You should usually
2428 pass C<0> for the cyls/heads/sectors parameters.
2429
2430 See also: C<guestfs_part_add>");
2431
2432   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2433    [],
2434    "display the partition table",
2435    "\
2436 This displays the partition table on C<device>, in the
2437 human-readable output of the L<sfdisk(8)> command.  It is
2438 not intended to be parsed.
2439
2440 See also: C<guestfs_part_list>");
2441
2442   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2443    [],
2444    "display the kernel geometry",
2445    "\
2446 This displays the kernel's idea of the geometry of C<device>.
2447
2448 The result is in human-readable format, and not designed to
2449 be parsed.");
2450
2451   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2452    [],
2453    "display the disk geometry from the partition table",
2454    "\
2455 This displays the disk geometry of C<device> read from the
2456 partition table.  Especially in the case where the underlying
2457 block device has been resized, this can be different from the
2458 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2459
2460 The result is in human-readable format, and not designed to
2461 be parsed.");
2462
2463   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2464    [],
2465    "activate or deactivate all volume groups",
2466    "\
2467 This command activates or (if C<activate> is false) deactivates
2468 all logical volumes in all volume groups.
2469 If activated, then they are made known to the
2470 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2471 then those devices disappear.
2472
2473 This command is the same as running C<vgchange -a y|n>");
2474
2475   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2476    [],
2477    "activate or deactivate some volume groups",
2478    "\
2479 This command activates or (if C<activate> is false) deactivates
2480 all logical volumes in the listed volume groups C<volgroups>.
2481 If activated, then they are made known to the
2482 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2483 then those devices disappear.
2484
2485 This command is the same as running C<vgchange -a y|n volgroups...>
2486
2487 Note that if C<volgroups> is an empty list then B<all> volume groups
2488 are activated or deactivated.");
2489
2490   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2491    [InitNone, Always, TestOutput (
2492       [["part_disk"; "/dev/sda"; "mbr"];
2493        ["pvcreate"; "/dev/sda1"];
2494        ["vgcreate"; "VG"; "/dev/sda1"];
2495        ["lvcreate"; "LV"; "VG"; "10"];
2496        ["mkfs"; "ext2"; "/dev/VG/LV"];
2497        ["mount"; "/dev/VG/LV"; "/"];
2498        ["write_file"; "/new"; "test content"; "0"];
2499        ["umount"; "/"];
2500        ["lvresize"; "/dev/VG/LV"; "20"];
2501        ["e2fsck_f"; "/dev/VG/LV"];
2502        ["resize2fs"; "/dev/VG/LV"];
2503        ["mount"; "/dev/VG/LV"; "/"];
2504        ["cat"; "/new"]], "test content")],
2505    "resize an LVM logical volume",
2506    "\
2507 This resizes (expands or shrinks) an existing LVM logical
2508 volume to C<mbytes>.  When reducing, data in the reduced part
2509 is lost.");
2510
2511   ("resize2fs", (RErr, [Device "device"]), 106, [],
2512    [], (* lvresize tests this *)
2513    "resize an ext2/ext3 filesystem",
2514    "\
2515 This resizes an ext2 or ext3 filesystem to match the size of
2516 the underlying device.
2517
2518 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2519 on the C<device> before calling this command.  For unknown reasons
2520 C<resize2fs> sometimes gives an error about this and sometimes not.
2521 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2522 calling this function.");
2523
2524   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2525    [InitBasicFS, Always, TestOutputList (
2526       [["find"; "/"]], ["lost+found"]);
2527     InitBasicFS, Always, TestOutputList (
2528       [["touch"; "/a"];
2529        ["mkdir"; "/b"];
2530        ["touch"; "/b/c"];
2531        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2532     InitBasicFS, Always, TestOutputList (
2533       [["mkdir_p"; "/a/b/c"];
2534        ["touch"; "/a/b/c/d"];
2535        ["find"; "/a/b/"]], ["c"; "c/d"])],
2536    "find all files and directories",
2537    "\
2538 This command lists out all files and directories, recursively,
2539 starting at C<directory>.  It is essentially equivalent to
2540 running the shell command C<find directory -print> but some
2541 post-processing happens on the output, described below.
2542
2543 This returns a list of strings I<without any prefix>.  Thus
2544 if the directory structure was:
2545
2546  /tmp/a
2547  /tmp/b
2548  /tmp/c/d
2549
2550 then the returned list from C<guestfs_find> C</tmp> would be
2551 4 elements:
2552
2553  a
2554  b
2555  c
2556  c/d
2557
2558 If C<directory> is not a directory, then this command returns
2559 an error.
2560
2561 The returned list is sorted.
2562
2563 See also C<guestfs_find0>.");
2564
2565   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2566    [], (* lvresize tests this *)
2567    "check an ext2/ext3 filesystem",
2568    "\
2569 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2570 filesystem checker on C<device>, noninteractively (C<-p>),
2571 even if the filesystem appears to be clean (C<-f>).
2572
2573 This command is only needed because of C<guestfs_resize2fs>
2574 (q.v.).  Normally you should use C<guestfs_fsck>.");
2575
2576   ("sleep", (RErr, [Int "secs"]), 109, [],
2577    [InitNone, Always, TestRun (
2578       [["sleep"; "1"]])],
2579    "sleep for some seconds",
2580    "\
2581 Sleep for C<secs> seconds.");
2582
2583   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2584    [InitNone, Always, TestOutputInt (
2585       [["part_disk"; "/dev/sda"; "mbr"];
2586        ["mkfs"; "ntfs"; "/dev/sda1"];
2587        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2588     InitNone, Always, TestOutputInt (
2589       [["part_disk"; "/dev/sda"; "mbr"];
2590        ["mkfs"; "ext2"; "/dev/sda1"];
2591        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2592    "probe NTFS volume",
2593    "\
2594 This command runs the L<ntfs-3g.probe(8)> command which probes
2595 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2596 be mounted read-write, and some cannot be mounted at all).
2597
2598 C<rw> is a boolean flag.  Set it to true if you want to test
2599 if the volume can be mounted read-write.  Set it to false if
2600 you want to test if the volume can be mounted read-only.
2601
2602 The return value is an integer which C<0> if the operation
2603 would succeed, or some non-zero value documented in the
2604 L<ntfs-3g.probe(8)> manual page.");
2605
2606   ("sh", (RString "output", [String "command"]), 111, [],
2607    [], (* XXX needs tests *)
2608    "run a command via the shell",
2609    "\
2610 This call runs a command from the guest filesystem via the
2611 guest's C</bin/sh>.
2612
2613 This is like C<guestfs_command>, but passes the command to:
2614
2615  /bin/sh -c \"command\"
2616
2617 Depending on the guest's shell, this usually results in
2618 wildcards being expanded, shell expressions being interpolated
2619 and so on.
2620
2621 All the provisos about C<guestfs_command> apply to this call.");
2622
2623   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2624    [], (* XXX needs tests *)
2625    "run a command via the shell returning lines",
2626    "\
2627 This is the same as C<guestfs_sh>, but splits the result
2628 into a list of lines.
2629
2630 See also: C<guestfs_command_lines>");
2631
2632   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2633    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2634     * code in stubs.c, since all valid glob patterns must start with "/".
2635     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2636     *)
2637    [InitBasicFS, Always, TestOutputList (
2638       [["mkdir_p"; "/a/b/c"];
2639        ["touch"; "/a/b/c/d"];
2640        ["touch"; "/a/b/c/e"];
2641        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2642     InitBasicFS, Always, TestOutputList (
2643       [["mkdir_p"; "/a/b/c"];
2644        ["touch"; "/a/b/c/d"];
2645        ["touch"; "/a/b/c/e"];
2646        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["mkdir_p"; "/a/b/c"];
2649        ["touch"; "/a/b/c/d"];
2650        ["touch"; "/a/b/c/e"];
2651        ["glob_expand"; "/a/*/x/*"]], [])],
2652    "expand a wildcard path",
2653    "\
2654 This command searches for all the pathnames matching
2655 C<pattern> according to the wildcard expansion rules
2656 used by the shell.
2657
2658 If no paths match, then this returns an empty list
2659 (note: not an error).
2660
2661 It is just a wrapper around the C L<glob(3)> function
2662 with flags C<GLOB_MARK|GLOB_BRACE>.
2663 See that manual page for more details.");
2664
2665   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2666    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2667       [["scrub_device"; "/dev/sdc"]])],
2668    "scrub (securely wipe) a device",
2669    "\
2670 This command writes patterns over C<device> to make data retrieval
2671 more difficult.
2672
2673 It is an interface to the L<scrub(1)> program.  See that
2674 manual page for more details.");
2675
2676   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2677    [InitBasicFS, Always, TestRun (
2678       [["write_file"; "/file"; "content"; "0"];
2679        ["scrub_file"; "/file"]])],
2680    "scrub (securely wipe) a file",
2681    "\
2682 This command writes patterns over a file to make data retrieval
2683 more difficult.
2684
2685 The file is I<removed> after scrubbing.
2686
2687 It is an interface to the L<scrub(1)> program.  See that
2688 manual page for more details.");
2689
2690   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2691    [], (* XXX needs testing *)
2692    "scrub (securely wipe) free space",
2693    "\
2694 This command creates the directory C<dir> and then fills it
2695 with files until the filesystem is full, and scrubs the files
2696 as for C<guestfs_scrub_file>, and deletes them.
2697 The intention is to scrub any free space on the partition
2698 containing C<dir>.
2699
2700 It is an interface to the L<scrub(1)> program.  See that
2701 manual page for more details.");
2702
2703   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2704    [InitBasicFS, Always, TestRun (
2705       [["mkdir"; "/tmp"];
2706        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2707    "create a temporary directory",
2708    "\
2709 This command creates a temporary directory.  The
2710 C<template> parameter should be a full pathname for the
2711 temporary directory name with the final six characters being
2712 \"XXXXXX\".
2713
2714 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2715 the second one being suitable for Windows filesystems.
2716
2717 The name of the temporary directory that was created
2718 is returned.
2719
2720 The temporary directory is created with mode 0700
2721 and is owned by root.
2722
2723 The caller is responsible for deleting the temporary
2724 directory and its contents after use.
2725
2726 See also: L<mkdtemp(3)>");
2727
2728   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2729    [InitISOFS, Always, TestOutputInt (
2730       [["wc_l"; "/10klines"]], 10000)],
2731    "count lines in a file",
2732    "\
2733 This command counts the lines in a file, using the
2734 C<wc -l> external command.");
2735
2736   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2737    [InitISOFS, Always, TestOutputInt (
2738       [["wc_w"; "/10klines"]], 10000)],
2739    "count words in a file",
2740    "\
2741 This command counts the words in a file, using the
2742 C<wc -w> external command.");
2743
2744   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2745    [InitISOFS, Always, TestOutputInt (
2746       [["wc_c"; "/100kallspaces"]], 102400)],
2747    "count characters in a file",
2748    "\
2749 This command counts the characters in a file, using the
2750 C<wc -c> external command.");
2751
2752   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2753    [InitISOFS, Always, TestOutputList (
2754       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2755    "return first 10 lines of a file",
2756    "\
2757 This command returns up to the first 10 lines of a file as
2758 a list of strings.");
2759
2760   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2761    [InitISOFS, Always, TestOutputList (
2762       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2763     InitISOFS, Always, TestOutputList (
2764       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2765     InitISOFS, Always, TestOutputList (
2766       [["head_n"; "0"; "/10klines"]], [])],
2767    "return first N lines of a file",
2768    "\
2769 If the parameter C<nrlines> is a positive number, this returns the first
2770 C<nrlines> lines of the file C<path>.
2771
2772 If the parameter C<nrlines> is a negative number, this returns lines
2773 from the file C<path>, excluding the last C<nrlines> lines.
2774
2775 If the parameter C<nrlines> is zero, this returns an empty list.");
2776
2777   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2778    [InitISOFS, Always, TestOutputList (
2779       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2780    "return last 10 lines of a file",
2781    "\
2782 This command returns up to the last 10 lines of a file as
2783 a list of strings.");
2784
2785   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2786    [InitISOFS, Always, TestOutputList (
2787       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2788     InitISOFS, Always, TestOutputList (
2789       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2790     InitISOFS, Always, TestOutputList (
2791       [["tail_n"; "0"; "/10klines"]], [])],
2792    "return last N lines of a file",
2793    "\
2794 If the parameter C<nrlines> is a positive number, this returns the last
2795 C<nrlines> lines of the file C<path>.
2796
2797 If the parameter C<nrlines> is a negative number, this returns lines
2798 from the file C<path>, starting with the C<-nrlines>th line.
2799
2800 If the parameter C<nrlines> is zero, this returns an empty list.");
2801
2802   ("df", (RString "output", []), 125, [],
2803    [], (* XXX Tricky to test because it depends on the exact format
2804         * of the 'df' command and other imponderables.
2805         *)
2806    "report file system disk space usage",
2807    "\
2808 This command runs the C<df> command to report disk space used.
2809
2810 This command is mostly useful for interactive sessions.  It
2811 is I<not> intended that you try to parse the output string.
2812 Use C<statvfs> from programs.");
2813
2814   ("df_h", (RString "output", []), 126, [],
2815    [], (* XXX Tricky to test because it depends on the exact format
2816         * of the 'df' command and other imponderables.
2817         *)
2818    "report file system disk space usage (human readable)",
2819    "\
2820 This command runs the C<df -h> command to report disk space used
2821 in human-readable format.
2822
2823 This command is mostly useful for interactive sessions.  It
2824 is I<not> intended that you try to parse the output string.
2825 Use C<statvfs> from programs.");
2826
2827   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2828    [InitISOFS, Always, TestOutputInt (
2829       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2830    "estimate file space usage",
2831    "\
2832 This command runs the C<du -s> command to estimate file space
2833 usage for C<path>.
2834
2835 C<path> can be a file or a directory.  If C<path> is a directory
2836 then the estimate includes the contents of the directory and all
2837 subdirectories (recursively).
2838
2839 The result is the estimated size in I<kilobytes>
2840 (ie. units of 1024 bytes).");
2841
2842   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2843    [InitISOFS, Always, TestOutputList (
2844       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2845    "list files in an initrd",
2846    "\
2847 This command lists out files contained in an initrd.
2848
2849 The files are listed without any initial C</> character.  The
2850 files are listed in the order they appear (not necessarily
2851 alphabetical).  Directory names are listed as separate items.
2852
2853 Old Linux kernels (2.4 and earlier) used a compressed ext2
2854 filesystem as initrd.  We I<only> support the newer initramfs
2855 format (compressed cpio files).");
2856
2857   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2858    [],
2859    "mount a file using the loop device",
2860    "\
2861 This command lets you mount C<file> (a filesystem image
2862 in a file) on a mount point.  It is entirely equivalent to
2863 the command C<mount -o loop file mountpoint>.");
2864
2865   ("mkswap", (RErr, [Device "device"]), 130, [],
2866    [InitEmpty, Always, TestRun (
2867       [["part_disk"; "/dev/sda"; "mbr"];
2868        ["mkswap"; "/dev/sda1"]])],
2869    "create a swap partition",
2870    "\
2871 Create a swap partition on C<device>.");
2872
2873   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2874    [InitEmpty, Always, TestRun (
2875       [["part_disk"; "/dev/sda"; "mbr"];
2876        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2877    "create a swap partition with a label",
2878    "\
2879 Create a swap partition on C<device> with label C<label>.
2880
2881 Note that you cannot attach a swap label to a block device
2882 (eg. C</dev/sda>), just to a partition.  This appears to be
2883 a limitation of the kernel or swap tools.");
2884
2885   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2886    (let uuid = uuidgen () in
2887     [InitEmpty, Always, TestRun (
2888        [["part_disk"; "/dev/sda"; "mbr"];
2889         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2890    "create a swap partition with an explicit UUID",
2891    "\
2892 Create a swap partition on C<device> with UUID C<uuid>.");
2893
2894   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2895    [InitBasicFS, Always, TestOutputStruct (
2896       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2897        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2898        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2899     InitBasicFS, Always, TestOutputStruct (
2900       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2901        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2902    "make block, character or FIFO devices",
2903    "\
2904 This call creates block or character special devices, or
2905 named pipes (FIFOs).
2906
2907 The C<mode> parameter should be the mode, using the standard
2908 constants.  C<devmajor> and C<devminor> are the
2909 device major and minor numbers, only used when creating block
2910 and character special devices.");
2911
2912   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2913    [InitBasicFS, Always, TestOutputStruct (
2914       [["mkfifo"; "0o777"; "/node"];
2915        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2916    "make FIFO (named pipe)",
2917    "\
2918 This call creates a FIFO (named pipe) called C<path> with
2919 mode C<mode>.  It is just a convenient wrapper around
2920 C<guestfs_mknod>.");
2921
2922   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2923    [InitBasicFS, Always, TestOutputStruct (
2924       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2925        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2926    "make block device node",
2927    "\
2928 This call creates a block device node called C<path> with
2929 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2930 It is just a convenient wrapper around C<guestfs_mknod>.");
2931
2932   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2933    [InitBasicFS, Always, TestOutputStruct (
2934       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2935        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2936    "make char device node",
2937    "\
2938 This call creates a char device node called C<path> with
2939 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2940 It is just a convenient wrapper around C<guestfs_mknod>.");
2941
2942   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2943    [], (* XXX umask is one of those stateful things that we should
2944         * reset between each test.
2945         *)
2946    "set file mode creation mask (umask)",
2947    "\
2948 This function sets the mask used for creating new files and
2949 device nodes to C<mask & 0777>.
2950
2951 Typical umask values would be C<022> which creates new files
2952 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2953 C<002> which creates new files with permissions like
2954 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2955
2956 The default umask is C<022>.  This is important because it
2957 means that directories and device nodes will be created with
2958 C<0644> or C<0755> mode even if you specify C<0777>.
2959
2960 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2961
2962 This call returns the previous umask.");
2963
2964   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2965    [],
2966    "read directories entries",
2967    "\
2968 This returns the list of directory entries in directory C<dir>.
2969
2970 All entries in the directory are returned, including C<.> and
2971 C<..>.  The entries are I<not> sorted, but returned in the same
2972 order as the underlying filesystem.
2973
2974 Also this call returns basic file type information about each
2975 file.  The C<ftyp> field will contain one of the following characters:
2976
2977 =over 4
2978
2979 =item 'b'
2980
2981 Block special
2982
2983 =item 'c'
2984
2985 Char special
2986
2987 =item 'd'
2988
2989 Directory
2990
2991 =item 'f'
2992
2993 FIFO (named pipe)
2994
2995 =item 'l'
2996
2997 Symbolic link
2998
2999 =item 'r'
3000
3001 Regular file
3002
3003 =item 's'
3004
3005 Socket
3006
3007 =item 'u'
3008
3009 Unknown file type
3010
3011 =item '?'
3012
3013 The L<readdir(3)> returned a C<d_type> field with an
3014 unexpected value
3015
3016 =back
3017
3018 This function is primarily intended for use by programs.  To
3019 get a simple list of names, use C<guestfs_ls>.  To get a printable
3020 directory for human consumption, use C<guestfs_ll>.");
3021
3022   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3023    [],
3024    "create partitions on a block device",
3025    "\
3026 This is a simplified interface to the C<guestfs_sfdisk>
3027 command, where partition sizes are specified in megabytes
3028 only (rounded to the nearest cylinder) and you don't need
3029 to specify the cyls, heads and sectors parameters which
3030 were rarely if ever used anyway.
3031
3032 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3033 and C<guestfs_part_disk>");
3034
3035   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3036    [],
3037    "determine file type inside a compressed file",
3038    "\
3039 This command runs C<file> after first decompressing C<path>
3040 using C<method>.
3041
3042 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3043
3044 Since 1.0.63, use C<guestfs_file> instead which can now
3045 process compressed files.");
3046
3047   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3048    [],
3049    "list extended attributes of a file or directory",
3050    "\
3051 This call lists the extended attributes of the file or directory
3052 C<path>.
3053
3054 At the system call level, this is a combination of the
3055 L<listxattr(2)> and L<getxattr(2)> calls.
3056
3057 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3058
3059   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3060    [],
3061    "list extended attributes of a file or directory",
3062    "\
3063 This is the same as C<guestfs_getxattrs>, but if C<path>
3064 is a symbolic link, then it returns the extended attributes
3065 of the link itself.");
3066
3067   ("setxattr", (RErr, [String "xattr";
3068                        String "val"; Int "vallen"; (* will be BufferIn *)
3069                        Pathname "path"]), 143, [],
3070    [],
3071    "set extended attribute of a file or directory",
3072    "\
3073 This call sets the extended attribute named C<xattr>
3074 of the file C<path> to the value C<val> (of length C<vallen>).
3075 The value is arbitrary 8 bit data.
3076
3077 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3078
3079   ("lsetxattr", (RErr, [String "xattr";
3080                         String "val"; Int "vallen"; (* will be BufferIn *)
3081                         Pathname "path"]), 144, [],
3082    [],
3083    "set extended attribute of a file or directory",
3084    "\
3085 This is the same as C<guestfs_setxattr>, but if C<path>
3086 is a symbolic link, then it sets an extended attribute
3087 of the link itself.");
3088
3089   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3090    [],
3091    "remove extended attribute of a file or directory",
3092    "\
3093 This call removes the extended attribute named C<xattr>
3094 of the file C<path>.
3095
3096 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3097
3098   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3099    [],
3100    "remove extended attribute of a file or directory",
3101    "\
3102 This is the same as C<guestfs_removexattr>, but if C<path>
3103 is a symbolic link, then it removes an extended attribute
3104 of the link itself.");
3105
3106   ("mountpoints", (RHashtable "mps", []), 147, [],
3107    [],
3108    "show mountpoints",
3109    "\
3110 This call is similar to C<guestfs_mounts>.  That call returns
3111 a list of devices.  This one returns a hash table (map) of
3112 device name to directory where the device is mounted.");
3113
3114   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3115   (* This is a special case: while you would expect a parameter
3116    * of type "Pathname", that doesn't work, because it implies
3117    * NEED_ROOT in the generated calling code in stubs.c, and
3118    * this function cannot use NEED_ROOT.
3119    *)
3120    [],
3121    "create a mountpoint",
3122    "\
3123 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3124 specialized calls that can be used to create extra mountpoints
3125 before mounting the first filesystem.
3126
3127 These calls are I<only> necessary in some very limited circumstances,
3128 mainly the case where you want to mount a mix of unrelated and/or
3129 read-only filesystems together.
3130
3131 For example, live CDs often contain a \"Russian doll\" nest of
3132 filesystems, an ISO outer layer, with a squashfs image inside, with
3133 an ext2/3 image inside that.  You can unpack this as follows
3134 in guestfish:
3135
3136  add-ro Fedora-11-i686-Live.iso
3137  run
3138  mkmountpoint /cd
3139  mkmountpoint /squash
3140  mkmountpoint /ext3
3141  mount /dev/sda /cd
3142  mount-loop /cd/LiveOS/squashfs.img /squash
3143  mount-loop /squash/LiveOS/ext3fs.img /ext3
3144
3145 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3146
3147   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3148    [],
3149    "remove a mountpoint",
3150    "\
3151 This calls removes a mountpoint that was previously created
3152 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3153 for full details.");
3154
3155   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3156    [InitISOFS, Always, TestOutputBuffer (
3157       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3158    "read a file",
3159    "\
3160 This calls returns the contents of the file C<path> as a
3161 buffer.
3162
3163 Unlike C<guestfs_cat>, this function can correctly
3164 handle files that contain embedded ASCII NUL characters.
3165 However unlike C<guestfs_download>, this function is limited
3166 in the total size of file that can be handled.");
3167
3168   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3169    [InitISOFS, Always, TestOutputList (
3170       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3171     InitISOFS, Always, TestOutputList (
3172       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3173    "return lines matching a pattern",
3174    "\
3175 This calls the external C<grep> program and returns the
3176 matching lines.");
3177
3178   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3179    [InitISOFS, Always, TestOutputList (
3180       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3181    "return lines matching a pattern",
3182    "\
3183 This calls the external C<egrep> program and returns the
3184 matching lines.");
3185
3186   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3187    [InitISOFS, Always, TestOutputList (
3188       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3189    "return lines matching a pattern",
3190    "\
3191 This calls the external C<fgrep> program and returns the
3192 matching lines.");
3193
3194   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3195    [InitISOFS, Always, TestOutputList (
3196       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3197    "return lines matching a pattern",
3198    "\
3199 This calls the external C<grep -i> program and returns the
3200 matching lines.");
3201
3202   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3203    [InitISOFS, Always, TestOutputList (
3204       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3205    "return lines matching a pattern",
3206    "\
3207 This calls the external C<egrep -i> program and returns the
3208 matching lines.");
3209
3210   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3211    [InitISOFS, Always, TestOutputList (
3212       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3213    "return lines matching a pattern",
3214    "\
3215 This calls the external C<fgrep -i> program and returns the
3216 matching lines.");
3217
3218   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3219    [InitISOFS, Always, TestOutputList (
3220       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3221    "return lines matching a pattern",
3222    "\
3223 This calls the external C<zgrep> program and returns the
3224 matching lines.");
3225
3226   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3227    [InitISOFS, Always, TestOutputList (
3228       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3229    "return lines matching a pattern",
3230    "\
3231 This calls the external C<zegrep> program and returns the
3232 matching lines.");
3233
3234   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3235    [InitISOFS, Always, TestOutputList (
3236       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3237    "return lines matching a pattern",
3238    "\
3239 This calls the external C<zfgrep> program and returns the
3240 matching lines.");
3241
3242   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3243    [InitISOFS, Always, TestOutputList (
3244       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3245    "return lines matching a pattern",
3246    "\
3247 This calls the external C<zgrep -i> program and returns the
3248 matching lines.");
3249
3250   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3251    [InitISOFS, Always, TestOutputList (
3252       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3253    "return lines matching a pattern",
3254    "\
3255 This calls the external C<zegrep -i> program and returns the
3256 matching lines.");
3257
3258   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3259    [InitISOFS, Always, TestOutputList (
3260       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3261    "return lines matching a pattern",
3262    "\
3263 This calls the external C<zfgrep -i> program and returns the
3264 matching lines.");
3265
3266   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3267    [InitISOFS, Always, TestOutput (
3268       [["realpath"; "/../directory"]], "/directory")],
3269    "canonicalized absolute pathname",
3270    "\
3271 Return the canonicalized absolute pathname of C<path>.  The
3272 returned path has no C<.>, C<..> or symbolic link path elements.");
3273
3274   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3275    [InitBasicFS, Always, TestOutputStruct (
3276       [["touch"; "/a"];
3277        ["ln"; "/a"; "/b"];
3278        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3279    "create a hard link",
3280    "\
3281 This command creates a hard link using the C<ln> command.");
3282
3283   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3284    [InitBasicFS, Always, TestOutputStruct (
3285       [["touch"; "/a"];
3286        ["touch"; "/b"];
3287        ["ln_f"; "/a"; "/b"];
3288        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3289    "create a hard link",
3290    "\
3291 This command creates a hard link using the C<ln -f> command.
3292 The C<-f> option removes the link (C<linkname>) if it exists already.");
3293
3294   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3295    [InitBasicFS, Always, TestOutputStruct (
3296       [["touch"; "/a"];
3297        ["ln_s"; "a"; "/b"];
3298        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3299    "create a symbolic link",
3300    "\
3301 This command creates a symbolic link using the C<ln -s> command.");
3302
3303   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3304    [InitBasicFS, Always, TestOutput (
3305       [["mkdir_p"; "/a/b"];
3306        ["touch"; "/a/b/c"];
3307        ["ln_sf"; "../d"; "/a/b/c"];
3308        ["readlink"; "/a/b/c"]], "../d")],
3309    "create a symbolic link",
3310    "\
3311 This command creates a symbolic link using the C<ln -sf> command,
3312 The C<-f> option removes the link (C<linkname>) if it exists already.");
3313
3314   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3315    [] (* XXX tested above *),
3316    "read the target of a symbolic link",
3317    "\
3318 This command reads the target of a symbolic link.");
3319
3320   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3321    [InitBasicFS, Always, TestOutputStruct (
3322       [["fallocate"; "/a"; "1000000"];
3323        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3324    "preallocate a file in the guest filesystem",
3325    "\
3326 This command preallocates a file (containing zero bytes) named
3327 C<path> of size C<len> bytes.  If the file exists already, it
3328 is overwritten.
3329
3330 Do not confuse this with the guestfish-specific
3331 C<alloc> command which allocates a file in the host and
3332 attaches it as a device.");
3333
3334   ("swapon_device", (RErr, [Device "device"]), 170, [],
3335    [InitPartition, Always, TestRun (
3336       [["mkswap"; "/dev/sda1"];
3337        ["swapon_device"; "/dev/sda1"];
3338        ["swapoff_device"; "/dev/sda1"]])],
3339    "enable swap on device",
3340    "\
3341 This command enables the libguestfs appliance to use the
3342 swap device or partition named C<device>.  The increased
3343 memory is made available for all commands, for example
3344 those run using C<guestfs_command> or C<guestfs_sh>.
3345
3346 Note that you should not swap to existing guest swap
3347 partitions unless you know what you are doing.  They may
3348 contain hibernation information, or other information that
3349 the guest doesn't want you to trash.  You also risk leaking
3350 information about the host to the guest this way.  Instead,
3351 attach a new host device to the guest and swap on that.");
3352
3353   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3354    [], (* XXX tested by swapon_device *)
3355    "disable swap on device",
3356    "\
3357 This command disables the libguestfs appliance swap
3358 device or partition named C<device>.
3359 See C<guestfs_swapon_device>.");
3360
3361   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3362    [InitBasicFS, Always, TestRun (
3363       [["fallocate"; "/swap"; "8388608"];
3364        ["mkswap_file"; "/swap"];
3365        ["swapon_file"; "/swap"];
3366        ["swapoff_file"; "/swap"]])],
3367    "enable swap on file",
3368    "\
3369 This command enables swap to a file.
3370 See C<guestfs_swapon_device> for other notes.");
3371
3372   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3373    [], (* XXX tested by swapon_file *)
3374    "disable swap on file",
3375    "\
3376 This command disables the libguestfs appliance swap on file.");
3377
3378   ("swapon_label", (RErr, [String "label"]), 174, [],
3379    [InitEmpty, Always, TestRun (
3380       [["part_disk"; "/dev/sdb"; "mbr"];
3381        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3382        ["swapon_label"; "swapit"];
3383        ["swapoff_label"; "swapit"];
3384        ["zero"; "/dev/sdb"];
3385        ["blockdev_rereadpt"; "/dev/sdb"]])],
3386    "enable swap on labeled swap partition",
3387    "\
3388 This command enables swap to a labeled swap partition.
3389 See C<guestfs_swapon_device> for other notes.");
3390
3391   ("swapoff_label", (RErr, [String "label"]), 175, [],
3392    [], (* XXX tested by swapon_label *)
3393    "disable swap on labeled swap partition",
3394    "\
3395 This command disables the libguestfs appliance swap on
3396 labeled swap partition.");
3397
3398   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3399    (let uuid = uuidgen () in
3400     [InitEmpty, Always, TestRun (
3401        [["mkswap_U"; uuid; "/dev/sdb"];
3402         ["swapon_uuid"; uuid];
3403         ["swapoff_uuid"; uuid]])]),
3404    "enable swap on swap partition by UUID",
3405    "\
3406 This command enables swap to a swap partition with the given UUID.
3407 See C<guestfs_swapon_device> for other notes.");
3408
3409   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3410    [], (* XXX tested by swapon_uuid *)
3411    "disable swap on swap partition by UUID",
3412    "\
3413 This command disables the libguestfs appliance swap partition
3414 with the given UUID.");
3415
3416   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3417    [InitBasicFS, Always, TestRun (
3418       [["fallocate"; "/swap"; "8388608"];
3419        ["mkswap_file"; "/swap"]])],
3420    "create a swap file",
3421    "\
3422 Create a swap file.
3423
3424 This command just writes a swap file signature to an existing
3425 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3426
3427   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3428    [InitISOFS, Always, TestRun (
3429       [["inotify_init"; "0"]])],
3430    "create an inotify handle",
3431    "\
3432 This command creates a new inotify handle.
3433 The inotify subsystem can be used to notify events which happen to
3434 objects in the guest filesystem.
3435
3436 C<maxevents> is the maximum number of events which will be
3437 queued up between calls to C<guestfs_inotify_read> or
3438 C<guestfs_inotify_files>.
3439 If this is passed as C<0>, then the kernel (or previously set)
3440 default is used.  For Linux 2.6.29 the default was 16384 events.
3441 Beyond this limit, the kernel throws away events, but records
3442 the fact that it threw them away by setting a flag
3443 C<IN_Q_OVERFLOW> in the returned structure list (see
3444 C<guestfs_inotify_read>).
3445
3446 Before any events are generated, you have to add some
3447 watches to the internal watch list.  See:
3448 C<guestfs_inotify_add_watch>,
3449 C<guestfs_inotify_rm_watch> and
3450 C<guestfs_inotify_watch_all>.
3451
3452 Queued up events should be read periodically by calling
3453 C<guestfs_inotify_read>
3454 (or C<guestfs_inotify_files> which is just a helpful
3455 wrapper around C<guestfs_inotify_read>).  If you don't
3456 read the events out often enough then you risk the internal
3457 queue overflowing.
3458
3459 The handle should be closed after use by calling
3460 C<guestfs_inotify_close>.  This also removes any
3461 watches automatically.
3462
3463 See also L<inotify(7)> for an overview of the inotify interface
3464 as exposed by the Linux kernel, which is roughly what we expose
3465 via libguestfs.  Note that there is one global inotify handle
3466 per libguestfs instance.");
3467
3468   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3469    [InitBasicFS, Always, TestOutputList (
3470       [["inotify_init"; "0"];
3471        ["inotify_add_watch"; "/"; "1073741823"];
3472        ["touch"; "/a"];
3473        ["touch"; "/b"];
3474        ["inotify_files"]], ["a"; "b"])],
3475    "add an inotify watch",
3476    "\
3477 Watch C<path> for the events listed in C<mask>.
3478
3479 Note that if C<path> is a directory then events within that
3480 directory are watched, but this does I<not> happen recursively
3481 (in subdirectories).
3482
3483 Note for non-C or non-Linux callers: the inotify events are
3484 defined by the Linux kernel ABI and are listed in
3485 C</usr/include/sys/inotify.h>.");
3486
3487   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3488    [],
3489    "remove an inotify watch",
3490    "\
3491 Remove a previously defined inotify watch.
3492 See C<guestfs_inotify_add_watch>.");
3493
3494   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3495    [],
3496    "return list of inotify events",
3497    "\
3498 Return the complete queue of events that have happened
3499 since the previous read call.
3500
3501 If no events have happened, this returns an empty list.
3502
3503 I<Note>: In order to make sure that all events have been
3504 read, you must call this function repeatedly until it
3505 returns an empty list.  The reason is that the call will
3506 read events up to the maximum appliance-to-host message
3507 size and leave remaining events in the queue.");
3508
3509   ("inotify_files", (RStringList "paths", []), 183, [],
3510    [],
3511    "return list of watched files that had events",
3512    "\
3513 This function is a helpful wrapper around C<guestfs_inotify_read>
3514 which just returns a list of pathnames of objects that were
3515 touched.  The returned pathnames are sorted and deduplicated.");
3516
3517   ("inotify_close", (RErr, []), 184, [],
3518    [],
3519    "close the inotify handle",
3520    "\
3521 This closes the inotify handle which was previously
3522 opened by inotify_init.  It removes all watches, throws
3523 away any pending events, and deallocates all resources.");
3524
3525   ("setcon", (RErr, [String "context"]), 185, [],
3526    [],
3527    "set SELinux security context",
3528    "\
3529 This sets the SELinux security context of the daemon
3530 to the string C<context>.
3531
3532 See the documentation about SELINUX in L<guestfs(3)>.");
3533
3534   ("getcon", (RString "context", []), 186, [],
3535    [],
3536    "get SELinux security context",
3537    "\
3538 This gets the SELinux security context of the daemon.
3539
3540 See the documentation about SELINUX in L<guestfs(3)>,
3541 and C<guestfs_setcon>");
3542
3543   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3544    [InitEmpty, Always, TestOutput (
3545       [["part_disk"; "/dev/sda"; "mbr"];
3546        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3547        ["mount"; "/dev/sda1"; "/"];
3548        ["write_file"; "/new"; "new file contents"; "0"];
3549        ["cat"; "/new"]], "new file contents")],
3550    "make a filesystem with block size",
3551    "\
3552 This call is similar to C<guestfs_mkfs>, but it allows you to
3553 control the block size of the resulting filesystem.  Supported
3554 block sizes depend on the filesystem type, but typically they
3555 are C<1024>, C<2048> or C<4096> only.");
3556
3557   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3558    [InitEmpty, Always, TestOutput (
3559       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3560        ["mke2journal"; "4096"; "/dev/sda1"];
3561        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3562        ["mount"; "/dev/sda2"; "/"];
3563        ["write_file"; "/new"; "new file contents"; "0"];
3564        ["cat"; "/new"]], "new file contents")],
3565    "make ext2/3/4 external journal",
3566    "\
3567 This creates an ext2 external journal on C<device>.  It is equivalent
3568 to the command:
3569
3570  mke2fs -O journal_dev -b blocksize device");
3571
3572   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3573    [InitEmpty, Always, TestOutput (
3574       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3575        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3576        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3577        ["mount"; "/dev/sda2"; "/"];
3578        ["write_file"; "/new"; "new file contents"; "0"];
3579        ["cat"; "/new"]], "new file contents")],
3580    "make ext2/3/4 external journal with label",
3581    "\
3582 This creates an ext2 external journal on C<device> with label C<label>.");
3583
3584   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3585    (let uuid = uuidgen () in
3586     [InitEmpty, Always, TestOutput (
3587        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3588         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3589         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3590         ["mount"; "/dev/sda2"; "/"];
3591         ["write_file"; "/new"; "new file contents"; "0"];
3592         ["cat"; "/new"]], "new file contents")]),
3593    "make ext2/3/4 external journal with UUID",
3594    "\
3595 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3596
3597   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3598    [],
3599    "make ext2/3/4 filesystem with external journal",
3600    "\
3601 This creates an ext2/3/4 filesystem on C<device> with
3602 an external journal on C<journal>.  It is equivalent
3603 to the command:
3604
3605  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3606
3607 See also C<guestfs_mke2journal>.");
3608
3609   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3610    [],
3611    "make ext2/3/4 filesystem with external journal",
3612    "\
3613 This creates an ext2/3/4 filesystem on C<device> with
3614 an external journal on the journal labeled C<label>.
3615
3616 See also C<guestfs_mke2journal_L>.");
3617
3618   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3619    [],
3620    "make ext2/3/4 filesystem with external journal",
3621    "\
3622 This creates an ext2/3/4 filesystem on C<device> with
3623 an external journal on the journal with UUID C<uuid>.
3624
3625 See also C<guestfs_mke2journal_U>.");
3626
3627   ("modprobe", (RErr, [String "modulename"]), 194, [],
3628    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3629    "load a kernel module",
3630    "\
3631 This loads a kernel module in the appliance.
3632
3633 The kernel module must have been whitelisted when libguestfs
3634 was built (see C<appliance/kmod.whitelist.in> in the source).");
3635
3636   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3637    [InitNone, Always, TestOutput (
3638      [["echo_daemon"; "This is a test"]], "This is a test"
3639    )],
3640    "echo arguments back to the client",
3641    "\
3642 This command concatenate the list of C<words> passed with single spaces between
3643 them and returns the resulting string.
3644
3645 You can use this command to test the connection through to the daemon.
3646
3647 See also C<guestfs_ping_daemon>.");
3648
3649   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3650    [], (* There is a regression test for this. *)
3651    "find all files and directories, returning NUL-separated list",
3652    "\
3653 This command lists out all files and directories, recursively,
3654 starting at C<directory>, placing the resulting list in the
3655 external file called C<files>.
3656
3657 This command works the same way as C<guestfs_find> with the
3658 following exceptions:
3659
3660 =over 4
3661
3662 =item *
3663
3664 The resulting list is written to an external file.
3665
3666 =item *
3667
3668 Items (filenames) in the result are separated
3669 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3670
3671 =item *
3672
3673 This command is not limited in the number of names that it
3674 can return.
3675
3676 =item *
3677
3678 The result list is not sorted.
3679
3680 =back");
3681
3682   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3683    [InitISOFS, Always, TestOutput (
3684       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3685     InitISOFS, Always, TestOutput (
3686       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3687     InitISOFS, Always, TestOutput (
3688       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3689     InitISOFS, Always, TestLastFail (
3690       [["case_sensitive_path"; "/Known-1/"]]);
3691     InitBasicFS, Always, TestOutput (
3692       [["mkdir"; "/a"];
3693        ["mkdir"; "/a/bbb"];
3694        ["touch"; "/a/bbb/c"];
3695        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3696     InitBasicFS, Always, TestOutput (
3697       [["mkdir"; "/a"];
3698        ["mkdir"; "/a/bbb"];
3699        ["touch"; "/a/bbb/c"];
3700        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3701     InitBasicFS, Always, TestLastFail (
3702       [["mkdir"; "/a"];
3703        ["mkdir"; "/a/bbb"];
3704        ["touch"; "/a/bbb/c"];
3705        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3706    "return true path on case-insensitive filesystem",
3707    "\
3708 This can be used to resolve case insensitive paths on
3709 a filesystem which is case sensitive.  The use case is
3710 to resolve paths which you have read from Windows configuration
3711 files or the Windows Registry, to the true path.
3712
3713 The command handles a peculiarity of the Linux ntfs-3g
3714 filesystem driver (and probably others), which is that although
3715 the underlying filesystem is case-insensitive, the driver
3716 exports the filesystem to Linux as case-sensitive.
3717
3718 One consequence of this is that special directories such
3719 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3720 (or other things) depending on the precise details of how
3721 they were created.  In Windows itself this would not be
3722 a problem.
3723
3724 Bug or feature?  You decide:
3725 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3726
3727 This function resolves the true case of each element in the
3728 path and returns the case-sensitive path.
3729
3730 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3731 might return C<\"/WINDOWS/system32\"> (the exact return value
3732 would depend on details of how the directories were originally
3733 created under Windows).
3734
3735 I<Note>:
3736 This function does not handle drive names, backslashes etc.
3737
3738 See also C<guestfs_realpath>.");
3739
3740   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3741    [InitBasicFS, Always, TestOutput (
3742       [["vfs_type"; "/dev/sda1"]], "ext2")],
3743    "get the Linux VFS type corresponding to a mounted device",
3744    "\
3745 This command gets the block device type corresponding to
3746 a mounted device called C<device>.
3747
3748 Usually the result is the name of the Linux VFS module that
3749 is used to mount this device (probably determined automatically
3750 if you used the C<guestfs_mount> call).");
3751
3752   ("truncate", (RErr, [Pathname "path"]), 199, [],
3753    [InitBasicFS, Always, TestOutputStruct (
3754       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3755        ["truncate"; "/test"];
3756        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3757    "truncate a file to zero size",
3758    "\
3759 This command truncates C<path> to a zero-length file.  The
3760 file must exist already.");
3761
3762   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3763    [InitBasicFS, Always, TestOutputStruct (
3764       [["touch"; "/test"];
3765        ["truncate_size"; "/test"; "1000"];
3766        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3767    "truncate a file to a particular size",
3768    "\
3769 This command truncates C<path> to size C<size> bytes.  The file
3770 must exist already.  If the file is smaller than C<size> then
3771 the file is extended to the required size with null bytes.");
3772
3773   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3774    [InitBasicFS, Always, TestOutputStruct (
3775       [["touch"; "/test"];
3776        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3777        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3778    "set timestamp of a file with nanosecond precision",
3779    "\
3780 This command sets the timestamps of a file with nanosecond
3781 precision.
3782
3783 C<atsecs, atnsecs> are the last access time (atime) in secs and
3784 nanoseconds from the epoch.
3785
3786 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3787 secs and nanoseconds from the epoch.
3788
3789 If the C<*nsecs> field contains the special value C<-1> then
3790 the corresponding timestamp is set to the current time.  (The
3791 C<*secs> field is ignored in this case).
3792
3793 If the C<*nsecs> field contains the special value C<-2> then
3794 the corresponding timestamp is left unchanged.  (The
3795 C<*secs> field is ignored in this case).");
3796
3797   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3798    [InitBasicFS, Always, TestOutputStruct (
3799       [["mkdir_mode"; "/test"; "0o111"];
3800        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3801    "create a directory with a particular mode",
3802    "\
3803 This command creates a directory, setting the initial permissions
3804 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3805
3806   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3807    [], (* XXX *)
3808    "change file owner and group",
3809    "\
3810 Change the file owner to C<owner> and group to C<group>.
3811 This is like C<guestfs_chown> but if C<path> is a symlink then
3812 the link itself is changed, not the target.
3813
3814 Only numeric uid and gid are supported.  If you want to use
3815 names, you will need to locate and parse the password file
3816 yourself (Augeas support makes this relatively easy).");
3817
3818   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3819    [], (* XXX *)
3820    "lstat on multiple files",
3821    "\
3822 This call allows you to perform the C<guestfs_lstat> operation
3823 on multiple files, where all files are in the directory C<path>.
3824 C<names> is the list of files from this directory.
3825
3826 On return you get a list of stat structs, with a one-to-one
3827 correspondence to the C<names> list.  If any name did not exist
3828 or could not be lstat'd, then the C<ino> field of that structure
3829 is set to C<-1>.
3830
3831 This call is intended for programs that want to efficiently
3832 list a directory contents without making many round-trips.
3833 See also C<guestfs_lxattrlist> for a similarly efficient call
3834 for getting extended attributes.  Very long directory listings
3835 might cause the protocol message size to be exceeded, causing
3836 this call to fail.  The caller must split up such requests
3837 into smaller groups of names.");
3838
3839   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
3840    [], (* XXX *)
3841    "lgetxattr on multiple files",
3842    "\
3843 This call allows you to get the extended attributes
3844 of multiple files, where all files are in the directory C<path>.
3845 C<names> is the list of files from this directory.
3846
3847 On return you get a flat list of xattr structs which must be
3848 interpreted sequentially.  The first xattr struct always has a zero-length
3849 C<attrname>.  C<attrval> in this struct is zero-length
3850 to indicate there was an error doing C<lgetxattr> for this
3851 file, I<or> is a C string which is a decimal number
3852 (the number of following attributes for this file, which could
3853 be C<\"0\">).  Then after the first xattr struct are the
3854 zero or more attributes for the first named file.
3855 This repeats for the second and subsequent files.
3856
3857 This call is intended for programs that want to efficiently
3858 list a directory contents without making many round-trips.
3859 See also C<guestfs_lstatlist> for a similarly efficient call
3860 for getting standard stats.  Very long directory listings
3861 might cause the protocol message size to be exceeded, causing
3862 this call to fail.  The caller must split up such requests
3863 into smaller groups of names.");
3864
3865   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3866    [], (* XXX *)
3867    "readlink on multiple files",
3868    "\
3869 This call allows you to do a C<readlink> operation
3870 on multiple files, where all files are in the directory C<path>.
3871 C<names> is the list of files from this directory.
3872
3873 On return you get a list of strings, with a one-to-one
3874 correspondence to the C<names> list.  Each string is the
3875 value of the symbol link.
3876
3877 If the C<readlink(2)> operation fails on any name, then
3878 the corresponding result string is the empty string C<\"\">.
3879 However the whole operation is completed even if there
3880 were C<readlink(2)> errors, and so you can call this
3881 function with names where you don't know if they are
3882 symbolic links already (albeit slightly less efficient).
3883
3884 This call is intended for programs that want to efficiently
3885 list a directory contents without making many round-trips.
3886 Very long directory listings might cause the protocol
3887 message size to be exceeded, causing
3888 this call to fail.  The caller must split up such requests
3889 into smaller groups of names.");
3890
3891   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3892    [InitISOFS, Always, TestOutputBuffer (
3893       [["pread"; "/known-4"; "1"; "3"]], "\n")],
3894    "read part of a file",
3895    "\
3896 This command lets you read part of a file.  It reads C<count>
3897 bytes of the file, starting at C<offset>, from file C<path>.
3898
3899 This may read fewer bytes than requested.  For further details
3900 see the L<pread(2)> system call.");
3901
3902   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3903    [InitEmpty, Always, TestRun (
3904       [["part_init"; "/dev/sda"; "gpt"]])],
3905    "create an empty partition table",
3906    "\
3907 This creates an empty partition table on C<device> of one of the
3908 partition types listed below.  Usually C<parttype> should be
3909 either C<msdos> or C<gpt> (for large disks).
3910
3911 Initially there are no partitions.  Following this, you should
3912 call C<guestfs_part_add> for each partition required.
3913
3914 Possible values for C<parttype> are:
3915
3916 =over 4
3917
3918 =item B<efi> | B<gpt>
3919
3920 Intel EFI / GPT partition table.
3921
3922 This is recommended for >= 2 TB partitions that will be accessed
3923 from Linux and Intel-based Mac OS X.  It also has limited backwards
3924 compatibility with the C<mbr> format.
3925
3926 =item B<mbr> | B<msdos>
3927
3928 The standard PC \"Master Boot Record\" (MBR) format used
3929 by MS-DOS and Windows.  This partition type will B<only> work
3930 for device sizes up to 2 TB.  For large disks we recommend
3931 using C<gpt>.
3932
3933 =back
3934
3935 Other partition table types that may work but are not
3936 supported include:
3937
3938 =over 4
3939
3940 =item B<aix>
3941
3942 AIX disk labels.
3943
3944 =item B<amiga> | B<rdb>
3945
3946 Amiga \"Rigid Disk Block\" format.
3947
3948 =item B<bsd>
3949
3950 BSD disk labels.
3951
3952 =item B<dasd>
3953
3954 DASD, used on IBM mainframes.
3955
3956 =item B<dvh>
3957
3958 MIPS/SGI volumes.
3959
3960 =item B<mac>
3961
3962 Old Mac partition format.  Modern Macs use C<gpt>.
3963
3964 =item B<pc98>
3965
3966 NEC PC-98 format, common in Japan apparently.
3967
3968 =item B<sun>
3969
3970 Sun disk labels.
3971
3972 =back");
3973
3974   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3975    [InitEmpty, Always, TestRun (
3976       [["part_init"; "/dev/sda"; "mbr"];
3977        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3978     InitEmpty, Always, TestRun (
3979       [["part_init"; "/dev/sda"; "gpt"];
3980        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3981        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3982     InitEmpty, Always, TestRun (
3983       [["part_init"; "/dev/sda"; "mbr"];
3984        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3985        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3986        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3987        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3988    "add a partition to the device",
3989    "\
3990 This command adds a partition to C<device>.  If there is no partition
3991 table on the device, call C<guestfs_part_init> first.
3992
3993 The C<prlogex> parameter is the type of partition.  Normally you
3994 should pass C<p> or C<primary> here, but MBR partition tables also
3995 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
3996 types.
3997
3998 C<startsect> and C<endsect> are the start and end of the partition
3999 in I<sectors>.  C<endsect> may be negative, which means it counts
4000 backwards from the end of the disk (C<-1> is the last sector).
4001
4002 Creating a partition which covers the whole disk is not so easy.
4003 Use C<guestfs_part_disk> to do that.");
4004
4005   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4006    [InitEmpty, Always, TestRun (
4007       [["part_disk"; "/dev/sda"; "mbr"]]);
4008     InitEmpty, Always, TestRun (
4009       [["part_disk"; "/dev/sda"; "gpt"]])],
4010    "partition whole disk with a single primary partition",
4011    "\
4012 This command is simply a combination of C<guestfs_part_init>
4013 followed by C<guestfs_part_add> to create a single primary partition
4014 covering the whole disk.
4015
4016 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4017 but other possible values are described in C<guestfs_part_init>.");
4018
4019   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4020    [InitEmpty, Always, TestRun (
4021       [["part_disk"; "/dev/sda"; "mbr"];
4022        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4023    "make a partition bootable",
4024    "\
4025 This sets the bootable flag on partition numbered C<partnum> on
4026 device C<device>.  Note that partitions are numbered from 1.
4027
4028 The bootable flag is used by some PC BIOSes to determine which
4029 partition to boot from.  It is by no means universally recognized,
4030 and in any case if your operating system installed a boot
4031 sector on the device itself, then that takes precedence.");
4032
4033   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4034    [InitEmpty, Always, TestRun (
4035       [["part_disk"; "/dev/sda"; "gpt"];
4036        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4037    "set partition name",
4038    "\
4039 This sets the partition name on partition numbered C<partnum> on
4040 device C<device>.  Note that partitions are numbered from 1.
4041
4042 The partition name can only be set on certain types of partition
4043 table.  This works on C<gpt> but not on C<mbr> partitions.");
4044
4045   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4046    [], (* XXX Add a regression test for this. *)
4047    "list partitions on a device",
4048    "\
4049 This command parses the partition table on C<device> and
4050 returns the list of partitions found.
4051
4052 The fields in the returned structure are:
4053
4054 =over 4
4055
4056 =item B<part_num>
4057
4058 Partition number, counting from 1.
4059
4060 =item B<part_start>
4061
4062 Start of the partition I<in bytes>.  To get sectors you have to
4063 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4064
4065 =item B<part_end>
4066
4067 End of the partition in bytes.
4068
4069 =item B<part_size>
4070
4071 Size of the partition in bytes.
4072
4073 =back");
4074
4075   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4076    [InitEmpty, Always, TestOutput (
4077       [["part_disk"; "/dev/sda"; "gpt"];
4078        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4079    "get the partition table type",
4080    "\
4081 This command examines the partition table on C<device> and
4082 returns the partition table type (format) being used.
4083
4084 Common return values include: C<msdos> (a DOS/Windows style MBR
4085 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4086 values are possible, although unusual.  See C<guestfs_part_init>
4087 for a full list.");
4088
4089   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4090    [InitBasicFS, Always, TestOutputBuffer (
4091       [["fill"; "0x63"; "10"; "/test"];
4092        ["read_file"; "/test"]], "cccccccccc")],
4093    "fill a file with octets",
4094    "\
4095 This command creates a new file called C<path>.  The initial
4096 content of the file is C<len> octets of C<c>, where C<c>
4097 must be a number in the range C<[0..255]>.
4098
4099 To fill a file with zero bytes (sparsely), it is
4100 much more efficient to use C<guestfs_truncate_size>.");
4101
4102 ]
4103
4104 let all_functions = non_daemon_functions @ daemon_functions
4105
4106 (* In some places we want the functions to be displayed sorted
4107  * alphabetically, so this is useful:
4108  *)
4109 let all_functions_sorted =
4110   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4111                compare n1 n2) all_functions
4112
4113 (* Field types for structures. *)
4114 type field =
4115   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4116   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4117   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4118   | FUInt32
4119   | FInt32
4120   | FUInt64
4121   | FInt64
4122   | FBytes                      (* Any int measure that counts bytes. *)
4123   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4124   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4125
4126 (* Because we generate extra parsing code for LVM command line tools,
4127  * we have to pull out the LVM columns separately here.
4128  *)
4129 let lvm_pv_cols = [
4130   "pv_name", FString;
4131   "pv_uuid", FUUID;
4132   "pv_fmt", FString;
4133   "pv_size", FBytes;
4134   "dev_size", FBytes;
4135   "pv_free", FBytes;
4136   "pv_used", FBytes;
4137   "pv_attr", FString (* XXX *);
4138   "pv_pe_count", FInt64;
4139   "pv_pe_alloc_count", FInt64;
4140   "pv_tags", FString;
4141   "pe_start", FBytes;
4142   "pv_mda_count", FInt64;
4143   "pv_mda_free", FBytes;
4144   (* Not in Fedora 10:
4145      "pv_mda_size", FBytes;
4146   *)
4147 ]
4148 let lvm_vg_cols = [
4149   "vg_name", FString;
4150   "vg_uuid", FUUID;
4151   "vg_fmt", FString;
4152   "vg_attr", FString (* XXX *);
4153   "vg_size", FBytes;
4154   "vg_free", FBytes;
4155   "vg_sysid", FString;
4156   "vg_extent_size", FBytes;
4157   "vg_extent_count", FInt64;
4158   "vg_free_count", FInt64;
4159   "max_lv", FInt64;
4160   "max_pv", FInt64;
4161   "pv_count", FInt64;
4162   "lv_count", FInt64;
4163   "snap_count", FInt64;
4164   "vg_seqno", FInt64;
4165   "vg_tags", FString;
4166   "vg_mda_count", FInt64;
4167   "vg_mda_free", FBytes;
4168   (* Not in Fedora 10:
4169      "vg_mda_size", FBytes;
4170   *)
4171 ]
4172 let lvm_lv_cols = [
4173   "lv_name", FString;
4174   "lv_uuid", FUUID;
4175   "lv_attr", FString (* XXX *);
4176   "lv_major", FInt64;
4177   "lv_minor", FInt64;
4178   "lv_kernel_major", FInt64;
4179   "lv_kernel_minor", FInt64;
4180   "lv_size", FBytes;
4181   "seg_count", FInt64;
4182   "origin", FString;
4183   "snap_percent", FOptPercent;
4184   "copy_percent", FOptPercent;
4185   "move_pv", FString;
4186   "lv_tags", FString;
4187   "mirror_log", FString;
4188   "modules", FString;
4189 ]
4190
4191 (* Names and fields in all structures (in RStruct and RStructList)
4192  * that we support.
4193  *)
4194 let structs = [
4195   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4196    * not use this struct in any new code.
4197    *)
4198   "int_bool", [
4199     "i", FInt32;                (* for historical compatibility *)
4200     "b", FInt32;                (* for historical compatibility *)
4201   ];
4202
4203   (* LVM PVs, VGs, LVs. *)
4204   "lvm_pv", lvm_pv_cols;
4205   "lvm_vg", lvm_vg_cols;
4206   "lvm_lv", lvm_lv_cols;
4207
4208   (* Column names and types from stat structures.
4209    * NB. Can't use things like 'st_atime' because glibc header files
4210    * define some of these as macros.  Ugh.
4211    *)
4212   "stat", [
4213     "dev", FInt64;
4214     "ino", FInt64;
4215     "mode", FInt64;
4216     "nlink", FInt64;
4217     "uid", FInt64;
4218     "gid", FInt64;
4219     "rdev", FInt64;
4220     "size", FInt64;
4221     "blksize", FInt64;
4222     "blocks", FInt64;
4223     "atime", FInt64;
4224     "mtime", FInt64;
4225     "ctime", FInt64;
4226   ];
4227   "statvfs", [
4228     "bsize", FInt64;
4229     "frsize", FInt64;
4230     "blocks", FInt64;
4231     "bfree", FInt64;
4232     "bavail", FInt64;
4233     "files", FInt64;
4234     "ffree", FInt64;
4235     "favail", FInt64;
4236     "fsid", FInt64;
4237     "flag", FInt64;
4238     "namemax", FInt64;
4239   ];
4240
4241   (* Column names in dirent structure. *)
4242   "dirent", [
4243     "ino", FInt64;
4244     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4245     "ftyp", FChar;
4246     "name", FString;
4247   ];
4248
4249   (* Version numbers. *)
4250   "version", [
4251     "major", FInt64;
4252     "minor", FInt64;
4253     "release", FInt64;
4254     "extra", FString;
4255   ];
4256
4257   (* Extended attribute. *)
4258   "xattr", [
4259     "attrname", FString;
4260     "attrval", FBuffer;
4261   ];
4262
4263   (* Inotify events. *)
4264   "inotify_event", [
4265     "in_wd", FInt64;
4266     "in_mask", FUInt32;
4267     "in_cookie", FUInt32;
4268     "in_name", FString;
4269   ];
4270
4271   (* Partition table entry. *)
4272   "partition", [
4273     "part_num", FInt32;
4274     "part_start", FBytes;
4275     "part_end", FBytes;
4276     "part_size", FBytes;
4277   ];
4278 ] (* end of structs *)
4279
4280 (* Ugh, Java has to be different ..
4281  * These names are also used by the Haskell bindings.
4282  *)
4283 let java_structs = [
4284   "int_bool", "IntBool";
4285   "lvm_pv", "PV";
4286   "lvm_vg", "VG";
4287   "lvm_lv", "LV";
4288   "stat", "Stat";
4289   "statvfs", "StatVFS";
4290   "dirent", "Dirent";
4291   "version", "Version";
4292   "xattr", "XAttr";
4293   "inotify_event", "INotifyEvent";
4294   "partition", "Partition";
4295 ]
4296
4297 (* What structs are actually returned. *)
4298 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4299
4300 (* Returns a list of RStruct/RStructList structs that are returned
4301  * by any function.  Each element of returned list is a pair:
4302  *
4303  * (structname, RStructOnly)
4304  *    == there exists function which returns RStruct (_, structname)
4305  * (structname, RStructListOnly)
4306  *    == there exists function which returns RStructList (_, structname)
4307  * (structname, RStructAndList)
4308  *    == there are functions returning both RStruct (_, structname)
4309  *                                      and RStructList (_, structname)
4310  *)
4311 let rstructs_used_by functions =
4312   (* ||| is a "logical OR" for rstructs_used_t *)
4313   let (|||) a b =
4314     match a, b with
4315     | RStructAndList, _
4316     | _, RStructAndList -> RStructAndList
4317     | RStructOnly, RStructListOnly
4318     | RStructListOnly, RStructOnly -> RStructAndList
4319     | RStructOnly, RStructOnly -> RStructOnly
4320     | RStructListOnly, RStructListOnly -> RStructListOnly
4321   in
4322
4323   let h = Hashtbl.create 13 in
4324
4325   (* if elem->oldv exists, update entry using ||| operator,
4326    * else just add elem->newv to the hash
4327    *)
4328   let update elem newv =
4329     try  let oldv = Hashtbl.find h elem in
4330          Hashtbl.replace h elem (newv ||| oldv)
4331     with Not_found -> Hashtbl.add h elem newv
4332   in
4333
4334   List.iter (
4335     fun (_, style, _, _, _, _, _) ->
4336       match fst style with
4337       | RStruct (_, structname) -> update structname RStructOnly
4338       | RStructList (_, structname) -> update structname RStructListOnly
4339       | _ -> ()
4340   ) functions;
4341
4342   (* return key->values as a list of (key,value) *)
4343   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4344
4345 (* Used for testing language bindings. *)
4346 type callt =
4347   | CallString of string
4348   | CallOptString of string option
4349   | CallStringList of string list
4350   | CallInt of int
4351   | CallInt64 of int64
4352   | CallBool of bool
4353
4354 (* Used to memoize the result of pod2text. *)
4355 let pod2text_memo_filename = "src/.pod2text.data"
4356 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4357   try
4358     let chan = open_in pod2text_memo_filename in
4359     let v = input_value chan in
4360     close_in chan;
4361     v
4362   with
4363     _ -> Hashtbl.create 13
4364 let pod2text_memo_updated () =
4365   let chan = open_out pod2text_memo_filename in
4366   output_value chan pod2text_memo;
4367   close_out chan
4368
4369 (* Useful functions.
4370  * Note we don't want to use any external OCaml libraries which
4371  * makes this a bit harder than it should be.
4372  *)
4373 let failwithf fs = ksprintf failwith fs
4374
4375 let replace_char s c1 c2 =
4376   let s2 = String.copy s in
4377   let r = ref false in
4378   for i = 0 to String.length s2 - 1 do
4379     if String.unsafe_get s2 i = c1 then (
4380       String.unsafe_set s2 i c2;
4381       r := true
4382     )
4383   done;
4384   if not !r then s else s2
4385
4386 let isspace c =
4387   c = ' '
4388   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4389
4390 let triml ?(test = isspace) str =
4391   let i = ref 0 in
4392   let n = ref (String.length str) in
4393   while !n > 0 && test str.[!i]; do
4394     decr n;
4395     incr i
4396   done;
4397   if !i = 0 then str
4398   else String.sub str !i !n
4399
4400 let trimr ?(test = isspace) str =
4401   let n = ref (String.length str) in
4402   while !n > 0 && test str.[!n-1]; do
4403     decr n
4404   done;
4405   if !n = String.length str then str
4406   else String.sub str 0 !n
4407
4408 let trim ?(test = isspace) str =
4409   trimr ~test (triml ~test str)
4410
4411 let rec find s sub =
4412   let len = String.length s in
4413   let sublen = String.length sub in
4414   let rec loop i =
4415     if i <= len-sublen then (
4416       let rec loop2 j =
4417         if j < sublen then (
4418           if s.[i+j] = sub.[j] then loop2 (j+1)
4419           else -1
4420         ) else
4421           i (* found *)
4422       in
4423       let r = loop2 0 in
4424       if r = -1 then loop (i+1) else r
4425     ) else
4426       -1 (* not found *)
4427   in
4428   loop 0
4429
4430 let rec replace_str s s1 s2 =
4431   let len = String.length s in
4432   let sublen = String.length s1 in
4433   let i = find s s1 in
4434   if i = -1 then s
4435   else (
4436     let s' = String.sub s 0 i in
4437     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4438     s' ^ s2 ^ replace_str s'' s1 s2
4439   )
4440
4441 let rec string_split sep str =
4442   let len = String.length str in
4443   let seplen = String.length sep in
4444   let i = find str sep in
4445   if i = -1 then [str]
4446   else (
4447     let s' = String.sub str 0 i in
4448     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4449     s' :: string_split sep s''
4450   )
4451
4452 let files_equal n1 n2 =
4453   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4454   match Sys.command cmd with
4455   | 0 -> true
4456   | 1 -> false
4457   | i -> failwithf "%s: failed with error code %d" cmd i
4458
4459 let rec filter_map f = function
4460   | [] -> []
4461   | x :: xs ->
4462       match f x with
4463       | Some y -> y :: filter_map f xs
4464       | None -> filter_map f xs
4465
4466 let rec find_map f = function
4467   | [] -> raise Not_found
4468   | x :: xs ->
4469       match f x with
4470       | Some y -> y
4471       | None -> find_map f xs
4472
4473 let iteri f xs =
4474   let rec loop i = function
4475     | [] -> ()
4476     | x :: xs -> f i x; loop (i+1) xs
4477   in
4478   loop 0 xs
4479
4480 let mapi f xs =
4481   let rec loop i = function
4482     | [] -> []
4483     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4484   in
4485   loop 0 xs
4486
4487 let name_of_argt = function
4488   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4489   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4490   | FileIn n | FileOut n -> n
4491
4492 let java_name_of_struct typ =
4493   try List.assoc typ java_structs
4494   with Not_found ->
4495     failwithf
4496       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4497
4498 let cols_of_struct typ =
4499   try List.assoc typ structs
4500   with Not_found ->
4501     failwithf "cols_of_struct: unknown struct %s" typ
4502
4503 let seq_of_test = function
4504   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4505   | TestOutputListOfDevices (s, _)
4506   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4507   | TestOutputTrue s | TestOutputFalse s
4508   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4509   | TestOutputStruct (s, _)
4510   | TestLastFail s -> s
4511
4512 (* Handling for function flags. *)
4513 let protocol_limit_warning =
4514   "Because of the message protocol, there is a transfer limit
4515 of somewhere between 2MB and 4MB.  To transfer large files you should use
4516 FTP."
4517
4518 let danger_will_robinson =
4519   "B<This command is dangerous.  Without careful use you
4520 can easily destroy all your data>."
4521
4522 let deprecation_notice flags =
4523   try
4524     let alt =
4525       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4526     let txt =
4527       sprintf "This function is deprecated.
4528 In new code, use the C<%s> call instead.
4529
4530 Deprecated functions will not be removed from the API, but the
4531 fact that they are deprecated indicates that there are problems
4532 with correct use of these functions." alt in
4533     Some txt
4534   with
4535     Not_found -> None
4536
4537 (* Check function names etc. for consistency. *)
4538 let check_functions () =
4539   let contains_uppercase str =
4540     let len = String.length str in
4541     let rec loop i =
4542       if i >= len then false
4543       else (
4544         let c = str.[i] in
4545         if c >= 'A' && c <= 'Z' then true
4546         else loop (i+1)
4547       )
4548     in
4549     loop 0
4550   in
4551
4552   (* Check function names. *)
4553   List.iter (
4554     fun (name, _, _, _, _, _, _) ->
4555       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4556         failwithf "function name %s does not need 'guestfs' prefix" name;
4557       if name = "" then
4558         failwithf "function name is empty";
4559       if name.[0] < 'a' || name.[0] > 'z' then
4560         failwithf "function name %s must start with lowercase a-z" name;
4561       if String.contains name '-' then
4562         failwithf "function name %s should not contain '-', use '_' instead."
4563           name
4564   ) all_functions;
4565
4566   (* Check function parameter/return names. *)
4567   List.iter (
4568     fun (name, style, _, _, _, _, _) ->
4569       let check_arg_ret_name n =
4570         if contains_uppercase n then
4571           failwithf "%s param/ret %s should not contain uppercase chars"
4572             name n;
4573         if String.contains n '-' || String.contains n '_' then
4574           failwithf "%s param/ret %s should not contain '-' or '_'"
4575             name n;
4576         if n = "value" then
4577           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;
4578         if n = "int" || n = "char" || n = "short" || n = "long" then
4579           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4580         if n = "i" || n = "n" then
4581           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4582         if n = "argv" || n = "args" then
4583           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4584
4585         (* List Haskell, OCaml and C keywords here.
4586          * http://www.haskell.org/haskellwiki/Keywords
4587          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4588          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4589          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4590          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4591          * Omitting _-containing words, since they're handled above.
4592          * Omitting the OCaml reserved word, "val", is ok,
4593          * and saves us from renaming several parameters.
4594          *)
4595         let reserved = [
4596           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4597           "char"; "class"; "const"; "constraint"; "continue"; "data";
4598           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4599           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4600           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4601           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4602           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4603           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4604           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4605           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4606           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4607           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4608           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4609           "volatile"; "when"; "where"; "while";
4610           ] in
4611         if List.mem n reserved then
4612           failwithf "%s has param/ret using reserved word %s" name n;
4613       in
4614
4615       (match fst style with
4616        | RErr -> ()
4617        | RInt n | RInt64 n | RBool n
4618        | RConstString n | RConstOptString n | RString n
4619        | RStringList n | RStruct (n, _) | RStructList (n, _)
4620        | RHashtable n | RBufferOut n ->
4621            check_arg_ret_name n
4622       );
4623       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4624   ) all_functions;
4625
4626   (* Check short descriptions. *)
4627   List.iter (
4628     fun (name, _, _, _, _, shortdesc, _) ->
4629       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4630         failwithf "short description of %s should begin with lowercase." name;
4631       let c = shortdesc.[String.length shortdesc-1] in
4632       if c = '\n' || c = '.' then
4633         failwithf "short description of %s should not end with . or \\n." name
4634   ) all_functions;
4635
4636   (* Check long dscriptions. *)
4637   List.iter (
4638     fun (name, _, _, _, _, _, longdesc) ->
4639       if longdesc.[String.length longdesc-1] = '\n' then
4640         failwithf "long description of %s should not end with \\n." name
4641   ) all_functions;
4642
4643   (* Check proc_nrs. *)
4644   List.iter (
4645     fun (name, _, proc_nr, _, _, _, _) ->
4646       if proc_nr <= 0 then
4647         failwithf "daemon function %s should have proc_nr > 0" name
4648   ) daemon_functions;
4649
4650   List.iter (
4651     fun (name, _, proc_nr, _, _, _, _) ->
4652       if proc_nr <> -1 then
4653         failwithf "non-daemon function %s should have proc_nr -1" name
4654   ) non_daemon_functions;
4655
4656   let proc_nrs =
4657     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4658       daemon_functions in
4659   let proc_nrs =
4660     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4661   let rec loop = function
4662     | [] -> ()
4663     | [_] -> ()
4664     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4665         loop rest
4666     | (name1,nr1) :: (name2,nr2) :: _ ->
4667         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4668           name1 name2 nr1 nr2
4669   in
4670   loop proc_nrs;
4671
4672   (* Check tests. *)
4673   List.iter (
4674     function
4675       (* Ignore functions that have no tests.  We generate a
4676        * warning when the user does 'make check' instead.
4677        *)
4678     | name, _, _, _, [], _, _ -> ()
4679     | name, _, _, _, tests, _, _ ->
4680         let funcs =
4681           List.map (
4682             fun (_, _, test) ->
4683               match seq_of_test test with
4684               | [] ->
4685                   failwithf "%s has a test containing an empty sequence" name
4686               | cmds -> List.map List.hd cmds
4687           ) tests in
4688         let funcs = List.flatten funcs in
4689
4690         let tested = List.mem name funcs in
4691
4692         if not tested then
4693           failwithf "function %s has tests but does not test itself" name
4694   ) all_functions
4695
4696 (* 'pr' prints to the current output file. *)
4697 let chan = ref stdout
4698 let pr fs = ksprintf (output_string !chan) fs
4699
4700 (* Generate a header block in a number of standard styles. *)
4701 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4702 type license = GPLv2 | LGPLv2
4703
4704 let generate_header comment license =
4705   let c = match comment with
4706     | CStyle ->     pr "/* "; " *"
4707     | HashStyle ->  pr "# ";  "#"
4708     | OCamlStyle -> pr "(* "; " *"
4709     | HaskellStyle -> pr "{- "; "  " in
4710   pr "libguestfs generated file\n";
4711   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4712   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4713   pr "%s\n" c;
4714   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4715   pr "%s\n" c;
4716   (match license with
4717    | GPLv2 ->
4718        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4719        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4720        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4721        pr "%s (at your option) any later version.\n" c;
4722        pr "%s\n" c;
4723        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4724        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4725        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4726        pr "%s GNU General Public License for more details.\n" c;
4727        pr "%s\n" c;
4728        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4729        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4730        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4731
4732    | LGPLv2 ->
4733        pr "%s This library is free software; you can redistribute it and/or\n" c;
4734        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4735        pr "%s License as published by the Free Software Foundation; either\n" c;
4736        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4737        pr "%s\n" c;
4738        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4739        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4740        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4741        pr "%s Lesser General Public License for more details.\n" c;
4742        pr "%s\n" c;
4743        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4744        pr "%s License along with this library; if not, write to the Free Software\n" c;
4745        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4746   );
4747   (match comment with
4748    | CStyle -> pr " */\n"
4749    | HashStyle -> ()
4750    | OCamlStyle -> pr " *)\n"
4751    | HaskellStyle -> pr "-}\n"
4752   );
4753   pr "\n"
4754
4755 (* Start of main code generation functions below this line. *)
4756
4757 (* Generate the pod documentation for the C API. *)
4758 let rec generate_actions_pod () =
4759   List.iter (
4760     fun (shortname, style, _, flags, _, _, longdesc) ->
4761       if not (List.mem NotInDocs flags) then (
4762         let name = "guestfs_" ^ shortname in
4763         pr "=head2 %s\n\n" name;
4764         pr " ";
4765         generate_prototype ~extern:false ~handle:"handle" name style;
4766         pr "\n\n";
4767         pr "%s\n\n" longdesc;
4768         (match fst style with
4769          | RErr ->
4770              pr "This function returns 0 on success or -1 on error.\n\n"
4771          | RInt _ ->
4772              pr "On error this function returns -1.\n\n"
4773          | RInt64 _ ->
4774              pr "On error this function returns -1.\n\n"
4775          | RBool _ ->
4776              pr "This function returns a C truth value on success or -1 on error.\n\n"
4777          | RConstString _ ->
4778              pr "This function returns a string, or NULL on error.
4779 The string is owned by the guest handle and must I<not> be freed.\n\n"
4780          | RConstOptString _ ->
4781              pr "This function returns a string which may be NULL.
4782 There is way to return an error from this function.
4783 The string is owned by the guest handle and must I<not> be freed.\n\n"
4784          | RString _ ->
4785              pr "This function returns a string, or NULL on error.
4786 I<The caller must free the returned string after use>.\n\n"
4787          | RStringList _ ->
4788              pr "This function returns a NULL-terminated array of strings
4789 (like L<environ(3)>), or NULL if there was an error.
4790 I<The caller must free the strings and the array after use>.\n\n"
4791          | RStruct (_, typ) ->
4792              pr "This function returns a C<struct guestfs_%s *>,
4793 or NULL if there was an error.
4794 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4795          | RStructList (_, typ) ->
4796              pr "This function returns a C<struct guestfs_%s_list *>
4797 (see E<lt>guestfs-structs.hE<gt>),
4798 or NULL if there was an error.
4799 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4800          | RHashtable _ ->
4801              pr "This function returns a NULL-terminated array of
4802 strings, or NULL if there was an error.
4803 The array of strings will always have length C<2n+1>, where
4804 C<n> keys and values alternate, followed by the trailing NULL entry.
4805 I<The caller must free the strings and the array after use>.\n\n"
4806          | RBufferOut _ ->
4807              pr "This function returns a buffer, or NULL on error.
4808 The size of the returned buffer is written to C<*size_r>.
4809 I<The caller must free the returned buffer after use>.\n\n"
4810         );
4811         if List.mem ProtocolLimitWarning flags then
4812           pr "%s\n\n" protocol_limit_warning;
4813         if List.mem DangerWillRobinson flags then
4814           pr "%s\n\n" danger_will_robinson;
4815         match deprecation_notice flags with
4816         | None -> ()
4817         | Some txt -> pr "%s\n\n" txt
4818       )
4819   ) all_functions_sorted
4820
4821 and generate_structs_pod () =
4822   (* Structs documentation. *)
4823   List.iter (
4824     fun (typ, cols) ->
4825       pr "=head2 guestfs_%s\n" typ;
4826       pr "\n";
4827       pr " struct guestfs_%s {\n" typ;
4828       List.iter (
4829         function
4830         | name, FChar -> pr "   char %s;\n" name
4831         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4832         | name, FInt32 -> pr "   int32_t %s;\n" name
4833         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4834         | name, FInt64 -> pr "   int64_t %s;\n" name
4835         | name, FString -> pr "   char *%s;\n" name
4836         | name, FBuffer ->
4837             pr "   /* The next two fields describe a byte array. */\n";
4838             pr "   uint32_t %s_len;\n" name;
4839             pr "   char *%s;\n" name
4840         | name, FUUID ->
4841             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4842             pr "   char %s[32];\n" name
4843         | name, FOptPercent ->
4844             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4845             pr "   float %s;\n" name
4846       ) cols;
4847       pr " };\n";
4848       pr " \n";
4849       pr " struct guestfs_%s_list {\n" typ;
4850       pr "   uint32_t len; /* Number of elements in list. */\n";
4851       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4852       pr " };\n";
4853       pr " \n";
4854       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4855       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4856         typ typ;
4857       pr "\n"
4858   ) structs
4859
4860 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4861  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4862  *
4863  * We have to use an underscore instead of a dash because otherwise
4864  * rpcgen generates incorrect code.
4865  *
4866  * This header is NOT exported to clients, but see also generate_structs_h.
4867  *)
4868 and generate_xdr () =
4869   generate_header CStyle LGPLv2;
4870
4871   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4872   pr "typedef string str<>;\n";
4873   pr "\n";
4874
4875   (* Internal structures. *)
4876   List.iter (
4877     function
4878     | typ, cols ->
4879         pr "struct guestfs_int_%s {\n" typ;
4880         List.iter (function
4881                    | name, FChar -> pr "  char %s;\n" name
4882                    | name, FString -> pr "  string %s<>;\n" name
4883                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4884                    | name, FUUID -> pr "  opaque %s[32];\n" name
4885                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4886                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4887                    | name, FOptPercent -> pr "  float %s;\n" name
4888                   ) cols;
4889         pr "};\n";
4890         pr "\n";
4891         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4892         pr "\n";
4893   ) structs;
4894
4895   List.iter (
4896     fun (shortname, style, _, _, _, _, _) ->
4897       let name = "guestfs_" ^ shortname in
4898
4899       (match snd style with
4900        | [] -> ()
4901        | args ->
4902            pr "struct %s_args {\n" name;
4903            List.iter (
4904              function
4905              | Pathname n | Device n | Dev_or_Path n | String n ->
4906                  pr "  string %s<>;\n" n
4907              | OptString n -> pr "  str *%s;\n" n
4908              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4909              | Bool n -> pr "  bool %s;\n" n
4910              | Int n -> pr "  int %s;\n" n
4911              | Int64 n -> pr "  hyper %s;\n" n
4912              | FileIn _ | FileOut _ -> ()
4913            ) args;
4914            pr "};\n\n"
4915       );
4916       (match fst style with
4917        | RErr -> ()
4918        | RInt n ->
4919            pr "struct %s_ret {\n" name;
4920            pr "  int %s;\n" n;
4921            pr "};\n\n"
4922        | RInt64 n ->
4923            pr "struct %s_ret {\n" name;
4924            pr "  hyper %s;\n" n;
4925            pr "};\n\n"
4926        | RBool n ->
4927            pr "struct %s_ret {\n" name;
4928            pr "  bool %s;\n" n;
4929            pr "};\n\n"
4930        | RConstString _ | RConstOptString _ ->
4931            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4932        | RString n ->
4933            pr "struct %s_ret {\n" name;
4934            pr "  string %s<>;\n" n;
4935            pr "};\n\n"
4936        | RStringList n ->
4937            pr "struct %s_ret {\n" name;
4938            pr "  str %s<>;\n" n;
4939            pr "};\n\n"
4940        | RStruct (n, typ) ->
4941            pr "struct %s_ret {\n" name;
4942            pr "  guestfs_int_%s %s;\n" typ n;
4943            pr "};\n\n"
4944        | RStructList (n, typ) ->
4945            pr "struct %s_ret {\n" name;
4946            pr "  guestfs_int_%s_list %s;\n" typ n;
4947            pr "};\n\n"
4948        | RHashtable n ->
4949            pr "struct %s_ret {\n" name;
4950            pr "  str %s<>;\n" n;
4951            pr "};\n\n"
4952        | RBufferOut n ->
4953            pr "struct %s_ret {\n" name;
4954            pr "  opaque %s<>;\n" n;
4955            pr "};\n\n"
4956       );
4957   ) daemon_functions;
4958
4959   (* Table of procedure numbers. *)
4960   pr "enum guestfs_procedure {\n";
4961   List.iter (
4962     fun (shortname, _, proc_nr, _, _, _, _) ->
4963       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4964   ) daemon_functions;
4965   pr "  GUESTFS_PROC_NR_PROCS\n";
4966   pr "};\n";
4967   pr "\n";
4968
4969   (* Having to choose a maximum message size is annoying for several
4970    * reasons (it limits what we can do in the API), but it (a) makes
4971    * the protocol a lot simpler, and (b) provides a bound on the size
4972    * of the daemon which operates in limited memory space.  For large
4973    * file transfers you should use FTP.
4974    *)
4975   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4976   pr "\n";
4977
4978   (* Message header, etc. *)
4979   pr "\
4980 /* The communication protocol is now documented in the guestfs(3)
4981  * manpage.
4982  */
4983
4984 const GUESTFS_PROGRAM = 0x2000F5F5;
4985 const GUESTFS_PROTOCOL_VERSION = 1;
4986
4987 /* These constants must be larger than any possible message length. */
4988 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4989 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4990
4991 enum guestfs_message_direction {
4992   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4993   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4994 };
4995
4996 enum guestfs_message_status {
4997   GUESTFS_STATUS_OK = 0,
4998   GUESTFS_STATUS_ERROR = 1
4999 };
5000
5001 const GUESTFS_ERROR_LEN = 256;
5002
5003 struct guestfs_message_error {
5004   string error_message<GUESTFS_ERROR_LEN>;
5005 };
5006
5007 struct guestfs_message_header {
5008   unsigned prog;                     /* GUESTFS_PROGRAM */
5009   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5010   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5011   guestfs_message_direction direction;
5012   unsigned serial;                   /* message serial number */
5013   guestfs_message_status status;
5014 };
5015
5016 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5017
5018 struct guestfs_chunk {
5019   int cancel;                        /* if non-zero, transfer is cancelled */
5020   /* data size is 0 bytes if the transfer has finished successfully */
5021   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5022 };
5023 "
5024
5025 (* Generate the guestfs-structs.h file. *)
5026 and generate_structs_h () =
5027   generate_header CStyle LGPLv2;
5028
5029   (* This is a public exported header file containing various
5030    * structures.  The structures are carefully written to have
5031    * exactly the same in-memory format as the XDR structures that
5032    * we use on the wire to the daemon.  The reason for creating
5033    * copies of these structures here is just so we don't have to
5034    * export the whole of guestfs_protocol.h (which includes much
5035    * unrelated and XDR-dependent stuff that we don't want to be
5036    * public, or required by clients).
5037    *
5038    * To reiterate, we will pass these structures to and from the
5039    * client with a simple assignment or memcpy, so the format
5040    * must be identical to what rpcgen / the RFC defines.
5041    *)
5042
5043   (* Public structures. *)
5044   List.iter (
5045     fun (typ, cols) ->
5046       pr "struct guestfs_%s {\n" typ;
5047       List.iter (
5048         function
5049         | name, FChar -> pr "  char %s;\n" name
5050         | name, FString -> pr "  char *%s;\n" name
5051         | name, FBuffer ->
5052             pr "  uint32_t %s_len;\n" name;
5053             pr "  char *%s;\n" name
5054         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5055         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5056         | name, FInt32 -> pr "  int32_t %s;\n" name
5057         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5058         | name, FInt64 -> pr "  int64_t %s;\n" name
5059         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5060       ) cols;
5061       pr "};\n";
5062       pr "\n";
5063       pr "struct guestfs_%s_list {\n" typ;
5064       pr "  uint32_t len;\n";
5065       pr "  struct guestfs_%s *val;\n" typ;
5066       pr "};\n";
5067       pr "\n";
5068       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5069       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5070       pr "\n"
5071   ) structs
5072
5073 (* Generate the guestfs-actions.h file. *)
5074 and generate_actions_h () =
5075   generate_header CStyle LGPLv2;
5076   List.iter (
5077     fun (shortname, style, _, _, _, _, _) ->
5078       let name = "guestfs_" ^ shortname in
5079       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5080         name style
5081   ) all_functions
5082
5083 (* Generate the guestfs-internal-actions.h file. *)
5084 and generate_internal_actions_h () =
5085   generate_header CStyle LGPLv2;
5086   List.iter (
5087     fun (shortname, style, _, _, _, _, _) ->
5088       let name = "guestfs__" ^ shortname in
5089       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5090         name style
5091   ) non_daemon_functions
5092
5093 (* Generate the client-side dispatch stubs. *)
5094 and generate_client_actions () =
5095   generate_header CStyle LGPLv2;
5096
5097   pr "\
5098 #include <stdio.h>
5099 #include <stdlib.h>
5100 #include <stdint.h>
5101 #include <inttypes.h>
5102
5103 #include \"guestfs.h\"
5104 #include \"guestfs-internal.h\"
5105 #include \"guestfs-internal-actions.h\"
5106 #include \"guestfs_protocol.h\"
5107
5108 #define error guestfs_error
5109 //#define perrorf guestfs_perrorf
5110 //#define safe_malloc guestfs_safe_malloc
5111 #define safe_realloc guestfs_safe_realloc
5112 //#define safe_strdup guestfs_safe_strdup
5113 #define safe_memdup guestfs_safe_memdup
5114
5115 /* Check the return message from a call for validity. */
5116 static int
5117 check_reply_header (guestfs_h *g,
5118                     const struct guestfs_message_header *hdr,
5119                     unsigned int proc_nr, unsigned int serial)
5120 {
5121   if (hdr->prog != GUESTFS_PROGRAM) {
5122     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5123     return -1;
5124   }
5125   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5126     error (g, \"wrong protocol version (%%d/%%d)\",
5127            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5128     return -1;
5129   }
5130   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5131     error (g, \"unexpected message direction (%%d/%%d)\",
5132            hdr->direction, GUESTFS_DIRECTION_REPLY);
5133     return -1;
5134   }
5135   if (hdr->proc != proc_nr) {
5136     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5137     return -1;
5138   }
5139   if (hdr->serial != serial) {
5140     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5141     return -1;
5142   }
5143
5144   return 0;
5145 }
5146
5147 /* Check we are in the right state to run a high-level action. */
5148 static int
5149 check_state (guestfs_h *g, const char *caller)
5150 {
5151   if (!guestfs__is_ready (g)) {
5152     if (guestfs__is_config (g) || guestfs__is_launching (g))
5153       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5154         caller);
5155     else
5156       error (g, \"%%s called from the wrong state, %%d != READY\",
5157         caller, guestfs__get_state (g));
5158     return -1;
5159   }
5160   return 0;
5161 }
5162
5163 ";
5164
5165   (* Generate code to generate guestfish call traces. *)
5166   let trace_call shortname style =
5167     pr "  if (guestfs__get_trace (g)) {\n";
5168
5169     let needs_i =
5170       List.exists (function
5171                    | StringList _ | DeviceList _ -> true
5172                    | _ -> false) (snd style) in
5173     if needs_i then (
5174       pr "    int i;\n";
5175       pr "\n"
5176     );
5177
5178     pr "    printf (\"%s\");\n" shortname;
5179     List.iter (
5180       function
5181       | String n                        (* strings *)
5182       | Device n
5183       | Pathname n
5184       | Dev_or_Path n
5185       | FileIn n
5186       | FileOut n ->
5187           (* guestfish doesn't support string escaping, so neither do we *)
5188           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5189       | OptString n ->                  (* string option *)
5190           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5191           pr "    else printf (\" null\");\n"
5192       | StringList n
5193       | DeviceList n ->                 (* string list *)
5194           pr "    putchar (' ');\n";
5195           pr "    putchar ('\"');\n";
5196           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5197           pr "      if (i > 0) putchar (' ');\n";
5198           pr "      fputs (%s[i], stdout);\n" n;
5199           pr "    }\n";
5200           pr "    putchar ('\"');\n";
5201       | Bool n ->                       (* boolean *)
5202           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5203       | Int n ->                        (* int *)
5204           pr "    printf (\" %%d\", %s);\n" n
5205       | Int64 n ->
5206           pr "    printf (\" %%\" PRIi64, %s);\n" n
5207     ) (snd style);
5208     pr "    putchar ('\\n');\n";
5209     pr "  }\n";
5210     pr "\n";
5211   in
5212
5213   (* For non-daemon functions, generate a wrapper around each function. *)
5214   List.iter (
5215     fun (shortname, style, _, _, _, _, _) ->
5216       let name = "guestfs_" ^ shortname in
5217
5218       generate_prototype ~extern:false ~semicolon:false ~newline:true
5219         ~handle:"g" name style;
5220       pr "{\n";
5221       trace_call shortname style;
5222       pr "  return guestfs__%s " shortname;
5223       generate_c_call_args ~handle:"g" style;
5224       pr ";\n";
5225       pr "}\n";
5226       pr "\n"
5227   ) non_daemon_functions;
5228
5229   (* Client-side stubs for each function. *)
5230   List.iter (
5231     fun (shortname, style, _, _, _, _, _) ->
5232       let name = "guestfs_" ^ shortname in
5233
5234       (* Generate the action stub. *)
5235       generate_prototype ~extern:false ~semicolon:false ~newline:true
5236         ~handle:"g" name style;
5237
5238       let error_code =
5239         match fst style with
5240         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5241         | RConstString _ | RConstOptString _ ->
5242             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5243         | RString _ | RStringList _
5244         | RStruct _ | RStructList _
5245         | RHashtable _ | RBufferOut _ ->
5246             "NULL" in
5247
5248       pr "{\n";
5249
5250       (match snd style with
5251        | [] -> ()
5252        | _ -> pr "  struct %s_args args;\n" name
5253       );
5254
5255       pr "  guestfs_message_header hdr;\n";
5256       pr "  guestfs_message_error err;\n";
5257       let has_ret =
5258         match fst style with
5259         | RErr -> false
5260         | RConstString _ | RConstOptString _ ->
5261             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5262         | RInt _ | RInt64 _
5263         | RBool _ | RString _ | RStringList _
5264         | RStruct _ | RStructList _
5265         | RHashtable _ | RBufferOut _ ->
5266             pr "  struct %s_ret ret;\n" name;
5267             true in
5268
5269       pr "  int serial;\n";
5270       pr "  int r;\n";
5271       pr "\n";
5272       trace_call shortname style;
5273       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5274       pr "  guestfs___set_busy (g);\n";
5275       pr "\n";
5276
5277       (* Send the main header and arguments. *)
5278       (match snd style with
5279        | [] ->
5280            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5281              (String.uppercase shortname)
5282        | args ->
5283            List.iter (
5284              function
5285              | Pathname n | Device n | Dev_or_Path n | String n ->
5286                  pr "  args.%s = (char *) %s;\n" n n
5287              | OptString n ->
5288                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5289              | StringList n | DeviceList n ->
5290                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5291                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5292              | Bool n ->
5293                  pr "  args.%s = %s;\n" n n
5294              | Int n ->
5295                  pr "  args.%s = %s;\n" n n
5296              | Int64 n ->
5297                  pr "  args.%s = %s;\n" n n
5298              | FileIn _ | FileOut _ -> ()
5299            ) args;
5300            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5301              (String.uppercase shortname);
5302            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5303              name;
5304       );
5305       pr "  if (serial == -1) {\n";
5306       pr "    guestfs___end_busy (g);\n";
5307       pr "    return %s;\n" error_code;
5308       pr "  }\n";
5309       pr "\n";
5310
5311       (* Send any additional files (FileIn) requested. *)
5312       let need_read_reply_label = ref false in
5313       List.iter (
5314         function
5315         | FileIn n ->
5316             pr "  r = guestfs___send_file (g, %s);\n" n;
5317             pr "  if (r == -1) {\n";
5318             pr "    guestfs___end_busy (g);\n";
5319             pr "    return %s;\n" error_code;
5320             pr "  }\n";
5321             pr "  if (r == -2) /* daemon cancelled */\n";
5322             pr "    goto read_reply;\n";
5323             need_read_reply_label := true;
5324             pr "\n";
5325         | _ -> ()
5326       ) (snd style);
5327
5328       (* Wait for the reply from the remote end. *)
5329       if !need_read_reply_label then pr " read_reply:\n";
5330       pr "  memset (&hdr, 0, sizeof hdr);\n";
5331       pr "  memset (&err, 0, sizeof err);\n";
5332       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5333       pr "\n";
5334       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5335       if not has_ret then
5336         pr "NULL, NULL"
5337       else
5338         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5339       pr ");\n";
5340
5341       pr "  if (r == -1) {\n";
5342       pr "    guestfs___end_busy (g);\n";
5343       pr "    return %s;\n" error_code;
5344       pr "  }\n";
5345       pr "\n";
5346
5347       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5348         (String.uppercase shortname);
5349       pr "    guestfs___end_busy (g);\n";
5350       pr "    return %s;\n" error_code;
5351       pr "  }\n";
5352       pr "\n";
5353
5354       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5355       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5356       pr "    free (err.error_message);\n";
5357       pr "    guestfs___end_busy (g);\n";
5358       pr "    return %s;\n" error_code;
5359       pr "  }\n";
5360       pr "\n";
5361
5362       (* Expecting to receive further files (FileOut)? *)
5363       List.iter (
5364         function
5365         | FileOut n ->
5366             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5367             pr "    guestfs___end_busy (g);\n";
5368             pr "    return %s;\n" error_code;
5369             pr "  }\n";
5370             pr "\n";
5371         | _ -> ()
5372       ) (snd style);
5373
5374       pr "  guestfs___end_busy (g);\n";
5375
5376       (match fst style with
5377        | RErr -> pr "  return 0;\n"
5378        | RInt n | RInt64 n | RBool n ->
5379            pr "  return ret.%s;\n" n
5380        | RConstString _ | RConstOptString _ ->
5381            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5382        | RString n ->
5383            pr "  return ret.%s; /* caller will free */\n" n
5384        | RStringList n | RHashtable n ->
5385            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5386            pr "  ret.%s.%s_val =\n" n n;
5387            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5388            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5389              n n;
5390            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5391            pr "  return ret.%s.%s_val;\n" n n
5392        | RStruct (n, _) ->
5393            pr "  /* caller will free this */\n";
5394            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5395        | RStructList (n, _) ->
5396            pr "  /* caller will free this */\n";
5397            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5398        | RBufferOut n ->
5399            pr "  *size_r = ret.%s.%s_len;\n" n n;
5400            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
5401       );
5402
5403       pr "}\n\n"
5404   ) daemon_functions;
5405
5406   (* Functions to free structures. *)
5407   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5408   pr " * structure format is identical to the XDR format.  See note in\n";
5409   pr " * generator.ml.\n";
5410   pr " */\n";
5411   pr "\n";
5412
5413   List.iter (
5414     fun (typ, _) ->
5415       pr "void\n";
5416       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5417       pr "{\n";
5418       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5419       pr "  free (x);\n";
5420       pr "}\n";
5421       pr "\n";
5422
5423       pr "void\n";
5424       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5425       pr "{\n";
5426       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5427       pr "  free (x);\n";
5428       pr "}\n";
5429       pr "\n";
5430
5431   ) structs;
5432
5433 (* Generate daemon/actions.h. *)
5434 and generate_daemon_actions_h () =
5435   generate_header CStyle GPLv2;
5436
5437   pr "#include \"../src/guestfs_protocol.h\"\n";
5438   pr "\n";
5439
5440   List.iter (
5441     fun (name, style, _, _, _, _, _) ->
5442       generate_prototype
5443         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5444         name style;
5445   ) daemon_functions
5446
5447 (* Generate the server-side stubs. *)
5448 and generate_daemon_actions () =
5449   generate_header CStyle GPLv2;
5450
5451   pr "#include <config.h>\n";
5452   pr "\n";
5453   pr "#include <stdio.h>\n";
5454   pr "#include <stdlib.h>\n";
5455   pr "#include <string.h>\n";
5456   pr "#include <inttypes.h>\n";
5457   pr "#include <rpc/types.h>\n";
5458   pr "#include <rpc/xdr.h>\n";
5459   pr "\n";
5460   pr "#include \"daemon.h\"\n";
5461   pr "#include \"c-ctype.h\"\n";
5462   pr "#include \"../src/guestfs_protocol.h\"\n";
5463   pr "#include \"actions.h\"\n";
5464   pr "\n";
5465
5466   List.iter (
5467     fun (name, style, _, _, _, _, _) ->
5468       (* Generate server-side stubs. *)
5469       pr "static void %s_stub (XDR *xdr_in)\n" name;
5470       pr "{\n";
5471       let error_code =
5472         match fst style with
5473         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5474         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5475         | RBool _ -> pr "  int r;\n"; "-1"
5476         | RConstString _ | RConstOptString _ ->
5477             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5478         | RString _ -> pr "  char *r;\n"; "NULL"
5479         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5480         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5481         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5482         | RBufferOut _ ->
5483             pr "  size_t size;\n";
5484             pr "  char *r;\n";
5485             "NULL" in
5486
5487       (match snd style with
5488        | [] -> ()
5489        | args ->
5490            pr "  struct guestfs_%s_args args;\n" name;
5491            List.iter (
5492              function
5493              | Device n | Dev_or_Path n
5494              | Pathname n
5495              | String n -> ()
5496              | OptString n -> pr "  char *%s;\n" n
5497              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5498              | Bool n -> pr "  int %s;\n" n
5499              | Int n -> pr "  int %s;\n" n
5500              | Int64 n -> pr "  int64_t %s;\n" n
5501              | FileIn _ | FileOut _ -> ()
5502            ) args
5503       );
5504       pr "\n";
5505
5506       (match snd style with
5507        | [] -> ()
5508        | args ->
5509            pr "  memset (&args, 0, sizeof args);\n";
5510            pr "\n";
5511            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5512            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5513            pr "    return;\n";
5514            pr "  }\n";
5515            let pr_args n =
5516              pr "  char *%s = args.%s;\n" n n
5517            in
5518            let pr_list_handling_code n =
5519              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5520              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5521              pr "  if (%s == NULL) {\n" n;
5522              pr "    reply_with_perror (\"realloc\");\n";
5523              pr "    goto done;\n";
5524              pr "  }\n";
5525              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5526              pr "  args.%s.%s_val = %s;\n" n n n;
5527            in
5528            List.iter (
5529              function
5530              | Pathname n ->
5531                  pr_args n;
5532                  pr "  ABS_PATH (%s, goto done);\n" n;
5533              | Device n ->
5534                  pr_args n;
5535                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5536              | Dev_or_Path n ->
5537                  pr_args n;
5538                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5539              | String n -> pr_args n
5540              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5541              | StringList n ->
5542                  pr_list_handling_code n;
5543              | DeviceList n ->
5544                  pr_list_handling_code n;
5545                  pr "  /* Ensure that each is a device,\n";
5546                  pr "   * and perform device name translation. */\n";
5547                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5548                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5549                  pr "  }\n";
5550              | Bool n -> pr "  %s = args.%s;\n" n n
5551              | Int n -> pr "  %s = args.%s;\n" n n
5552              | Int64 n -> pr "  %s = args.%s;\n" n n
5553              | FileIn _ | FileOut _ -> ()
5554            ) args;
5555            pr "\n"
5556       );
5557
5558
5559       (* this is used at least for do_equal *)
5560       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5561         (* Emit NEED_ROOT just once, even when there are two or
5562            more Pathname args *)
5563         pr "  NEED_ROOT (goto done);\n";
5564       );
5565
5566       (* Don't want to call the impl with any FileIn or FileOut
5567        * parameters, since these go "outside" the RPC protocol.
5568        *)
5569       let args' =
5570         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5571           (snd style) in
5572       pr "  r = do_%s " name;
5573       generate_c_call_args (fst style, args');
5574       pr ";\n";
5575
5576       pr "  if (r == %s)\n" error_code;
5577       pr "    /* do_%s has already called reply_with_error */\n" name;
5578       pr "    goto done;\n";
5579       pr "\n";
5580
5581       (* If there are any FileOut parameters, then the impl must
5582        * send its own reply.
5583        *)
5584       let no_reply =
5585         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5586       if no_reply then
5587         pr "  /* do_%s has already sent a reply */\n" name
5588       else (
5589         match fst style with
5590         | RErr -> pr "  reply (NULL, NULL);\n"
5591         | RInt n | RInt64 n | RBool n ->
5592             pr "  struct guestfs_%s_ret ret;\n" name;
5593             pr "  ret.%s = r;\n" n;
5594             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5595               name
5596         | RConstString _ | RConstOptString _ ->
5597             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5598         | RString n ->
5599             pr "  struct guestfs_%s_ret ret;\n" name;
5600             pr "  ret.%s = r;\n" n;
5601             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5602               name;
5603             pr "  free (r);\n"
5604         | RStringList n | RHashtable n ->
5605             pr "  struct guestfs_%s_ret ret;\n" name;
5606             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5607             pr "  ret.%s.%s_val = r;\n" n n;
5608             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5609               name;
5610             pr "  free_strings (r);\n"
5611         | RStruct (n, _) ->
5612             pr "  struct guestfs_%s_ret ret;\n" name;
5613             pr "  ret.%s = *r;\n" n;
5614             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5615               name;
5616             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5617               name
5618         | RStructList (n, _) ->
5619             pr "  struct guestfs_%s_ret ret;\n" name;
5620             pr "  ret.%s = *r;\n" n;
5621             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5622               name;
5623             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5624               name
5625         | RBufferOut n ->
5626             pr "  struct guestfs_%s_ret ret;\n" name;
5627             pr "  ret.%s.%s_val = r;\n" n n;
5628             pr "  ret.%s.%s_len = size;\n" n n;
5629             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5630               name;
5631             pr "  free (r);\n"
5632       );
5633
5634       (* Free the args. *)
5635       (match snd style with
5636        | [] ->
5637            pr "done: ;\n";
5638        | _ ->
5639            pr "done:\n";
5640            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5641              name
5642       );
5643
5644       pr "}\n\n";
5645   ) daemon_functions;
5646
5647   (* Dispatch function. *)
5648   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5649   pr "{\n";
5650   pr "  switch (proc_nr) {\n";
5651
5652   List.iter (
5653     fun (name, style, _, _, _, _, _) ->
5654       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5655       pr "      %s_stub (xdr_in);\n" name;
5656       pr "      break;\n"
5657   ) daemon_functions;
5658
5659   pr "    default:\n";
5660   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";
5661   pr "  }\n";
5662   pr "}\n";
5663   pr "\n";
5664
5665   (* LVM columns and tokenization functions. *)
5666   (* XXX This generates crap code.  We should rethink how we
5667    * do this parsing.
5668    *)
5669   List.iter (
5670     function
5671     | typ, cols ->
5672         pr "static const char *lvm_%s_cols = \"%s\";\n"
5673           typ (String.concat "," (List.map fst cols));
5674         pr "\n";
5675
5676         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5677         pr "{\n";
5678         pr "  char *tok, *p, *next;\n";
5679         pr "  int i, j;\n";
5680         pr "\n";
5681         (*
5682           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5683           pr "\n";
5684         *)
5685         pr "  if (!str) {\n";
5686         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5687         pr "    return -1;\n";
5688         pr "  }\n";
5689         pr "  if (!*str || c_isspace (*str)) {\n";
5690         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5691         pr "    return -1;\n";
5692         pr "  }\n";
5693         pr "  tok = str;\n";
5694         List.iter (
5695           fun (name, coltype) ->
5696             pr "  if (!tok) {\n";
5697             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5698             pr "    return -1;\n";
5699             pr "  }\n";
5700             pr "  p = strchrnul (tok, ',');\n";
5701             pr "  if (*p) next = p+1; else next = NULL;\n";
5702             pr "  *p = '\\0';\n";
5703             (match coltype with
5704              | FString ->
5705                  pr "  r->%s = strdup (tok);\n" name;
5706                  pr "  if (r->%s == NULL) {\n" name;
5707                  pr "    perror (\"strdup\");\n";
5708                  pr "    return -1;\n";
5709                  pr "  }\n"
5710              | FUUID ->
5711                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5712                  pr "    if (tok[j] == '\\0') {\n";
5713                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5714                  pr "      return -1;\n";
5715                  pr "    } else if (tok[j] != '-')\n";
5716                  pr "      r->%s[i++] = tok[j];\n" name;
5717                  pr "  }\n";
5718              | FBytes ->
5719                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5720                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5721                  pr "    return -1;\n";
5722                  pr "  }\n";
5723              | FInt64 ->
5724                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5725                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5726                  pr "    return -1;\n";
5727                  pr "  }\n";
5728              | FOptPercent ->
5729                  pr "  if (tok[0] == '\\0')\n";
5730                  pr "    r->%s = -1;\n" name;
5731                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5732                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5733                  pr "    return -1;\n";
5734                  pr "  }\n";
5735              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5736                  assert false (* can never be an LVM column *)
5737             );
5738             pr "  tok = next;\n";
5739         ) cols;
5740
5741         pr "  if (tok != NULL) {\n";
5742         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5743         pr "    return -1;\n";
5744         pr "  }\n";
5745         pr "  return 0;\n";
5746         pr "}\n";
5747         pr "\n";
5748
5749         pr "guestfs_int_lvm_%s_list *\n" typ;
5750         pr "parse_command_line_%ss (void)\n" typ;
5751         pr "{\n";
5752         pr "  char *out, *err;\n";
5753         pr "  char *p, *pend;\n";
5754         pr "  int r, i;\n";
5755         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5756         pr "  void *newp;\n";
5757         pr "\n";
5758         pr "  ret = malloc (sizeof *ret);\n";
5759         pr "  if (!ret) {\n";
5760         pr "    reply_with_perror (\"malloc\");\n";
5761         pr "    return NULL;\n";
5762         pr "  }\n";
5763         pr "\n";
5764         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5765         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5766         pr "\n";
5767         pr "  r = command (&out, &err,\n";
5768         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5769         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5770         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5771         pr "  if (r == -1) {\n";
5772         pr "    reply_with_error (\"%%s\", err);\n";
5773         pr "    free (out);\n";
5774         pr "    free (err);\n";
5775         pr "    free (ret);\n";
5776         pr "    return NULL;\n";
5777         pr "  }\n";
5778         pr "\n";
5779         pr "  free (err);\n";
5780         pr "\n";
5781         pr "  /* Tokenize each line of the output. */\n";
5782         pr "  p = out;\n";
5783         pr "  i = 0;\n";
5784         pr "  while (p) {\n";
5785         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5786         pr "    if (pend) {\n";
5787         pr "      *pend = '\\0';\n";
5788         pr "      pend++;\n";
5789         pr "    }\n";
5790         pr "\n";
5791         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5792         pr "      p++;\n";
5793         pr "\n";
5794         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5795         pr "      p = pend;\n";
5796         pr "      continue;\n";
5797         pr "    }\n";
5798         pr "\n";
5799         pr "    /* Allocate some space to store this next entry. */\n";
5800         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5801         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5802         pr "    if (newp == NULL) {\n";
5803         pr "      reply_with_perror (\"realloc\");\n";
5804         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5805         pr "      free (ret);\n";
5806         pr "      free (out);\n";
5807         pr "      return NULL;\n";
5808         pr "    }\n";
5809         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5810         pr "\n";
5811         pr "    /* Tokenize the next entry. */\n";
5812         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5813         pr "    if (r == -1) {\n";
5814         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5815         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5816         pr "      free (ret);\n";
5817         pr "      free (out);\n";
5818         pr "      return NULL;\n";
5819         pr "    }\n";
5820         pr "\n";
5821         pr "    ++i;\n";
5822         pr "    p = pend;\n";
5823         pr "  }\n";
5824         pr "\n";
5825         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5826         pr "\n";
5827         pr "  free (out);\n";
5828         pr "  return ret;\n";
5829         pr "}\n"
5830
5831   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5832
5833 (* Generate a list of function names, for debugging in the daemon.. *)
5834 and generate_daemon_names () =
5835   generate_header CStyle GPLv2;
5836
5837   pr "#include <config.h>\n";
5838   pr "\n";
5839   pr "#include \"daemon.h\"\n";
5840   pr "\n";
5841
5842   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5843   pr "const char *function_names[] = {\n";
5844   List.iter (
5845     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5846   ) daemon_functions;
5847   pr "};\n";
5848
5849 (* Generate the tests. *)
5850 and generate_tests () =
5851   generate_header CStyle GPLv2;
5852
5853   pr "\
5854 #include <stdio.h>
5855 #include <stdlib.h>
5856 #include <string.h>
5857 #include <unistd.h>
5858 #include <sys/types.h>
5859 #include <fcntl.h>
5860
5861 #include \"guestfs.h\"
5862 #include \"guestfs-internal.h\"
5863
5864 static guestfs_h *g;
5865 static int suppress_error = 0;
5866
5867 static void print_error (guestfs_h *g, void *data, const char *msg)
5868 {
5869   if (!suppress_error)
5870     fprintf (stderr, \"%%s\\n\", msg);
5871 }
5872
5873 /* FIXME: nearly identical code appears in fish.c */
5874 static void print_strings (char *const *argv)
5875 {
5876   int argc;
5877
5878   for (argc = 0; argv[argc] != NULL; ++argc)
5879     printf (\"\\t%%s\\n\", argv[argc]);
5880 }
5881
5882 /*
5883 static void print_table (char const *const *argv)
5884 {
5885   int i;
5886
5887   for (i = 0; argv[i] != NULL; i += 2)
5888     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5889 }
5890 */
5891
5892 ";
5893
5894   (* Generate a list of commands which are not tested anywhere. *)
5895   pr "static void no_test_warnings (void)\n";
5896   pr "{\n";
5897
5898   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5899   List.iter (
5900     fun (_, _, _, _, tests, _, _) ->
5901       let tests = filter_map (
5902         function
5903         | (_, (Always|If _|Unless _), test) -> Some test
5904         | (_, Disabled, _) -> None
5905       ) tests in
5906       let seq = List.concat (List.map seq_of_test tests) in
5907       let cmds_tested = List.map List.hd seq in
5908       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5909   ) all_functions;
5910
5911   List.iter (
5912     fun (name, _, _, _, _, _, _) ->
5913       if not (Hashtbl.mem hash name) then
5914         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5915   ) all_functions;
5916
5917   pr "}\n";
5918   pr "\n";
5919
5920   (* Generate the actual tests.  Note that we generate the tests
5921    * in reverse order, deliberately, so that (in general) the
5922    * newest tests run first.  This makes it quicker and easier to
5923    * debug them.
5924    *)
5925   let test_names =
5926     List.map (
5927       fun (name, _, _, _, tests, _, _) ->
5928         mapi (generate_one_test name) tests
5929     ) (List.rev all_functions) in
5930   let test_names = List.concat test_names in
5931   let nr_tests = List.length test_names in
5932
5933   pr "\
5934 int main (int argc, char *argv[])
5935 {
5936   char c = 0;
5937   unsigned long int n_failed = 0;
5938   const char *filename;
5939   int fd;
5940   int nr_tests, test_num = 0;
5941
5942   setbuf (stdout, NULL);
5943
5944   no_test_warnings ();
5945
5946   g = guestfs_create ();
5947   if (g == NULL) {
5948     printf (\"guestfs_create FAILED\\n\");
5949     exit (1);
5950   }
5951
5952   guestfs_set_error_handler (g, print_error, NULL);
5953
5954   guestfs_set_path (g, \"../appliance\");
5955
5956   filename = \"test1.img\";
5957   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5958   if (fd == -1) {
5959     perror (filename);
5960     exit (1);
5961   }
5962   if (lseek (fd, %d, SEEK_SET) == -1) {
5963     perror (\"lseek\");
5964     close (fd);
5965     unlink (filename);
5966     exit (1);
5967   }
5968   if (write (fd, &c, 1) == -1) {
5969     perror (\"write\");
5970     close (fd);
5971     unlink (filename);
5972     exit (1);
5973   }
5974   if (close (fd) == -1) {
5975     perror (filename);
5976     unlink (filename);
5977     exit (1);
5978   }
5979   if (guestfs_add_drive (g, filename) == -1) {
5980     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5981     exit (1);
5982   }
5983
5984   filename = \"test2.img\";
5985   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5986   if (fd == -1) {
5987     perror (filename);
5988     exit (1);
5989   }
5990   if (lseek (fd, %d, SEEK_SET) == -1) {
5991     perror (\"lseek\");
5992     close (fd);
5993     unlink (filename);
5994     exit (1);
5995   }
5996   if (write (fd, &c, 1) == -1) {
5997     perror (\"write\");
5998     close (fd);
5999     unlink (filename);
6000     exit (1);
6001   }
6002   if (close (fd) == -1) {
6003     perror (filename);
6004     unlink (filename);
6005     exit (1);
6006   }
6007   if (guestfs_add_drive (g, filename) == -1) {
6008     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6009     exit (1);
6010   }
6011
6012   filename = \"test3.img\";
6013   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6014   if (fd == -1) {
6015     perror (filename);
6016     exit (1);
6017   }
6018   if (lseek (fd, %d, SEEK_SET) == -1) {
6019     perror (\"lseek\");
6020     close (fd);
6021     unlink (filename);
6022     exit (1);
6023   }
6024   if (write (fd, &c, 1) == -1) {
6025     perror (\"write\");
6026     close (fd);
6027     unlink (filename);
6028     exit (1);
6029   }
6030   if (close (fd) == -1) {
6031     perror (filename);
6032     unlink (filename);
6033     exit (1);
6034   }
6035   if (guestfs_add_drive (g, filename) == -1) {
6036     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6037     exit (1);
6038   }
6039
6040   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6041     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6042     exit (1);
6043   }
6044
6045   if (guestfs_launch (g) == -1) {
6046     printf (\"guestfs_launch FAILED\\n\");
6047     exit (1);
6048   }
6049
6050   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6051   alarm (600);
6052
6053   /* Cancel previous alarm. */
6054   alarm (0);
6055
6056   nr_tests = %d;
6057
6058 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6059
6060   iteri (
6061     fun i test_name ->
6062       pr "  test_num++;\n";
6063       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6064       pr "  if (%s () == -1) {\n" test_name;
6065       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6066       pr "    n_failed++;\n";
6067       pr "  }\n";
6068   ) test_names;
6069   pr "\n";
6070
6071   pr "  guestfs_close (g);\n";
6072   pr "  unlink (\"test1.img\");\n";
6073   pr "  unlink (\"test2.img\");\n";
6074   pr "  unlink (\"test3.img\");\n";
6075   pr "\n";
6076
6077   pr "  if (n_failed > 0) {\n";
6078   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6079   pr "    exit (1);\n";
6080   pr "  }\n";
6081   pr "\n";
6082
6083   pr "  exit (0);\n";
6084   pr "}\n"
6085
6086 and generate_one_test name i (init, prereq, test) =
6087   let test_name = sprintf "test_%s_%d" name i in
6088
6089   pr "\
6090 static int %s_skip (void)
6091 {
6092   const char *str;
6093
6094   str = getenv (\"TEST_ONLY\");
6095   if (str)
6096     return strstr (str, \"%s\") == NULL;
6097   str = getenv (\"SKIP_%s\");
6098   if (str && STREQ (str, \"1\")) return 1;
6099   str = getenv (\"SKIP_TEST_%s\");
6100   if (str && STREQ (str, \"1\")) return 1;
6101   return 0;
6102 }
6103
6104 " test_name name (String.uppercase test_name) (String.uppercase name);
6105
6106   (match prereq with
6107    | Disabled | Always -> ()
6108    | If code | Unless code ->
6109        pr "static int %s_prereq (void)\n" test_name;
6110        pr "{\n";
6111        pr "  %s\n" code;
6112        pr "}\n";
6113        pr "\n";
6114   );
6115
6116   pr "\
6117 static int %s (void)
6118 {
6119   if (%s_skip ()) {
6120     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6121     return 0;
6122   }
6123
6124 " test_name test_name test_name;
6125
6126   (match prereq with
6127    | Disabled ->
6128        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6129    | If _ ->
6130        pr "  if (! %s_prereq ()) {\n" test_name;
6131        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6132        pr "    return 0;\n";
6133        pr "  }\n";
6134        pr "\n";
6135        generate_one_test_body name i test_name init test;
6136    | Unless _ ->
6137        pr "  if (%s_prereq ()) {\n" test_name;
6138        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6139        pr "    return 0;\n";
6140        pr "  }\n";
6141        pr "\n";
6142        generate_one_test_body name i test_name init test;
6143    | Always ->
6144        generate_one_test_body name i test_name init test
6145   );
6146
6147   pr "  return 0;\n";
6148   pr "}\n";
6149   pr "\n";
6150   test_name
6151
6152 and generate_one_test_body name i test_name init test =
6153   (match init with
6154    | InitNone (* XXX at some point, InitNone and InitEmpty became
6155                * folded together as the same thing.  Really we should
6156                * make InitNone do nothing at all, but the tests may
6157                * need to be checked to make sure this is OK.
6158                *)
6159    | InitEmpty ->
6160        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6161        List.iter (generate_test_command_call test_name)
6162          [["blockdev_setrw"; "/dev/sda"];
6163           ["umount_all"];
6164           ["lvm_remove_all"]]
6165    | InitPartition ->
6166        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6167        List.iter (generate_test_command_call test_name)
6168          [["blockdev_setrw"; "/dev/sda"];
6169           ["umount_all"];
6170           ["lvm_remove_all"];
6171           ["part_disk"; "/dev/sda"; "mbr"]]
6172    | InitBasicFS ->
6173        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6174        List.iter (generate_test_command_call test_name)
6175          [["blockdev_setrw"; "/dev/sda"];
6176           ["umount_all"];
6177           ["lvm_remove_all"];
6178           ["part_disk"; "/dev/sda"; "mbr"];
6179           ["mkfs"; "ext2"; "/dev/sda1"];
6180           ["mount"; "/dev/sda1"; "/"]]
6181    | InitBasicFSonLVM ->
6182        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6183          test_name;
6184        List.iter (generate_test_command_call test_name)
6185          [["blockdev_setrw"; "/dev/sda"];
6186           ["umount_all"];
6187           ["lvm_remove_all"];
6188           ["part_disk"; "/dev/sda"; "mbr"];
6189           ["pvcreate"; "/dev/sda1"];
6190           ["vgcreate"; "VG"; "/dev/sda1"];
6191           ["lvcreate"; "LV"; "VG"; "8"];
6192           ["mkfs"; "ext2"; "/dev/VG/LV"];
6193           ["mount"; "/dev/VG/LV"; "/"]]
6194    | InitISOFS ->
6195        pr "  /* InitISOFS for %s */\n" test_name;
6196        List.iter (generate_test_command_call test_name)
6197          [["blockdev_setrw"; "/dev/sda"];
6198           ["umount_all"];
6199           ["lvm_remove_all"];
6200           ["mount_ro"; "/dev/sdd"; "/"]]
6201   );
6202
6203   let get_seq_last = function
6204     | [] ->
6205         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6206           test_name
6207     | seq ->
6208         let seq = List.rev seq in
6209         List.rev (List.tl seq), List.hd seq
6210   in
6211
6212   match test with
6213   | TestRun seq ->
6214       pr "  /* TestRun for %s (%d) */\n" name i;
6215       List.iter (generate_test_command_call test_name) seq
6216   | TestOutput (seq, expected) ->
6217       pr "  /* TestOutput for %s (%d) */\n" name i;
6218       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6219       let seq, last = get_seq_last seq in
6220       let test () =
6221         pr "    if (STRNEQ (r, expected)) {\n";
6222         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6223         pr "      return -1;\n";
6224         pr "    }\n"
6225       in
6226       List.iter (generate_test_command_call test_name) seq;
6227       generate_test_command_call ~test test_name last
6228   | TestOutputList (seq, expected) ->
6229       pr "  /* TestOutputList for %s (%d) */\n" name i;
6230       let seq, last = get_seq_last seq in
6231       let test () =
6232         iteri (
6233           fun i str ->
6234             pr "    if (!r[%d]) {\n" i;
6235             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6236             pr "      print_strings (r);\n";
6237             pr "      return -1;\n";
6238             pr "    }\n";
6239             pr "    {\n";
6240             pr "      const char *expected = \"%s\";\n" (c_quote str);
6241             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6242             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6243             pr "        return -1;\n";
6244             pr "      }\n";
6245             pr "    }\n"
6246         ) expected;
6247         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6248         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6249           test_name;
6250         pr "      print_strings (r);\n";
6251         pr "      return -1;\n";
6252         pr "    }\n"
6253       in
6254       List.iter (generate_test_command_call test_name) seq;
6255       generate_test_command_call ~test test_name last
6256   | TestOutputListOfDevices (seq, expected) ->
6257       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6258       let seq, last = get_seq_last seq in
6259       let test () =
6260         iteri (
6261           fun i str ->
6262             pr "    if (!r[%d]) {\n" i;
6263             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6264             pr "      print_strings (r);\n";
6265             pr "      return -1;\n";
6266             pr "    }\n";
6267             pr "    {\n";
6268             pr "      const char *expected = \"%s\";\n" (c_quote str);
6269             pr "      r[%d][5] = 's';\n" i;
6270             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6271             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6272             pr "        return -1;\n";
6273             pr "      }\n";
6274             pr "    }\n"
6275         ) expected;
6276         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6277         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6278           test_name;
6279         pr "      print_strings (r);\n";
6280         pr "      return -1;\n";
6281         pr "    }\n"
6282       in
6283       List.iter (generate_test_command_call test_name) seq;
6284       generate_test_command_call ~test test_name last
6285   | TestOutputInt (seq, expected) ->
6286       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6287       let seq, last = get_seq_last seq in
6288       let test () =
6289         pr "    if (r != %d) {\n" expected;
6290         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6291           test_name expected;
6292         pr "               (int) r);\n";
6293         pr "      return -1;\n";
6294         pr "    }\n"
6295       in
6296       List.iter (generate_test_command_call test_name) seq;
6297       generate_test_command_call ~test test_name last
6298   | TestOutputIntOp (seq, op, expected) ->
6299       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6300       let seq, last = get_seq_last seq in
6301       let test () =
6302         pr "    if (! (r %s %d)) {\n" op expected;
6303         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6304           test_name op expected;
6305         pr "               (int) r);\n";
6306         pr "      return -1;\n";
6307         pr "    }\n"
6308       in
6309       List.iter (generate_test_command_call test_name) seq;
6310       generate_test_command_call ~test test_name last
6311   | TestOutputTrue seq ->
6312       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6313       let seq, last = get_seq_last seq in
6314       let test () =
6315         pr "    if (!r) {\n";
6316         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6317           test_name;
6318         pr "      return -1;\n";
6319         pr "    }\n"
6320       in
6321       List.iter (generate_test_command_call test_name) seq;
6322       generate_test_command_call ~test test_name last
6323   | TestOutputFalse seq ->
6324       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6325       let seq, last = get_seq_last seq in
6326       let test () =
6327         pr "    if (r) {\n";
6328         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6329           test_name;
6330         pr "      return -1;\n";
6331         pr "    }\n"
6332       in
6333       List.iter (generate_test_command_call test_name) seq;
6334       generate_test_command_call ~test test_name last
6335   | TestOutputLength (seq, expected) ->
6336       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6337       let seq, last = get_seq_last seq in
6338       let test () =
6339         pr "    int j;\n";
6340         pr "    for (j = 0; j < %d; ++j)\n" expected;
6341         pr "      if (r[j] == NULL) {\n";
6342         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6343           test_name;
6344         pr "        print_strings (r);\n";
6345         pr "        return -1;\n";
6346         pr "      }\n";
6347         pr "    if (r[j] != NULL) {\n";
6348         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6349           test_name;
6350         pr "      print_strings (r);\n";
6351         pr "      return -1;\n";
6352         pr "    }\n"
6353       in
6354       List.iter (generate_test_command_call test_name) seq;
6355       generate_test_command_call ~test test_name last
6356   | TestOutputBuffer (seq, expected) ->
6357       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6358       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6359       let seq, last = get_seq_last seq in
6360       let len = String.length expected in
6361       let test () =
6362         pr "    if (size != %d) {\n" len;
6363         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6364         pr "      return -1;\n";
6365         pr "    }\n";
6366         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6367         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6368         pr "      return -1;\n";
6369         pr "    }\n"
6370       in
6371       List.iter (generate_test_command_call test_name) seq;
6372       generate_test_command_call ~test test_name last
6373   | TestOutputStruct (seq, checks) ->
6374       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6375       let seq, last = get_seq_last seq in
6376       let test () =
6377         List.iter (
6378           function
6379           | CompareWithInt (field, expected) ->
6380               pr "    if (r->%s != %d) {\n" field expected;
6381               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6382                 test_name field expected;
6383               pr "               (int) r->%s);\n" field;
6384               pr "      return -1;\n";
6385               pr "    }\n"
6386           | CompareWithIntOp (field, op, expected) ->
6387               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6388               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6389                 test_name field op expected;
6390               pr "               (int) r->%s);\n" field;
6391               pr "      return -1;\n";
6392               pr "    }\n"
6393           | CompareWithString (field, expected) ->
6394               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6395               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6396                 test_name field expected;
6397               pr "               r->%s);\n" field;
6398               pr "      return -1;\n";
6399               pr "    }\n"
6400           | CompareFieldsIntEq (field1, field2) ->
6401               pr "    if (r->%s != r->%s) {\n" field1 field2;
6402               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6403                 test_name field1 field2;
6404               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6405               pr "      return -1;\n";
6406               pr "    }\n"
6407           | CompareFieldsStrEq (field1, field2) ->
6408               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6409               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6410                 test_name field1 field2;
6411               pr "               r->%s, r->%s);\n" field1 field2;
6412               pr "      return -1;\n";
6413               pr "    }\n"
6414         ) checks
6415       in
6416       List.iter (generate_test_command_call test_name) seq;
6417       generate_test_command_call ~test test_name last
6418   | TestLastFail seq ->
6419       pr "  /* TestLastFail for %s (%d) */\n" name i;
6420       let seq, last = get_seq_last seq in
6421       List.iter (generate_test_command_call test_name) seq;
6422       generate_test_command_call test_name ~expect_error:true last
6423
6424 (* Generate the code to run a command, leaving the result in 'r'.
6425  * If you expect to get an error then you should set expect_error:true.
6426  *)
6427 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6428   match cmd with
6429   | [] -> assert false
6430   | name :: args ->
6431       (* Look up the command to find out what args/ret it has. *)
6432       let style =
6433         try
6434           let _, style, _, _, _, _, _ =
6435             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6436           style
6437         with Not_found ->
6438           failwithf "%s: in test, command %s was not found" test_name name in
6439
6440       if List.length (snd style) <> List.length args then
6441         failwithf "%s: in test, wrong number of args given to %s"
6442           test_name name;
6443
6444       pr "  {\n";
6445
6446       List.iter (
6447         function
6448         | OptString n, "NULL" -> ()
6449         | Pathname n, arg
6450         | Device n, arg
6451         | Dev_or_Path n, arg
6452         | String n, arg
6453         | OptString n, arg ->
6454             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6455         | Int _, _
6456         | Int64 _, _
6457         | Bool _, _
6458         | FileIn _, _ | FileOut _, _ -> ()
6459         | StringList n, arg | DeviceList n, arg ->
6460             let strs = string_split " " arg in
6461             iteri (
6462               fun i str ->
6463                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6464             ) strs;
6465             pr "    const char *const %s[] = {\n" n;
6466             iteri (
6467               fun i _ -> pr "      %s_%d,\n" n i
6468             ) strs;
6469             pr "      NULL\n";
6470             pr "    };\n";
6471       ) (List.combine (snd style) args);
6472
6473       let error_code =
6474         match fst style with
6475         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6476         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6477         | RConstString _ | RConstOptString _ ->
6478             pr "    const char *r;\n"; "NULL"
6479         | RString _ -> pr "    char *r;\n"; "NULL"
6480         | RStringList _ | RHashtable _ ->
6481             pr "    char **r;\n";
6482             pr "    int i;\n";
6483             "NULL"
6484         | RStruct (_, typ) ->
6485             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6486         | RStructList (_, typ) ->
6487             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6488         | RBufferOut _ ->
6489             pr "    char *r;\n";
6490             pr "    size_t size;\n";
6491             "NULL" in
6492
6493       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6494       pr "    r = guestfs_%s (g" name;
6495
6496       (* Generate the parameters. *)
6497       List.iter (
6498         function
6499         | OptString _, "NULL" -> pr ", NULL"
6500         | Pathname n, _
6501         | Device n, _ | Dev_or_Path n, _
6502         | String n, _
6503         | OptString n, _ ->
6504             pr ", %s" n
6505         | FileIn _, arg | FileOut _, arg ->
6506             pr ", \"%s\"" (c_quote arg)
6507         | StringList n, _ | DeviceList n, _ ->
6508             pr ", (char **) %s" n
6509         | Int _, arg ->
6510             let i =
6511               try int_of_string arg
6512               with Failure "int_of_string" ->
6513                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6514             pr ", %d" i
6515         | Int64 _, arg ->
6516             let i =
6517               try Int64.of_string arg
6518               with Failure "int_of_string" ->
6519                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6520             pr ", %Ld" i
6521         | Bool _, arg ->
6522             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6523       ) (List.combine (snd style) args);
6524
6525       (match fst style with
6526        | RBufferOut _ -> pr ", &size"
6527        | _ -> ()
6528       );
6529
6530       pr ");\n";
6531
6532       if not expect_error then
6533         pr "    if (r == %s)\n" error_code
6534       else
6535         pr "    if (r != %s)\n" error_code;
6536       pr "      return -1;\n";
6537
6538       (* Insert the test code. *)
6539       (match test with
6540        | None -> ()
6541        | Some f -> f ()
6542       );
6543
6544       (match fst style with
6545        | RErr | RInt _ | RInt64 _ | RBool _
6546        | RConstString _ | RConstOptString _ -> ()
6547        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6548        | RStringList _ | RHashtable _ ->
6549            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6550            pr "      free (r[i]);\n";
6551            pr "    free (r);\n"
6552        | RStruct (_, typ) ->
6553            pr "    guestfs_free_%s (r);\n" typ
6554        | RStructList (_, typ) ->
6555            pr "    guestfs_free_%s_list (r);\n" typ
6556       );
6557
6558       pr "  }\n"
6559
6560 and c_quote str =
6561   let str = replace_str str "\r" "\\r" in
6562   let str = replace_str str "\n" "\\n" in
6563   let str = replace_str str "\t" "\\t" in
6564   let str = replace_str str "\000" "\\0" in
6565   str
6566
6567 (* Generate a lot of different functions for guestfish. *)
6568 and generate_fish_cmds () =
6569   generate_header CStyle GPLv2;
6570
6571   let all_functions =
6572     List.filter (
6573       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6574     ) all_functions in
6575   let all_functions_sorted =
6576     List.filter (
6577       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6578     ) all_functions_sorted in
6579
6580   pr "#include <stdio.h>\n";
6581   pr "#include <stdlib.h>\n";
6582   pr "#include <string.h>\n";
6583   pr "#include <inttypes.h>\n";
6584   pr "\n";
6585   pr "#include <guestfs.h>\n";
6586   pr "#include \"c-ctype.h\"\n";
6587   pr "#include \"fish.h\"\n";
6588   pr "\n";
6589
6590   (* list_commands function, which implements guestfish -h *)
6591   pr "void list_commands (void)\n";
6592   pr "{\n";
6593   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6594   pr "  list_builtin_commands ();\n";
6595   List.iter (
6596     fun (name, _, _, flags, _, shortdesc, _) ->
6597       let name = replace_char name '_' '-' in
6598       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6599         name shortdesc
6600   ) all_functions_sorted;
6601   pr "  printf (\"    %%s\\n\",";
6602   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6603   pr "}\n";
6604   pr "\n";
6605
6606   (* display_command function, which implements guestfish -h cmd *)
6607   pr "void display_command (const char *cmd)\n";
6608   pr "{\n";
6609   List.iter (
6610     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6611       let name2 = replace_char name '_' '-' in
6612       let alias =
6613         try find_map (function FishAlias n -> Some n | _ -> None) flags
6614         with Not_found -> name in
6615       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6616       let synopsis =
6617         match snd style with
6618         | [] -> name2
6619         | args ->
6620             sprintf "%s %s"
6621               name2 (String.concat " " (List.map name_of_argt args)) in
6622
6623       let warnings =
6624         if List.mem ProtocolLimitWarning flags then
6625           ("\n\n" ^ protocol_limit_warning)
6626         else "" in
6627
6628       (* For DangerWillRobinson commands, we should probably have
6629        * guestfish prompt before allowing you to use them (especially
6630        * in interactive mode). XXX
6631        *)
6632       let warnings =
6633         warnings ^
6634           if List.mem DangerWillRobinson flags then
6635             ("\n\n" ^ danger_will_robinson)
6636           else "" in
6637
6638       let warnings =
6639         warnings ^
6640           match deprecation_notice flags with
6641           | None -> ""
6642           | Some txt -> "\n\n" ^ txt in
6643
6644       let describe_alias =
6645         if name <> alias then
6646           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6647         else "" in
6648
6649       pr "  if (";
6650       pr "STRCASEEQ (cmd, \"%s\")" name;
6651       if name <> name2 then
6652         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6653       if name <> alias then
6654         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6655       pr ")\n";
6656       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6657         name2 shortdesc
6658         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6659          "=head1 DESCRIPTION\n\n" ^
6660          longdesc ^ warnings ^ describe_alias);
6661       pr "  else\n"
6662   ) all_functions;
6663   pr "    display_builtin_command (cmd);\n";
6664   pr "}\n";
6665   pr "\n";
6666
6667   let emit_print_list_function typ =
6668     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6669       typ typ typ;
6670     pr "{\n";
6671     pr "  unsigned int i;\n";
6672     pr "\n";
6673     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6674     pr "    printf (\"[%%d] = {\\n\", i);\n";
6675     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6676     pr "    printf (\"}\\n\");\n";
6677     pr "  }\n";
6678     pr "}\n";
6679     pr "\n";
6680   in
6681
6682   (* print_* functions *)
6683   List.iter (
6684     fun (typ, cols) ->
6685       let needs_i =
6686         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6687
6688       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6689       pr "{\n";
6690       if needs_i then (
6691         pr "  unsigned int i;\n";
6692         pr "\n"
6693       );
6694       List.iter (
6695         function
6696         | name, FString ->
6697             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6698         | name, FUUID ->
6699             pr "  printf (\"%%s%s: \", indent);\n" name;
6700             pr "  for (i = 0; i < 32; ++i)\n";
6701             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6702             pr "  printf (\"\\n\");\n"
6703         | name, FBuffer ->
6704             pr "  printf (\"%%s%s: \", indent);\n" name;
6705             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6706             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6707             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6708             pr "    else\n";
6709             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6710             pr "  printf (\"\\n\");\n"
6711         | name, (FUInt64|FBytes) ->
6712             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6713               name typ name
6714         | name, FInt64 ->
6715             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6716               name typ name
6717         | name, FUInt32 ->
6718             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6719               name typ name
6720         | name, FInt32 ->
6721             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6722               name typ name
6723         | name, FChar ->
6724             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6725               name typ name
6726         | name, FOptPercent ->
6727             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6728               typ name name typ name;
6729             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6730       ) cols;
6731       pr "}\n";
6732       pr "\n";
6733   ) structs;
6734
6735   (* Emit a print_TYPE_list function definition only if that function is used. *)
6736   List.iter (
6737     function
6738     | typ, (RStructListOnly | RStructAndList) ->
6739         (* generate the function for typ *)
6740         emit_print_list_function typ
6741     | typ, _ -> () (* empty *)
6742   ) (rstructs_used_by all_functions);
6743
6744   (* Emit a print_TYPE function definition only if that function is used. *)
6745   List.iter (
6746     function
6747     | typ, (RStructOnly | RStructAndList) ->
6748         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6749         pr "{\n";
6750         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6751         pr "}\n";
6752         pr "\n";
6753     | typ, _ -> () (* empty *)
6754   ) (rstructs_used_by all_functions);
6755
6756   (* run_<action> actions *)
6757   List.iter (
6758     fun (name, style, _, flags, _, _, _) ->
6759       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6760       pr "{\n";
6761       (match fst style with
6762        | RErr
6763        | RInt _
6764        | RBool _ -> pr "  int r;\n"
6765        | RInt64 _ -> pr "  int64_t r;\n"
6766        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6767        | RString _ -> pr "  char *r;\n"
6768        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6769        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6770        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6771        | RBufferOut _ ->
6772            pr "  char *r;\n";
6773            pr "  size_t size;\n";
6774       );
6775       List.iter (
6776         function
6777         | Device n
6778         | String n
6779         | OptString n
6780         | FileIn n
6781         | FileOut n -> pr "  const char *%s;\n" n
6782         | Pathname n
6783         | Dev_or_Path n -> pr "  char *%s;\n" n
6784         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6785         | Bool n -> pr "  int %s;\n" n
6786         | Int n -> pr "  int %s;\n" n
6787         | Int64 n -> pr "  int64_t %s;\n" n
6788       ) (snd style);
6789
6790       (* Check and convert parameters. *)
6791       let argc_expected = List.length (snd style) in
6792       pr "  if (argc != %d) {\n" argc_expected;
6793       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6794         argc_expected;
6795       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6796       pr "    return -1;\n";
6797       pr "  }\n";
6798       iteri (
6799         fun i ->
6800           function
6801           | Device name
6802           | String name ->
6803               pr "  %s = argv[%d];\n" name i
6804           | Pathname name
6805           | Dev_or_Path name ->
6806               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6807               pr "  if (%s == NULL) return -1;\n" name
6808           | OptString name ->
6809               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6810                 name i i
6811           | FileIn name ->
6812               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6813                 name i i
6814           | FileOut name ->
6815               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6816                 name i i
6817           | StringList name | DeviceList name ->
6818               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6819               pr "  if (%s == NULL) return -1;\n" name;
6820           | Bool name ->
6821               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6822           | Int name ->
6823               pr "  %s = atoi (argv[%d]);\n" name i
6824           | Int64 name ->
6825               pr "  %s = atoll (argv[%d]);\n" name i
6826       ) (snd style);
6827
6828       (* Call C API function. *)
6829       let fn =
6830         try find_map (function FishAction n -> Some n | _ -> None) flags
6831         with Not_found -> sprintf "guestfs_%s" name in
6832       pr "  r = %s " fn;
6833       generate_c_call_args ~handle:"g" style;
6834       pr ";\n";
6835
6836       List.iter (
6837         function
6838         | Device name | String name
6839         | OptString name | FileIn name | FileOut name | Bool name
6840         | Int name | Int64 name -> ()
6841         | Pathname name | Dev_or_Path name ->
6842             pr "  free (%s);\n" name
6843         | StringList name | DeviceList name ->
6844             pr "  free_strings (%s);\n" name
6845       ) (snd style);
6846
6847       (* Check return value for errors and display command results. *)
6848       (match fst style with
6849        | RErr -> pr "  return r;\n"
6850        | RInt _ ->
6851            pr "  if (r == -1) return -1;\n";
6852            pr "  printf (\"%%d\\n\", r);\n";
6853            pr "  return 0;\n"
6854        | RInt64 _ ->
6855            pr "  if (r == -1) return -1;\n";
6856            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6857            pr "  return 0;\n"
6858        | RBool _ ->
6859            pr "  if (r == -1) return -1;\n";
6860            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6861            pr "  return 0;\n"
6862        | RConstString _ ->
6863            pr "  if (r == NULL) return -1;\n";
6864            pr "  printf (\"%%s\\n\", r);\n";
6865            pr "  return 0;\n"
6866        | RConstOptString _ ->
6867            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6868            pr "  return 0;\n"
6869        | RString _ ->
6870            pr "  if (r == NULL) return -1;\n";
6871            pr "  printf (\"%%s\\n\", r);\n";
6872            pr "  free (r);\n";
6873            pr "  return 0;\n"
6874        | RStringList _ ->
6875            pr "  if (r == NULL) return -1;\n";
6876            pr "  print_strings (r);\n";
6877            pr "  free_strings (r);\n";
6878            pr "  return 0;\n"
6879        | RStruct (_, typ) ->
6880            pr "  if (r == NULL) return -1;\n";
6881            pr "  print_%s (r);\n" typ;
6882            pr "  guestfs_free_%s (r);\n" typ;
6883            pr "  return 0;\n"
6884        | RStructList (_, typ) ->
6885            pr "  if (r == NULL) return -1;\n";
6886            pr "  print_%s_list (r);\n" typ;
6887            pr "  guestfs_free_%s_list (r);\n" typ;
6888            pr "  return 0;\n"
6889        | RHashtable _ ->
6890            pr "  if (r == NULL) return -1;\n";
6891            pr "  print_table (r);\n";
6892            pr "  free_strings (r);\n";
6893            pr "  return 0;\n"
6894        | RBufferOut _ ->
6895            pr "  if (r == NULL) return -1;\n";
6896            pr "  fwrite (r, size, 1, stdout);\n";
6897            pr "  free (r);\n";
6898            pr "  return 0;\n"
6899       );
6900       pr "}\n";
6901       pr "\n"
6902   ) all_functions;
6903
6904   (* run_action function *)
6905   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6906   pr "{\n";
6907   List.iter (
6908     fun (name, _, _, flags, _, _, _) ->
6909       let name2 = replace_char name '_' '-' in
6910       let alias =
6911         try find_map (function FishAlias n -> Some n | _ -> None) flags
6912         with Not_found -> name in
6913       pr "  if (";
6914       pr "STRCASEEQ (cmd, \"%s\")" name;
6915       if name <> name2 then
6916         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6917       if name <> alias then
6918         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6919       pr ")\n";
6920       pr "    return run_%s (cmd, argc, argv);\n" name;
6921       pr "  else\n";
6922   ) all_functions;
6923   pr "    {\n";
6924   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6925   pr "      return -1;\n";
6926   pr "    }\n";
6927   pr "  return 0;\n";
6928   pr "}\n";
6929   pr "\n"
6930
6931 (* Readline completion for guestfish. *)
6932 and generate_fish_completion () =
6933   generate_header CStyle GPLv2;
6934
6935   let all_functions =
6936     List.filter (
6937       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6938     ) all_functions in
6939
6940   pr "\
6941 #include <config.h>
6942
6943 #include <stdio.h>
6944 #include <stdlib.h>
6945 #include <string.h>
6946
6947 #ifdef HAVE_LIBREADLINE
6948 #include <readline/readline.h>
6949 #endif
6950
6951 #include \"fish.h\"
6952
6953 #ifdef HAVE_LIBREADLINE
6954
6955 static const char *const commands[] = {
6956   BUILTIN_COMMANDS_FOR_COMPLETION,
6957 ";
6958
6959   (* Get the commands, including the aliases.  They don't need to be
6960    * sorted - the generator() function just does a dumb linear search.
6961    *)
6962   let commands =
6963     List.map (
6964       fun (name, _, _, flags, _, _, _) ->
6965         let name2 = replace_char name '_' '-' in
6966         let alias =
6967           try find_map (function FishAlias n -> Some n | _ -> None) flags
6968           with Not_found -> name in
6969
6970         if name <> alias then [name2; alias] else [name2]
6971     ) all_functions in
6972   let commands = List.flatten commands in
6973
6974   List.iter (pr "  \"%s\",\n") commands;
6975
6976   pr "  NULL
6977 };
6978
6979 static char *
6980 generator (const char *text, int state)
6981 {
6982   static int index, len;
6983   const char *name;
6984
6985   if (!state) {
6986     index = 0;
6987     len = strlen (text);
6988   }
6989
6990   rl_attempted_completion_over = 1;
6991
6992   while ((name = commands[index]) != NULL) {
6993     index++;
6994     if (STRCASEEQLEN (name, text, len))
6995       return strdup (name);
6996   }
6997
6998   return NULL;
6999 }
7000
7001 #endif /* HAVE_LIBREADLINE */
7002
7003 char **do_completion (const char *text, int start, int end)
7004 {
7005   char **matches = NULL;
7006
7007 #ifdef HAVE_LIBREADLINE
7008   rl_completion_append_character = ' ';
7009
7010   if (start == 0)
7011     matches = rl_completion_matches (text, generator);
7012   else if (complete_dest_paths)
7013     matches = rl_completion_matches (text, complete_dest_paths_generator);
7014 #endif
7015
7016   return matches;
7017 }
7018 ";
7019
7020 (* Generate the POD documentation for guestfish. *)
7021 and generate_fish_actions_pod () =
7022   let all_functions_sorted =
7023     List.filter (
7024       fun (_, _, _, flags, _, _, _) ->
7025         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7026     ) all_functions_sorted in
7027
7028   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7029
7030   List.iter (
7031     fun (name, style, _, flags, _, _, longdesc) ->
7032       let longdesc =
7033         Str.global_substitute rex (
7034           fun s ->
7035             let sub =
7036               try Str.matched_group 1 s
7037               with Not_found ->
7038                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7039             "C<" ^ replace_char sub '_' '-' ^ ">"
7040         ) longdesc in
7041       let name = replace_char name '_' '-' in
7042       let alias =
7043         try find_map (function FishAlias n -> Some n | _ -> None) flags
7044         with Not_found -> name in
7045
7046       pr "=head2 %s" name;
7047       if name <> alias then
7048         pr " | %s" alias;
7049       pr "\n";
7050       pr "\n";
7051       pr " %s" name;
7052       List.iter (
7053         function
7054         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7055         | OptString n -> pr " %s" n
7056         | StringList n | DeviceList n -> pr " '%s ...'" n
7057         | Bool _ -> pr " true|false"
7058         | Int n -> pr " %s" n
7059         | Int64 n -> pr " %s" n
7060         | FileIn n | FileOut n -> pr " (%s|-)" n
7061       ) (snd style);
7062       pr "\n";
7063       pr "\n";
7064       pr "%s\n\n" longdesc;
7065
7066       if List.exists (function FileIn _ | FileOut _ -> true
7067                       | _ -> false) (snd style) then
7068         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7069
7070       if List.mem ProtocolLimitWarning flags then
7071         pr "%s\n\n" protocol_limit_warning;
7072
7073       if List.mem DangerWillRobinson flags then
7074         pr "%s\n\n" danger_will_robinson;
7075
7076       match deprecation_notice flags with
7077       | None -> ()
7078       | Some txt -> pr "%s\n\n" txt
7079   ) all_functions_sorted
7080
7081 (* Generate a C function prototype. *)
7082 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7083     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7084     ?(prefix = "")
7085     ?handle name style =
7086   if extern then pr "extern ";
7087   if static then pr "static ";
7088   (match fst style with
7089    | RErr -> pr "int "
7090    | RInt _ -> pr "int "
7091    | RInt64 _ -> pr "int64_t "
7092    | RBool _ -> pr "int "
7093    | RConstString _ | RConstOptString _ -> pr "const char *"
7094    | RString _ | RBufferOut _ -> pr "char *"
7095    | RStringList _ | RHashtable _ -> pr "char **"
7096    | RStruct (_, typ) ->
7097        if not in_daemon then pr "struct guestfs_%s *" typ
7098        else pr "guestfs_int_%s *" typ
7099    | RStructList (_, typ) ->
7100        if not in_daemon then pr "struct guestfs_%s_list *" typ
7101        else pr "guestfs_int_%s_list *" typ
7102   );
7103   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7104   pr "%s%s (" prefix name;
7105   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7106     pr "void"
7107   else (
7108     let comma = ref false in
7109     (match handle with
7110      | None -> ()
7111      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7112     );
7113     let next () =
7114       if !comma then (
7115         if single_line then pr ", " else pr ",\n\t\t"
7116       );
7117       comma := true
7118     in
7119     List.iter (
7120       function
7121       | Pathname n
7122       | Device n | Dev_or_Path n
7123       | String n
7124       | OptString n ->
7125           next ();
7126           pr "const char *%s" n
7127       | StringList n | DeviceList n ->
7128           next ();
7129           pr "char *const *%s" n
7130       | Bool n -> next (); pr "int %s" n
7131       | Int n -> next (); pr "int %s" n
7132       | Int64 n -> next (); pr "int64_t %s" n
7133       | FileIn n
7134       | FileOut n ->
7135           if not in_daemon then (next (); pr "const char *%s" n)
7136     ) (snd style);
7137     if is_RBufferOut then (next (); pr "size_t *size_r");
7138   );
7139   pr ")";
7140   if semicolon then pr ";";
7141   if newline then pr "\n"
7142
7143 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7144 and generate_c_call_args ?handle ?(decl = false) style =
7145   pr "(";
7146   let comma = ref false in
7147   let next () =
7148     if !comma then pr ", ";
7149     comma := true
7150   in
7151   (match handle with
7152    | None -> ()
7153    | Some handle -> pr "%s" handle; comma := true
7154   );
7155   List.iter (
7156     fun arg ->
7157       next ();
7158       pr "%s" (name_of_argt arg)
7159   ) (snd style);
7160   (* For RBufferOut calls, add implicit &size parameter. *)
7161   if not decl then (
7162     match fst style with
7163     | RBufferOut _ ->
7164         next ();
7165         pr "&size"
7166     | _ -> ()
7167   );
7168   pr ")"
7169
7170 (* Generate the OCaml bindings interface. *)
7171 and generate_ocaml_mli () =
7172   generate_header OCamlStyle LGPLv2;
7173
7174   pr "\
7175 (** For API documentation you should refer to the C API
7176     in the guestfs(3) manual page.  The OCaml API uses almost
7177     exactly the same calls. *)
7178
7179 type t
7180 (** A [guestfs_h] handle. *)
7181
7182 exception Error of string
7183 (** This exception is raised when there is an error. *)
7184
7185 exception Handle_closed of string
7186 (** This exception is raised if you use a {!Guestfs.t} handle
7187     after calling {!close} on it.  The string is the name of
7188     the function. *)
7189
7190 val create : unit -> t
7191 (** Create a {!Guestfs.t} handle. *)
7192
7193 val close : t -> unit
7194 (** Close the {!Guestfs.t} handle and free up all resources used
7195     by it immediately.
7196
7197     Handles are closed by the garbage collector when they become
7198     unreferenced, but callers can call this in order to provide
7199     predictable cleanup. *)
7200
7201 ";
7202   generate_ocaml_structure_decls ();
7203
7204   (* The actions. *)
7205   List.iter (
7206     fun (name, style, _, _, _, shortdesc, _) ->
7207       generate_ocaml_prototype name style;
7208       pr "(** %s *)\n" shortdesc;
7209       pr "\n"
7210   ) all_functions_sorted
7211
7212 (* Generate the OCaml bindings implementation. *)
7213 and generate_ocaml_ml () =
7214   generate_header OCamlStyle LGPLv2;
7215
7216   pr "\
7217 type t
7218
7219 exception Error of string
7220 exception Handle_closed of string
7221
7222 external create : unit -> t = \"ocaml_guestfs_create\"
7223 external close : t -> unit = \"ocaml_guestfs_close\"
7224
7225 (* Give the exceptions names, so they can be raised from the C code. *)
7226 let () =
7227   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7228   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7229
7230 ";
7231
7232   generate_ocaml_structure_decls ();
7233
7234   (* The actions. *)
7235   List.iter (
7236     fun (name, style, _, _, _, shortdesc, _) ->
7237       generate_ocaml_prototype ~is_external:true name style;
7238   ) all_functions_sorted
7239
7240 (* Generate the OCaml bindings C implementation. *)
7241 and generate_ocaml_c () =
7242   generate_header CStyle LGPLv2;
7243
7244   pr "\
7245 #include <stdio.h>
7246 #include <stdlib.h>
7247 #include <string.h>
7248
7249 #include <caml/config.h>
7250 #include <caml/alloc.h>
7251 #include <caml/callback.h>
7252 #include <caml/fail.h>
7253 #include <caml/memory.h>
7254 #include <caml/mlvalues.h>
7255 #include <caml/signals.h>
7256
7257 #include <guestfs.h>
7258
7259 #include \"guestfs_c.h\"
7260
7261 /* Copy a hashtable of string pairs into an assoc-list.  We return
7262  * the list in reverse order, but hashtables aren't supposed to be
7263  * ordered anyway.
7264  */
7265 static CAMLprim value
7266 copy_table (char * const * argv)
7267 {
7268   CAMLparam0 ();
7269   CAMLlocal5 (rv, pairv, kv, vv, cons);
7270   int i;
7271
7272   rv = Val_int (0);
7273   for (i = 0; argv[i] != NULL; i += 2) {
7274     kv = caml_copy_string (argv[i]);
7275     vv = caml_copy_string (argv[i+1]);
7276     pairv = caml_alloc (2, 0);
7277     Store_field (pairv, 0, kv);
7278     Store_field (pairv, 1, vv);
7279     cons = caml_alloc (2, 0);
7280     Store_field (cons, 1, rv);
7281     rv = cons;
7282     Store_field (cons, 0, pairv);
7283   }
7284
7285   CAMLreturn (rv);
7286 }
7287
7288 ";
7289
7290   (* Struct copy functions. *)
7291
7292   let emit_ocaml_copy_list_function typ =
7293     pr "static CAMLprim value\n";
7294     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7295     pr "{\n";
7296     pr "  CAMLparam0 ();\n";
7297     pr "  CAMLlocal2 (rv, v);\n";
7298     pr "  unsigned int i;\n";
7299     pr "\n";
7300     pr "  if (%ss->len == 0)\n" typ;
7301     pr "    CAMLreturn (Atom (0));\n";
7302     pr "  else {\n";
7303     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7304     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7305     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7306     pr "      caml_modify (&Field (rv, i), v);\n";
7307     pr "    }\n";
7308     pr "    CAMLreturn (rv);\n";
7309     pr "  }\n";
7310     pr "}\n";
7311     pr "\n";
7312   in
7313
7314   List.iter (
7315     fun (typ, cols) ->
7316       let has_optpercent_col =
7317         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7318
7319       pr "static CAMLprim value\n";
7320       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7321       pr "{\n";
7322       pr "  CAMLparam0 ();\n";
7323       if has_optpercent_col then
7324         pr "  CAMLlocal3 (rv, v, v2);\n"
7325       else
7326         pr "  CAMLlocal2 (rv, v);\n";
7327       pr "\n";
7328       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7329       iteri (
7330         fun i col ->
7331           (match col with
7332            | name, FString ->
7333                pr "  v = caml_copy_string (%s->%s);\n" typ name
7334            | name, FBuffer ->
7335                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7336                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7337                  typ name typ name
7338            | name, FUUID ->
7339                pr "  v = caml_alloc_string (32);\n";
7340                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7341            | name, (FBytes|FInt64|FUInt64) ->
7342                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7343            | name, (FInt32|FUInt32) ->
7344                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7345            | name, FOptPercent ->
7346                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7347                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7348                pr "    v = caml_alloc (1, 0);\n";
7349                pr "    Store_field (v, 0, v2);\n";
7350                pr "  } else /* None */\n";
7351                pr "    v = Val_int (0);\n";
7352            | name, FChar ->
7353                pr "  v = Val_int (%s->%s);\n" typ name
7354           );
7355           pr "  Store_field (rv, %d, v);\n" i
7356       ) cols;
7357       pr "  CAMLreturn (rv);\n";
7358       pr "}\n";
7359       pr "\n";
7360   ) structs;
7361
7362   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7363   List.iter (
7364     function
7365     | typ, (RStructListOnly | RStructAndList) ->
7366         (* generate the function for typ *)
7367         emit_ocaml_copy_list_function typ
7368     | typ, _ -> () (* empty *)
7369   ) (rstructs_used_by all_functions);
7370
7371   (* The wrappers. *)
7372   List.iter (
7373     fun (name, style, _, _, _, _, _) ->
7374       pr "/* Automatically generated wrapper for function\n";
7375       pr " * ";
7376       generate_ocaml_prototype name style;
7377       pr " */\n";
7378       pr "\n";
7379
7380       let params =
7381         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7382
7383       let needs_extra_vs =
7384         match fst style with RConstOptString _ -> true | _ -> false in
7385
7386       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7387       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7388       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7389       pr "\n";
7390
7391       pr "CAMLprim value\n";
7392       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7393       List.iter (pr ", value %s") (List.tl params);
7394       pr ")\n";
7395       pr "{\n";
7396
7397       (match params with
7398        | [p1; p2; p3; p4; p5] ->
7399            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7400        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7401            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7402            pr "  CAMLxparam%d (%s);\n"
7403              (List.length rest) (String.concat ", " rest)
7404        | ps ->
7405            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7406       );
7407       if not needs_extra_vs then
7408         pr "  CAMLlocal1 (rv);\n"
7409       else
7410         pr "  CAMLlocal3 (rv, v, v2);\n";
7411       pr "\n";
7412
7413       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7414       pr "  if (g == NULL)\n";
7415       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7416       pr "\n";
7417
7418       List.iter (
7419         function
7420         | Pathname n
7421         | Device n | Dev_or_Path n
7422         | String n
7423         | FileIn n
7424         | FileOut n ->
7425             pr "  const char *%s = String_val (%sv);\n" n n
7426         | OptString n ->
7427             pr "  const char *%s =\n" n;
7428             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7429               n n
7430         | StringList n | DeviceList n ->
7431             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7432         | Bool n ->
7433             pr "  int %s = Bool_val (%sv);\n" n n
7434         | Int n ->
7435             pr "  int %s = Int_val (%sv);\n" n n
7436         | Int64 n ->
7437             pr "  int64_t %s = Int64_val (%sv);\n" n n
7438       ) (snd style);
7439       let error_code =
7440         match fst style with
7441         | RErr -> pr "  int r;\n"; "-1"
7442         | RInt _ -> pr "  int r;\n"; "-1"
7443         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7444         | RBool _ -> pr "  int r;\n"; "-1"
7445         | RConstString _ | RConstOptString _ ->
7446             pr "  const char *r;\n"; "NULL"
7447         | RString _ -> pr "  char *r;\n"; "NULL"
7448         | RStringList _ ->
7449             pr "  int i;\n";
7450             pr "  char **r;\n";
7451             "NULL"
7452         | RStruct (_, typ) ->
7453             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7454         | RStructList (_, typ) ->
7455             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7456         | RHashtable _ ->
7457             pr "  int i;\n";
7458             pr "  char **r;\n";
7459             "NULL"
7460         | RBufferOut _ ->
7461             pr "  char *r;\n";
7462             pr "  size_t size;\n";
7463             "NULL" in
7464       pr "\n";
7465
7466       pr "  caml_enter_blocking_section ();\n";
7467       pr "  r = guestfs_%s " name;
7468       generate_c_call_args ~handle:"g" style;
7469       pr ";\n";
7470       pr "  caml_leave_blocking_section ();\n";
7471
7472       List.iter (
7473         function
7474         | StringList n | DeviceList n ->
7475             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7476         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7477         | Bool _ | Int _ | Int64 _
7478         | FileIn _ | FileOut _ -> ()
7479       ) (snd style);
7480
7481       pr "  if (r == %s)\n" error_code;
7482       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7483       pr "\n";
7484
7485       (match fst style with
7486        | RErr -> pr "  rv = Val_unit;\n"
7487        | RInt _ -> pr "  rv = Val_int (r);\n"
7488        | RInt64 _ ->
7489            pr "  rv = caml_copy_int64 (r);\n"
7490        | RBool _ -> pr "  rv = Val_bool (r);\n"
7491        | RConstString _ ->
7492            pr "  rv = caml_copy_string (r);\n"
7493        | RConstOptString _ ->
7494            pr "  if (r) { /* Some string */\n";
7495            pr "    v = caml_alloc (1, 0);\n";
7496            pr "    v2 = caml_copy_string (r);\n";
7497            pr "    Store_field (v, 0, v2);\n";
7498            pr "  } else /* None */\n";
7499            pr "    v = Val_int (0);\n";
7500        | RString _ ->
7501            pr "  rv = caml_copy_string (r);\n";
7502            pr "  free (r);\n"
7503        | RStringList _ ->
7504            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7505            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7506            pr "  free (r);\n"
7507        | RStruct (_, typ) ->
7508            pr "  rv = copy_%s (r);\n" typ;
7509            pr "  guestfs_free_%s (r);\n" typ;
7510        | RStructList (_, typ) ->
7511            pr "  rv = copy_%s_list (r);\n" typ;
7512            pr "  guestfs_free_%s_list (r);\n" typ;
7513        | RHashtable _ ->
7514            pr "  rv = copy_table (r);\n";
7515            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7516            pr "  free (r);\n";
7517        | RBufferOut _ ->
7518            pr "  rv = caml_alloc_string (size);\n";
7519            pr "  memcpy (String_val (rv), r, size);\n";
7520       );
7521
7522       pr "  CAMLreturn (rv);\n";
7523       pr "}\n";
7524       pr "\n";
7525
7526       if List.length params > 5 then (
7527         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7528         pr "CAMLprim value ";
7529         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7530         pr "CAMLprim value\n";
7531         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7532         pr "{\n";
7533         pr "  return ocaml_guestfs_%s (argv[0]" name;
7534         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7535         pr ");\n";
7536         pr "}\n";
7537         pr "\n"
7538       )
7539   ) all_functions_sorted
7540
7541 and generate_ocaml_structure_decls () =
7542   List.iter (
7543     fun (typ, cols) ->
7544       pr "type %s = {\n" typ;
7545       List.iter (
7546         function
7547         | name, FString -> pr "  %s : string;\n" name
7548         | name, FBuffer -> pr "  %s : string;\n" name
7549         | name, FUUID -> pr "  %s : string;\n" name
7550         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7551         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7552         | name, FChar -> pr "  %s : char;\n" name
7553         | name, FOptPercent -> pr "  %s : float option;\n" name
7554       ) cols;
7555       pr "}\n";
7556       pr "\n"
7557   ) structs
7558
7559 and generate_ocaml_prototype ?(is_external = false) name style =
7560   if is_external then pr "external " else pr "val ";
7561   pr "%s : t -> " name;
7562   List.iter (
7563     function
7564     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7565     | OptString _ -> pr "string option -> "
7566     | StringList _ | DeviceList _ -> pr "string array -> "
7567     | Bool _ -> pr "bool -> "
7568     | Int _ -> pr "int -> "
7569     | Int64 _ -> pr "int64 -> "
7570   ) (snd style);
7571   (match fst style with
7572    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7573    | RInt _ -> pr "int"
7574    | RInt64 _ -> pr "int64"
7575    | RBool _ -> pr "bool"
7576    | RConstString _ -> pr "string"
7577    | RConstOptString _ -> pr "string option"
7578    | RString _ | RBufferOut _ -> pr "string"
7579    | RStringList _ -> pr "string array"
7580    | RStruct (_, typ) -> pr "%s" typ
7581    | RStructList (_, typ) -> pr "%s array" typ
7582    | RHashtable _ -> pr "(string * string) list"
7583   );
7584   if is_external then (
7585     pr " = ";
7586     if List.length (snd style) + 1 > 5 then
7587       pr "\"ocaml_guestfs_%s_byte\" " name;
7588     pr "\"ocaml_guestfs_%s\"" name
7589   );
7590   pr "\n"
7591
7592 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7593 and generate_perl_xs () =
7594   generate_header CStyle LGPLv2;
7595
7596   pr "\
7597 #include \"EXTERN.h\"
7598 #include \"perl.h\"
7599 #include \"XSUB.h\"
7600
7601 #include <guestfs.h>
7602
7603 #ifndef PRId64
7604 #define PRId64 \"lld\"
7605 #endif
7606
7607 static SV *
7608 my_newSVll(long long val) {
7609 #ifdef USE_64_BIT_ALL
7610   return newSViv(val);
7611 #else
7612   char buf[100];
7613   int len;
7614   len = snprintf(buf, 100, \"%%\" PRId64, val);
7615   return newSVpv(buf, len);
7616 #endif
7617 }
7618
7619 #ifndef PRIu64
7620 #define PRIu64 \"llu\"
7621 #endif
7622
7623 static SV *
7624 my_newSVull(unsigned long long val) {
7625 #ifdef USE_64_BIT_ALL
7626   return newSVuv(val);
7627 #else
7628   char buf[100];
7629   int len;
7630   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7631   return newSVpv(buf, len);
7632 #endif
7633 }
7634
7635 /* http://www.perlmonks.org/?node_id=680842 */
7636 static char **
7637 XS_unpack_charPtrPtr (SV *arg) {
7638   char **ret;
7639   AV *av;
7640   I32 i;
7641
7642   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7643     croak (\"array reference expected\");
7644
7645   av = (AV *)SvRV (arg);
7646   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7647   if (!ret)
7648     croak (\"malloc failed\");
7649
7650   for (i = 0; i <= av_len (av); i++) {
7651     SV **elem = av_fetch (av, i, 0);
7652
7653     if (!elem || !*elem)
7654       croak (\"missing element in list\");
7655
7656     ret[i] = SvPV_nolen (*elem);
7657   }
7658
7659   ret[i] = NULL;
7660
7661   return ret;
7662 }
7663
7664 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7665
7666 PROTOTYPES: ENABLE
7667
7668 guestfs_h *
7669 _create ()
7670    CODE:
7671       RETVAL = guestfs_create ();
7672       if (!RETVAL)
7673         croak (\"could not create guestfs handle\");
7674       guestfs_set_error_handler (RETVAL, NULL, NULL);
7675  OUTPUT:
7676       RETVAL
7677
7678 void
7679 DESTROY (g)
7680       guestfs_h *g;
7681  PPCODE:
7682       guestfs_close (g);
7683
7684 ";
7685
7686   List.iter (
7687     fun (name, style, _, _, _, _, _) ->
7688       (match fst style with
7689        | RErr -> pr "void\n"
7690        | RInt _ -> pr "SV *\n"
7691        | RInt64 _ -> pr "SV *\n"
7692        | RBool _ -> pr "SV *\n"
7693        | RConstString _ -> pr "SV *\n"
7694        | RConstOptString _ -> pr "SV *\n"
7695        | RString _ -> pr "SV *\n"
7696        | RBufferOut _ -> pr "SV *\n"
7697        | RStringList _
7698        | RStruct _ | RStructList _
7699        | RHashtable _ ->
7700            pr "void\n" (* all lists returned implictly on the stack *)
7701       );
7702       (* Call and arguments. *)
7703       pr "%s " name;
7704       generate_c_call_args ~handle:"g" ~decl:true style;
7705       pr "\n";
7706       pr "      guestfs_h *g;\n";
7707       iteri (
7708         fun i ->
7709           function
7710           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7711               pr "      char *%s;\n" n
7712           | OptString n ->
7713               (* http://www.perlmonks.org/?node_id=554277
7714                * Note that the implicit handle argument means we have
7715                * to add 1 to the ST(x) operator.
7716                *)
7717               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7718           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7719           | Bool n -> pr "      int %s;\n" n
7720           | Int n -> pr "      int %s;\n" n
7721           | Int64 n -> pr "      int64_t %s;\n" n
7722       ) (snd style);
7723
7724       let do_cleanups () =
7725         List.iter (
7726           function
7727           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7728           | Bool _ | Int _ | Int64 _
7729           | FileIn _ | FileOut _ -> ()
7730           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7731         ) (snd style)
7732       in
7733
7734       (* Code. *)
7735       (match fst style with
7736        | RErr ->
7737            pr "PREINIT:\n";
7738            pr "      int r;\n";
7739            pr " PPCODE:\n";
7740            pr "      r = guestfs_%s " name;
7741            generate_c_call_args ~handle:"g" style;
7742            pr ";\n";
7743            do_cleanups ();
7744            pr "      if (r == -1)\n";
7745            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7746        | RInt n
7747        | RBool n ->
7748            pr "PREINIT:\n";
7749            pr "      int %s;\n" n;
7750            pr "   CODE:\n";
7751            pr "      %s = guestfs_%s " n name;
7752            generate_c_call_args ~handle:"g" style;
7753            pr ";\n";
7754            do_cleanups ();
7755            pr "      if (%s == -1)\n" n;
7756            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7757            pr "      RETVAL = newSViv (%s);\n" n;
7758            pr " OUTPUT:\n";
7759            pr "      RETVAL\n"
7760        | RInt64 n ->
7761            pr "PREINIT:\n";
7762            pr "      int64_t %s;\n" n;
7763            pr "   CODE:\n";
7764            pr "      %s = guestfs_%s " n name;
7765            generate_c_call_args ~handle:"g" style;
7766            pr ";\n";
7767            do_cleanups ();
7768            pr "      if (%s == -1)\n" n;
7769            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7770            pr "      RETVAL = my_newSVll (%s);\n" n;
7771            pr " OUTPUT:\n";
7772            pr "      RETVAL\n"
7773        | RConstString n ->
7774            pr "PREINIT:\n";
7775            pr "      const char *%s;\n" n;
7776            pr "   CODE:\n";
7777            pr "      %s = guestfs_%s " n name;
7778            generate_c_call_args ~handle:"g" style;
7779            pr ";\n";
7780            do_cleanups ();
7781            pr "      if (%s == NULL)\n" n;
7782            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7783            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7784            pr " OUTPUT:\n";
7785            pr "      RETVAL\n"
7786        | RConstOptString n ->
7787            pr "PREINIT:\n";
7788            pr "      const char *%s;\n" n;
7789            pr "   CODE:\n";
7790            pr "      %s = guestfs_%s " n name;
7791            generate_c_call_args ~handle:"g" style;
7792            pr ";\n";
7793            do_cleanups ();
7794            pr "      if (%s == NULL)\n" n;
7795            pr "        RETVAL = &PL_sv_undef;\n";
7796            pr "      else\n";
7797            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7798            pr " OUTPUT:\n";
7799            pr "      RETVAL\n"
7800        | RString n ->
7801            pr "PREINIT:\n";
7802            pr "      char *%s;\n" n;
7803            pr "   CODE:\n";
7804            pr "      %s = guestfs_%s " n name;
7805            generate_c_call_args ~handle:"g" style;
7806            pr ";\n";
7807            do_cleanups ();
7808            pr "      if (%s == NULL)\n" n;
7809            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7810            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7811            pr "      free (%s);\n" n;
7812            pr " OUTPUT:\n";
7813            pr "      RETVAL\n"
7814        | RStringList n | RHashtable n ->
7815            pr "PREINIT:\n";
7816            pr "      char **%s;\n" n;
7817            pr "      int i, n;\n";
7818            pr " PPCODE:\n";
7819            pr "      %s = guestfs_%s " n name;
7820            generate_c_call_args ~handle:"g" style;
7821            pr ";\n";
7822            do_cleanups ();
7823            pr "      if (%s == NULL)\n" n;
7824            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7825            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7826            pr "      EXTEND (SP, n);\n";
7827            pr "      for (i = 0; i < n; ++i) {\n";
7828            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7829            pr "        free (%s[i]);\n" n;
7830            pr "      }\n";
7831            pr "      free (%s);\n" n;
7832        | RStruct (n, typ) ->
7833            let cols = cols_of_struct typ in
7834            generate_perl_struct_code typ cols name style n do_cleanups
7835        | RStructList (n, typ) ->
7836            let cols = cols_of_struct typ in
7837            generate_perl_struct_list_code typ cols name style n do_cleanups
7838        | RBufferOut n ->
7839            pr "PREINIT:\n";
7840            pr "      char *%s;\n" n;
7841            pr "      size_t size;\n";
7842            pr "   CODE:\n";
7843            pr "      %s = guestfs_%s " n name;
7844            generate_c_call_args ~handle:"g" style;
7845            pr ";\n";
7846            do_cleanups ();
7847            pr "      if (%s == NULL)\n" n;
7848            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7849            pr "      RETVAL = newSVpv (%s, size);\n" n;
7850            pr "      free (%s);\n" n;
7851            pr " OUTPUT:\n";
7852            pr "      RETVAL\n"
7853       );
7854
7855       pr "\n"
7856   ) all_functions
7857
7858 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7859   pr "PREINIT:\n";
7860   pr "      struct guestfs_%s_list *%s;\n" typ n;
7861   pr "      int i;\n";
7862   pr "      HV *hv;\n";
7863   pr " PPCODE:\n";
7864   pr "      %s = guestfs_%s " n name;
7865   generate_c_call_args ~handle:"g" style;
7866   pr ";\n";
7867   do_cleanups ();
7868   pr "      if (%s == NULL)\n" n;
7869   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7870   pr "      EXTEND (SP, %s->len);\n" n;
7871   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7872   pr "        hv = newHV ();\n";
7873   List.iter (
7874     function
7875     | name, FString ->
7876         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7877           name (String.length name) n name
7878     | name, FUUID ->
7879         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7880           name (String.length name) n name
7881     | name, FBuffer ->
7882         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7883           name (String.length name) n name n name
7884     | name, (FBytes|FUInt64) ->
7885         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7886           name (String.length name) n name
7887     | name, FInt64 ->
7888         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7889           name (String.length name) n name
7890     | name, (FInt32|FUInt32) ->
7891         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7892           name (String.length name) n name
7893     | name, FChar ->
7894         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7895           name (String.length name) n name
7896     | name, FOptPercent ->
7897         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7898           name (String.length name) n name
7899   ) cols;
7900   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7901   pr "      }\n";
7902   pr "      guestfs_free_%s_list (%s);\n" typ n
7903
7904 and generate_perl_struct_code typ cols name style n do_cleanups =
7905   pr "PREINIT:\n";
7906   pr "      struct guestfs_%s *%s;\n" typ n;
7907   pr " PPCODE:\n";
7908   pr "      %s = guestfs_%s " n name;
7909   generate_c_call_args ~handle:"g" style;
7910   pr ";\n";
7911   do_cleanups ();
7912   pr "      if (%s == NULL)\n" n;
7913   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7914   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7915   List.iter (
7916     fun ((name, _) as col) ->
7917       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7918
7919       match col with
7920       | name, FString ->
7921           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7922             n name
7923       | name, FBuffer ->
7924           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7925             n name n name
7926       | name, FUUID ->
7927           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7928             n name
7929       | name, (FBytes|FUInt64) ->
7930           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7931             n name
7932       | name, FInt64 ->
7933           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7934             n name
7935       | name, (FInt32|FUInt32) ->
7936           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7937             n name
7938       | name, FChar ->
7939           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7940             n name
7941       | name, FOptPercent ->
7942           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7943             n name
7944   ) cols;
7945   pr "      free (%s);\n" n
7946
7947 (* Generate Sys/Guestfs.pm. *)
7948 and generate_perl_pm () =
7949   generate_header HashStyle LGPLv2;
7950
7951   pr "\
7952 =pod
7953
7954 =head1 NAME
7955
7956 Sys::Guestfs - Perl bindings for libguestfs
7957
7958 =head1 SYNOPSIS
7959
7960  use Sys::Guestfs;
7961
7962  my $h = Sys::Guestfs->new ();
7963  $h->add_drive ('guest.img');
7964  $h->launch ();
7965  $h->mount ('/dev/sda1', '/');
7966  $h->touch ('/hello');
7967  $h->sync ();
7968
7969 =head1 DESCRIPTION
7970
7971 The C<Sys::Guestfs> module provides a Perl XS binding to the
7972 libguestfs API for examining and modifying virtual machine
7973 disk images.
7974
7975 Amongst the things this is good for: making batch configuration
7976 changes to guests, getting disk used/free statistics (see also:
7977 virt-df), migrating between virtualization systems (see also:
7978 virt-p2v), performing partial backups, performing partial guest
7979 clones, cloning guests and changing registry/UUID/hostname info, and
7980 much else besides.
7981
7982 Libguestfs uses Linux kernel and qemu code, and can access any type of
7983 guest filesystem that Linux and qemu can, including but not limited
7984 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7985 schemes, qcow, qcow2, vmdk.
7986
7987 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7988 LVs, what filesystem is in each LV, etc.).  It can also run commands
7989 in the context of the guest.  Also you can access filesystems over FTP.
7990
7991 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7992 functions for using libguestfs from Perl, including integration
7993 with libvirt.
7994
7995 =head1 ERRORS
7996
7997 All errors turn into calls to C<croak> (see L<Carp(3)>).
7998
7999 =head1 METHODS
8000
8001 =over 4
8002
8003 =cut
8004
8005 package Sys::Guestfs;
8006
8007 use strict;
8008 use warnings;
8009
8010 require XSLoader;
8011 XSLoader::load ('Sys::Guestfs');
8012
8013 =item $h = Sys::Guestfs->new ();
8014
8015 Create a new guestfs handle.
8016
8017 =cut
8018
8019 sub new {
8020   my $proto = shift;
8021   my $class = ref ($proto) || $proto;
8022
8023   my $self = Sys::Guestfs::_create ();
8024   bless $self, $class;
8025   return $self;
8026 }
8027
8028 ";
8029
8030   (* Actions.  We only need to print documentation for these as
8031    * they are pulled in from the XS code automatically.
8032    *)
8033   List.iter (
8034     fun (name, style, _, flags, _, _, longdesc) ->
8035       if not (List.mem NotInDocs flags) then (
8036         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8037         pr "=item ";
8038         generate_perl_prototype name style;
8039         pr "\n\n";
8040         pr "%s\n\n" longdesc;
8041         if List.mem ProtocolLimitWarning flags then
8042           pr "%s\n\n" protocol_limit_warning;
8043         if List.mem DangerWillRobinson flags then
8044           pr "%s\n\n" danger_will_robinson;
8045         match deprecation_notice flags with
8046         | None -> ()
8047         | Some txt -> pr "%s\n\n" txt
8048       )
8049   ) all_functions_sorted;
8050
8051   (* End of file. *)
8052   pr "\
8053 =cut
8054
8055 1;
8056
8057 =back
8058
8059 =head1 COPYRIGHT
8060
8061 Copyright (C) 2009 Red Hat Inc.
8062
8063 =head1 LICENSE
8064
8065 Please see the file COPYING.LIB for the full license.
8066
8067 =head1 SEE ALSO
8068
8069 L<guestfs(3)>,
8070 L<guestfish(1)>,
8071 L<http://libguestfs.org>,
8072 L<Sys::Guestfs::Lib(3)>.
8073
8074 =cut
8075 "
8076
8077 and generate_perl_prototype name style =
8078   (match fst style with
8079    | RErr -> ()
8080    | RBool n
8081    | RInt n
8082    | RInt64 n
8083    | RConstString n
8084    | RConstOptString n
8085    | RString n
8086    | RBufferOut n -> pr "$%s = " n
8087    | RStruct (n,_)
8088    | RHashtable n -> pr "%%%s = " n
8089    | RStringList n
8090    | RStructList (n,_) -> pr "@%s = " n
8091   );
8092   pr "$h->%s (" name;
8093   let comma = ref false in
8094   List.iter (
8095     fun arg ->
8096       if !comma then pr ", ";
8097       comma := true;
8098       match arg with
8099       | Pathname n | Device n | Dev_or_Path n | String n
8100       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8101           pr "$%s" n
8102       | StringList n | DeviceList n ->
8103           pr "\\@%s" n
8104   ) (snd style);
8105   pr ");"
8106
8107 (* Generate Python C module. *)
8108 and generate_python_c () =
8109   generate_header CStyle LGPLv2;
8110
8111   pr "\
8112 #include <Python.h>
8113
8114 #include <stdio.h>
8115 #include <stdlib.h>
8116 #include <assert.h>
8117
8118 #include \"guestfs.h\"
8119
8120 typedef struct {
8121   PyObject_HEAD
8122   guestfs_h *g;
8123 } Pyguestfs_Object;
8124
8125 static guestfs_h *
8126 get_handle (PyObject *obj)
8127 {
8128   assert (obj);
8129   assert (obj != Py_None);
8130   return ((Pyguestfs_Object *) obj)->g;
8131 }
8132
8133 static PyObject *
8134 put_handle (guestfs_h *g)
8135 {
8136   assert (g);
8137   return
8138     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8139 }
8140
8141 /* This list should be freed (but not the strings) after use. */
8142 static char **
8143 get_string_list (PyObject *obj)
8144 {
8145   int i, len;
8146   char **r;
8147
8148   assert (obj);
8149
8150   if (!PyList_Check (obj)) {
8151     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8152     return NULL;
8153   }
8154
8155   len = PyList_Size (obj);
8156   r = malloc (sizeof (char *) * (len+1));
8157   if (r == NULL) {
8158     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8159     return NULL;
8160   }
8161
8162   for (i = 0; i < len; ++i)
8163     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8164   r[len] = NULL;
8165
8166   return r;
8167 }
8168
8169 static PyObject *
8170 put_string_list (char * const * const argv)
8171 {
8172   PyObject *list;
8173   int argc, i;
8174
8175   for (argc = 0; argv[argc] != NULL; ++argc)
8176     ;
8177
8178   list = PyList_New (argc);
8179   for (i = 0; i < argc; ++i)
8180     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8181
8182   return list;
8183 }
8184
8185 static PyObject *
8186 put_table (char * const * const argv)
8187 {
8188   PyObject *list, *item;
8189   int argc, i;
8190
8191   for (argc = 0; argv[argc] != NULL; ++argc)
8192     ;
8193
8194   list = PyList_New (argc >> 1);
8195   for (i = 0; i < argc; i += 2) {
8196     item = PyTuple_New (2);
8197     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8198     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8199     PyList_SetItem (list, i >> 1, item);
8200   }
8201
8202   return list;
8203 }
8204
8205 static void
8206 free_strings (char **argv)
8207 {
8208   int argc;
8209
8210   for (argc = 0; argv[argc] != NULL; ++argc)
8211     free (argv[argc]);
8212   free (argv);
8213 }
8214
8215 static PyObject *
8216 py_guestfs_create (PyObject *self, PyObject *args)
8217 {
8218   guestfs_h *g;
8219
8220   g = guestfs_create ();
8221   if (g == NULL) {
8222     PyErr_SetString (PyExc_RuntimeError,
8223                      \"guestfs.create: failed to allocate handle\");
8224     return NULL;
8225   }
8226   guestfs_set_error_handler (g, NULL, NULL);
8227   return put_handle (g);
8228 }
8229
8230 static PyObject *
8231 py_guestfs_close (PyObject *self, PyObject *args)
8232 {
8233   PyObject *py_g;
8234   guestfs_h *g;
8235
8236   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8237     return NULL;
8238   g = get_handle (py_g);
8239
8240   guestfs_close (g);
8241
8242   Py_INCREF (Py_None);
8243   return Py_None;
8244 }
8245
8246 ";
8247
8248   let emit_put_list_function typ =
8249     pr "static PyObject *\n";
8250     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8251     pr "{\n";
8252     pr "  PyObject *list;\n";
8253     pr "  int i;\n";
8254     pr "\n";
8255     pr "  list = PyList_New (%ss->len);\n" typ;
8256     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8257     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8258     pr "  return list;\n";
8259     pr "};\n";
8260     pr "\n"
8261   in
8262
8263   (* Structures, turned into Python dictionaries. *)
8264   List.iter (
8265     fun (typ, cols) ->
8266       pr "static PyObject *\n";
8267       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8268       pr "{\n";
8269       pr "  PyObject *dict;\n";
8270       pr "\n";
8271       pr "  dict = PyDict_New ();\n";
8272       List.iter (
8273         function
8274         | name, FString ->
8275             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8276             pr "                        PyString_FromString (%s->%s));\n"
8277               typ name
8278         | name, FBuffer ->
8279             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8280             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8281               typ name typ name
8282         | name, FUUID ->
8283             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8284             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8285               typ name
8286         | name, (FBytes|FUInt64) ->
8287             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8288             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8289               typ name
8290         | name, FInt64 ->
8291             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8292             pr "                        PyLong_FromLongLong (%s->%s));\n"
8293               typ name
8294         | name, FUInt32 ->
8295             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8296             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8297               typ name
8298         | name, FInt32 ->
8299             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8300             pr "                        PyLong_FromLong (%s->%s));\n"
8301               typ name
8302         | name, FOptPercent ->
8303             pr "  if (%s->%s >= 0)\n" typ name;
8304             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8305             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8306               typ name;
8307             pr "  else {\n";
8308             pr "    Py_INCREF (Py_None);\n";
8309             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8310             pr "  }\n"
8311         | name, FChar ->
8312             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8313             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8314       ) cols;
8315       pr "  return dict;\n";
8316       pr "};\n";
8317       pr "\n";
8318
8319   ) structs;
8320
8321   (* Emit a put_TYPE_list function definition only if that function is used. *)
8322   List.iter (
8323     function
8324     | typ, (RStructListOnly | RStructAndList) ->
8325         (* generate the function for typ *)
8326         emit_put_list_function typ
8327     | typ, _ -> () (* empty *)
8328   ) (rstructs_used_by all_functions);
8329
8330   (* Python wrapper functions. *)
8331   List.iter (
8332     fun (name, style, _, _, _, _, _) ->
8333       pr "static PyObject *\n";
8334       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8335       pr "{\n";
8336
8337       pr "  PyObject *py_g;\n";
8338       pr "  guestfs_h *g;\n";
8339       pr "  PyObject *py_r;\n";
8340
8341       let error_code =
8342         match fst style with
8343         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8344         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8345         | RConstString _ | RConstOptString _ ->
8346             pr "  const char *r;\n"; "NULL"
8347         | RString _ -> pr "  char *r;\n"; "NULL"
8348         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8349         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8350         | RStructList (_, typ) ->
8351             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8352         | RBufferOut _ ->
8353             pr "  char *r;\n";
8354             pr "  size_t size;\n";
8355             "NULL" in
8356
8357       List.iter (
8358         function
8359         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8360             pr "  const char *%s;\n" n
8361         | OptString n -> pr "  const char *%s;\n" n
8362         | StringList n | DeviceList n ->
8363             pr "  PyObject *py_%s;\n" n;
8364             pr "  char **%s;\n" n
8365         | Bool n -> pr "  int %s;\n" n
8366         | Int n -> pr "  int %s;\n" n
8367         | Int64 n -> pr "  long long %s;\n" n
8368       ) (snd style);
8369
8370       pr "\n";
8371
8372       (* Convert the parameters. *)
8373       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8374       List.iter (
8375         function
8376         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8377         | OptString _ -> pr "z"
8378         | StringList _ | DeviceList _ -> pr "O"
8379         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8380         | Int _ -> pr "i"
8381         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8382                              * emulate C's int/long/long long in Python?
8383                              *)
8384       ) (snd style);
8385       pr ":guestfs_%s\",\n" name;
8386       pr "                         &py_g";
8387       List.iter (
8388         function
8389         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8390         | OptString n -> pr ", &%s" n
8391         | StringList n | DeviceList n -> pr ", &py_%s" n
8392         | Bool n -> pr ", &%s" n
8393         | Int n -> pr ", &%s" n
8394         | Int64 n -> pr ", &%s" n
8395       ) (snd style);
8396
8397       pr "))\n";
8398       pr "    return NULL;\n";
8399
8400       pr "  g = get_handle (py_g);\n";
8401       List.iter (
8402         function
8403         | Pathname _ | Device _ | Dev_or_Path _ | String _
8404         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8405         | StringList n | DeviceList n ->
8406             pr "  %s = get_string_list (py_%s);\n" n n;
8407             pr "  if (!%s) return NULL;\n" n
8408       ) (snd style);
8409
8410       pr "\n";
8411
8412       pr "  r = guestfs_%s " name;
8413       generate_c_call_args ~handle:"g" style;
8414       pr ";\n";
8415
8416       List.iter (
8417         function
8418         | Pathname _ | Device _ | Dev_or_Path _ | String _
8419         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8420         | StringList n | DeviceList n ->
8421             pr "  free (%s);\n" n
8422       ) (snd style);
8423
8424       pr "  if (r == %s) {\n" error_code;
8425       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8426       pr "    return NULL;\n";
8427       pr "  }\n";
8428       pr "\n";
8429
8430       (match fst style with
8431        | RErr ->
8432            pr "  Py_INCREF (Py_None);\n";
8433            pr "  py_r = Py_None;\n"
8434        | RInt _
8435        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8436        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8437        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8438        | RConstOptString _ ->
8439            pr "  if (r)\n";
8440            pr "    py_r = PyString_FromString (r);\n";
8441            pr "  else {\n";
8442            pr "    Py_INCREF (Py_None);\n";
8443            pr "    py_r = Py_None;\n";
8444            pr "  }\n"
8445        | RString _ ->
8446            pr "  py_r = PyString_FromString (r);\n";
8447            pr "  free (r);\n"
8448        | RStringList _ ->
8449            pr "  py_r = put_string_list (r);\n";
8450            pr "  free_strings (r);\n"
8451        | RStruct (_, typ) ->
8452            pr "  py_r = put_%s (r);\n" typ;
8453            pr "  guestfs_free_%s (r);\n" typ
8454        | RStructList (_, typ) ->
8455            pr "  py_r = put_%s_list (r);\n" typ;
8456            pr "  guestfs_free_%s_list (r);\n" typ
8457        | RHashtable n ->
8458            pr "  py_r = put_table (r);\n";
8459            pr "  free_strings (r);\n"
8460        | RBufferOut _ ->
8461            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8462            pr "  free (r);\n"
8463       );
8464
8465       pr "  return py_r;\n";
8466       pr "}\n";
8467       pr "\n"
8468   ) all_functions;
8469
8470   (* Table of functions. *)
8471   pr "static PyMethodDef methods[] = {\n";
8472   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8473   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8474   List.iter (
8475     fun (name, _, _, _, _, _, _) ->
8476       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8477         name name
8478   ) all_functions;
8479   pr "  { NULL, NULL, 0, NULL }\n";
8480   pr "};\n";
8481   pr "\n";
8482
8483   (* Init function. *)
8484   pr "\
8485 void
8486 initlibguestfsmod (void)
8487 {
8488   static int initialized = 0;
8489
8490   if (initialized) return;
8491   Py_InitModule ((char *) \"libguestfsmod\", methods);
8492   initialized = 1;
8493 }
8494 "
8495
8496 (* Generate Python module. *)
8497 and generate_python_py () =
8498   generate_header HashStyle LGPLv2;
8499
8500   pr "\
8501 u\"\"\"Python bindings for libguestfs
8502
8503 import guestfs
8504 g = guestfs.GuestFS ()
8505 g.add_drive (\"guest.img\")
8506 g.launch ()
8507 parts = g.list_partitions ()
8508
8509 The guestfs module provides a Python binding to the libguestfs API
8510 for examining and modifying virtual machine disk images.
8511
8512 Amongst the things this is good for: making batch configuration
8513 changes to guests, getting disk used/free statistics (see also:
8514 virt-df), migrating between virtualization systems (see also:
8515 virt-p2v), performing partial backups, performing partial guest
8516 clones, cloning guests and changing registry/UUID/hostname info, and
8517 much else besides.
8518
8519 Libguestfs uses Linux kernel and qemu code, and can access any type of
8520 guest filesystem that Linux and qemu can, including but not limited
8521 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8522 schemes, qcow, qcow2, vmdk.
8523
8524 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8525 LVs, what filesystem is in each LV, etc.).  It can also run commands
8526 in the context of the guest.  Also you can access filesystems over FTP.
8527
8528 Errors which happen while using the API are turned into Python
8529 RuntimeError exceptions.
8530
8531 To create a guestfs handle you usually have to perform the following
8532 sequence of calls:
8533
8534 # Create the handle, call add_drive at least once, and possibly
8535 # several times if the guest has multiple block devices:
8536 g = guestfs.GuestFS ()
8537 g.add_drive (\"guest.img\")
8538
8539 # Launch the qemu subprocess and wait for it to become ready:
8540 g.launch ()
8541
8542 # Now you can issue commands, for example:
8543 logvols = g.lvs ()
8544
8545 \"\"\"
8546
8547 import libguestfsmod
8548
8549 class GuestFS:
8550     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8551
8552     def __init__ (self):
8553         \"\"\"Create a new libguestfs handle.\"\"\"
8554         self._o = libguestfsmod.create ()
8555
8556     def __del__ (self):
8557         libguestfsmod.close (self._o)
8558
8559 ";
8560
8561   List.iter (
8562     fun (name, style, _, flags, _, _, longdesc) ->
8563       pr "    def %s " name;
8564       generate_py_call_args ~handle:"self" (snd style);
8565       pr ":\n";
8566
8567       if not (List.mem NotInDocs flags) then (
8568         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8569         let doc =
8570           match fst style with
8571           | RErr | RInt _ | RInt64 _ | RBool _
8572           | RConstOptString _ | RConstString _
8573           | RString _ | RBufferOut _ -> doc
8574           | RStringList _ ->
8575               doc ^ "\n\nThis function returns a list of strings."
8576           | RStruct (_, typ) ->
8577               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8578           | RStructList (_, typ) ->
8579               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8580           | RHashtable _ ->
8581               doc ^ "\n\nThis function returns a dictionary." in
8582         let doc =
8583           if List.mem ProtocolLimitWarning flags then
8584             doc ^ "\n\n" ^ protocol_limit_warning
8585           else doc in
8586         let doc =
8587           if List.mem DangerWillRobinson flags then
8588             doc ^ "\n\n" ^ danger_will_robinson
8589           else doc in
8590         let doc =
8591           match deprecation_notice flags with
8592           | None -> doc
8593           | Some txt -> doc ^ "\n\n" ^ txt in
8594         let doc = pod2text ~width:60 name doc in
8595         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8596         let doc = String.concat "\n        " doc in
8597         pr "        u\"\"\"%s\"\"\"\n" doc;
8598       );
8599       pr "        return libguestfsmod.%s " name;
8600       generate_py_call_args ~handle:"self._o" (snd style);
8601       pr "\n";
8602       pr "\n";
8603   ) all_functions
8604
8605 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8606 and generate_py_call_args ~handle args =
8607   pr "(%s" handle;
8608   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8609   pr ")"
8610
8611 (* Useful if you need the longdesc POD text as plain text.  Returns a
8612  * list of lines.
8613  *
8614  * Because this is very slow (the slowest part of autogeneration),
8615  * we memoize the results.
8616  *)
8617 and pod2text ~width name longdesc =
8618   let key = width, name, longdesc in
8619   try Hashtbl.find pod2text_memo key
8620   with Not_found ->
8621     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8622     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8623     close_out chan;
8624     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8625     let chan = Unix.open_process_in cmd in
8626     let lines = ref [] in
8627     let rec loop i =
8628       let line = input_line chan in
8629       if i = 1 then             (* discard the first line of output *)
8630         loop (i+1)
8631       else (
8632         let line = triml line in
8633         lines := line :: !lines;
8634         loop (i+1)
8635       ) in
8636     let lines = try loop 1 with End_of_file -> List.rev !lines in
8637     Unix.unlink filename;
8638     (match Unix.close_process_in chan with
8639      | Unix.WEXITED 0 -> ()
8640      | Unix.WEXITED i ->
8641          failwithf "pod2text: process exited with non-zero status (%d)" i
8642      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8643          failwithf "pod2text: process signalled or stopped by signal %d" i
8644     );
8645     Hashtbl.add pod2text_memo key lines;
8646     pod2text_memo_updated ();
8647     lines
8648
8649 (* Generate ruby bindings. *)
8650 and generate_ruby_c () =
8651   generate_header CStyle LGPLv2;
8652
8653   pr "\
8654 #include <stdio.h>
8655 #include <stdlib.h>
8656
8657 #include <ruby.h>
8658
8659 #include \"guestfs.h\"
8660
8661 #include \"extconf.h\"
8662
8663 /* For Ruby < 1.9 */
8664 #ifndef RARRAY_LEN
8665 #define RARRAY_LEN(r) (RARRAY((r))->len)
8666 #endif
8667
8668 static VALUE m_guestfs;                 /* guestfs module */
8669 static VALUE c_guestfs;                 /* guestfs_h handle */
8670 static VALUE e_Error;                   /* used for all errors */
8671
8672 static void ruby_guestfs_free (void *p)
8673 {
8674   if (!p) return;
8675   guestfs_close ((guestfs_h *) p);
8676 }
8677
8678 static VALUE ruby_guestfs_create (VALUE m)
8679 {
8680   guestfs_h *g;
8681
8682   g = guestfs_create ();
8683   if (!g)
8684     rb_raise (e_Error, \"failed to create guestfs handle\");
8685
8686   /* Don't print error messages to stderr by default. */
8687   guestfs_set_error_handler (g, NULL, NULL);
8688
8689   /* Wrap it, and make sure the close function is called when the
8690    * handle goes away.
8691    */
8692   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8693 }
8694
8695 static VALUE ruby_guestfs_close (VALUE gv)
8696 {
8697   guestfs_h *g;
8698   Data_Get_Struct (gv, guestfs_h, g);
8699
8700   ruby_guestfs_free (g);
8701   DATA_PTR (gv) = NULL;
8702
8703   return Qnil;
8704 }
8705
8706 ";
8707
8708   List.iter (
8709     fun (name, style, _, _, _, _, _) ->
8710       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8711       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8712       pr ")\n";
8713       pr "{\n";
8714       pr "  guestfs_h *g;\n";
8715       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8716       pr "  if (!g)\n";
8717       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8718         name;
8719       pr "\n";
8720
8721       List.iter (
8722         function
8723         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8724             pr "  Check_Type (%sv, T_STRING);\n" n;
8725             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8726             pr "  if (!%s)\n" n;
8727             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8728             pr "              \"%s\", \"%s\");\n" n name
8729         | OptString n ->
8730             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8731         | StringList n | DeviceList n ->
8732             pr "  char **%s;\n" n;
8733             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8734             pr "  {\n";
8735             pr "    int i, len;\n";
8736             pr "    len = RARRAY_LEN (%sv);\n" n;
8737             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8738               n;
8739             pr "    for (i = 0; i < len; ++i) {\n";
8740             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8741             pr "      %s[i] = StringValueCStr (v);\n" n;
8742             pr "    }\n";
8743             pr "    %s[len] = NULL;\n" n;
8744             pr "  }\n";
8745         | Bool n ->
8746             pr "  int %s = RTEST (%sv);\n" n n
8747         | Int n ->
8748             pr "  int %s = NUM2INT (%sv);\n" n n
8749         | Int64 n ->
8750             pr "  long long %s = NUM2LL (%sv);\n" n n
8751       ) (snd style);
8752       pr "\n";
8753
8754       let error_code =
8755         match fst style with
8756         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8757         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8758         | RConstString _ | RConstOptString _ ->
8759             pr "  const char *r;\n"; "NULL"
8760         | RString _ -> pr "  char *r;\n"; "NULL"
8761         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8762         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8763         | RStructList (_, typ) ->
8764             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8765         | RBufferOut _ ->
8766             pr "  char *r;\n";
8767             pr "  size_t size;\n";
8768             "NULL" in
8769       pr "\n";
8770
8771       pr "  r = guestfs_%s " name;
8772       generate_c_call_args ~handle:"g" style;
8773       pr ";\n";
8774
8775       List.iter (
8776         function
8777         | Pathname _ | Device _ | Dev_or_Path _ | String _
8778         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8779         | StringList n | DeviceList n ->
8780             pr "  free (%s);\n" n
8781       ) (snd style);
8782
8783       pr "  if (r == %s)\n" error_code;
8784       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8785       pr "\n";
8786
8787       (match fst style with
8788        | RErr ->
8789            pr "  return Qnil;\n"
8790        | RInt _ | RBool _ ->
8791            pr "  return INT2NUM (r);\n"
8792        | RInt64 _ ->
8793            pr "  return ULL2NUM (r);\n"
8794        | RConstString _ ->
8795            pr "  return rb_str_new2 (r);\n";
8796        | RConstOptString _ ->
8797            pr "  if (r)\n";
8798            pr "    return rb_str_new2 (r);\n";
8799            pr "  else\n";
8800            pr "    return Qnil;\n";
8801        | RString _ ->
8802            pr "  VALUE rv = rb_str_new2 (r);\n";
8803            pr "  free (r);\n";
8804            pr "  return rv;\n";
8805        | RStringList _ ->
8806            pr "  int i, len = 0;\n";
8807            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8808            pr "  VALUE rv = rb_ary_new2 (len);\n";
8809            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8810            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8811            pr "    free (r[i]);\n";
8812            pr "  }\n";
8813            pr "  free (r);\n";
8814            pr "  return rv;\n"
8815        | RStruct (_, typ) ->
8816            let cols = cols_of_struct typ in
8817            generate_ruby_struct_code typ cols
8818        | RStructList (_, typ) ->
8819            let cols = cols_of_struct typ in
8820            generate_ruby_struct_list_code typ cols
8821        | RHashtable _ ->
8822            pr "  VALUE rv = rb_hash_new ();\n";
8823            pr "  int i;\n";
8824            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8825            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8826            pr "    free (r[i]);\n";
8827            pr "    free (r[i+1]);\n";
8828            pr "  }\n";
8829            pr "  free (r);\n";
8830            pr "  return rv;\n"
8831        | RBufferOut _ ->
8832            pr "  VALUE rv = rb_str_new (r, size);\n";
8833            pr "  free (r);\n";
8834            pr "  return rv;\n";
8835       );
8836
8837       pr "}\n";
8838       pr "\n"
8839   ) all_functions;
8840
8841   pr "\
8842 /* Initialize the module. */
8843 void Init__guestfs ()
8844 {
8845   m_guestfs = rb_define_module (\"Guestfs\");
8846   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8847   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8848
8849   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8850   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8851
8852 ";
8853   (* Define the rest of the methods. *)
8854   List.iter (
8855     fun (name, style, _, _, _, _, _) ->
8856       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8857       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8858   ) all_functions;
8859
8860   pr "}\n"
8861
8862 (* Ruby code to return a struct. *)
8863 and generate_ruby_struct_code typ cols =
8864   pr "  VALUE rv = rb_hash_new ();\n";
8865   List.iter (
8866     function
8867     | name, FString ->
8868         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8869     | name, FBuffer ->
8870         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8871     | name, FUUID ->
8872         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8873     | name, (FBytes|FUInt64) ->
8874         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8875     | name, FInt64 ->
8876         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8877     | name, FUInt32 ->
8878         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8879     | name, FInt32 ->
8880         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8881     | name, FOptPercent ->
8882         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8883     | name, FChar -> (* XXX wrong? *)
8884         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8885   ) cols;
8886   pr "  guestfs_free_%s (r);\n" typ;
8887   pr "  return rv;\n"
8888
8889 (* Ruby code to return a struct list. *)
8890 and generate_ruby_struct_list_code typ cols =
8891   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8892   pr "  int i;\n";
8893   pr "  for (i = 0; i < r->len; ++i) {\n";
8894   pr "    VALUE hv = rb_hash_new ();\n";
8895   List.iter (
8896     function
8897     | name, FString ->
8898         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8899     | name, FBuffer ->
8900         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
8901     | name, FUUID ->
8902         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8903     | name, (FBytes|FUInt64) ->
8904         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8905     | name, FInt64 ->
8906         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8907     | name, FUInt32 ->
8908         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8909     | name, FInt32 ->
8910         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8911     | name, FOptPercent ->
8912         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8913     | name, FChar -> (* XXX wrong? *)
8914         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8915   ) cols;
8916   pr "    rb_ary_push (rv, hv);\n";
8917   pr "  }\n";
8918   pr "  guestfs_free_%s_list (r);\n" typ;
8919   pr "  return rv;\n"
8920
8921 (* Generate Java bindings GuestFS.java file. *)
8922 and generate_java_java () =
8923   generate_header CStyle LGPLv2;
8924
8925   pr "\
8926 package com.redhat.et.libguestfs;
8927
8928 import java.util.HashMap;
8929 import com.redhat.et.libguestfs.LibGuestFSException;
8930 import com.redhat.et.libguestfs.PV;
8931 import com.redhat.et.libguestfs.VG;
8932 import com.redhat.et.libguestfs.LV;
8933 import com.redhat.et.libguestfs.Stat;
8934 import com.redhat.et.libguestfs.StatVFS;
8935 import com.redhat.et.libguestfs.IntBool;
8936 import com.redhat.et.libguestfs.Dirent;
8937
8938 /**
8939  * The GuestFS object is a libguestfs handle.
8940  *
8941  * @author rjones
8942  */
8943 public class GuestFS {
8944   // Load the native code.
8945   static {
8946     System.loadLibrary (\"guestfs_jni\");
8947   }
8948
8949   /**
8950    * The native guestfs_h pointer.
8951    */
8952   long g;
8953
8954   /**
8955    * Create a libguestfs handle.
8956    *
8957    * @throws LibGuestFSException
8958    */
8959   public GuestFS () throws LibGuestFSException
8960   {
8961     g = _create ();
8962   }
8963   private native long _create () throws LibGuestFSException;
8964
8965   /**
8966    * Close a libguestfs handle.
8967    *
8968    * You can also leave handles to be collected by the garbage
8969    * collector, but this method ensures that the resources used
8970    * by the handle are freed up immediately.  If you call any
8971    * other methods after closing the handle, you will get an
8972    * exception.
8973    *
8974    * @throws LibGuestFSException
8975    */
8976   public void close () throws LibGuestFSException
8977   {
8978     if (g != 0)
8979       _close (g);
8980     g = 0;
8981   }
8982   private native void _close (long g) throws LibGuestFSException;
8983
8984   public void finalize () throws LibGuestFSException
8985   {
8986     close ();
8987   }
8988
8989 ";
8990
8991   List.iter (
8992     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8993       if not (List.mem NotInDocs flags); then (
8994         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8995         let doc =
8996           if List.mem ProtocolLimitWarning flags then
8997             doc ^ "\n\n" ^ protocol_limit_warning
8998           else doc in
8999         let doc =
9000           if List.mem DangerWillRobinson flags then
9001             doc ^ "\n\n" ^ danger_will_robinson
9002           else doc in
9003         let doc =
9004           match deprecation_notice flags with
9005           | None -> doc
9006           | Some txt -> doc ^ "\n\n" ^ txt in
9007         let doc = pod2text ~width:60 name doc in
9008         let doc = List.map (            (* RHBZ#501883 *)
9009           function
9010           | "" -> "<p>"
9011           | nonempty -> nonempty
9012         ) doc in
9013         let doc = String.concat "\n   * " doc in
9014
9015         pr "  /**\n";
9016         pr "   * %s\n" shortdesc;
9017         pr "   * <p>\n";
9018         pr "   * %s\n" doc;
9019         pr "   * @throws LibGuestFSException\n";
9020         pr "   */\n";
9021         pr "  ";
9022       );
9023       generate_java_prototype ~public:true ~semicolon:false name style;
9024       pr "\n";
9025       pr "  {\n";
9026       pr "    if (g == 0)\n";
9027       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9028         name;
9029       pr "    ";
9030       if fst style <> RErr then pr "return ";
9031       pr "_%s " name;
9032       generate_java_call_args ~handle:"g" (snd style);
9033       pr ";\n";
9034       pr "  }\n";
9035       pr "  ";
9036       generate_java_prototype ~privat:true ~native:true name style;
9037       pr "\n";
9038       pr "\n";
9039   ) all_functions;
9040
9041   pr "}\n"
9042
9043 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9044 and generate_java_call_args ~handle args =
9045   pr "(%s" handle;
9046   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9047   pr ")"
9048
9049 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9050     ?(semicolon=true) name style =
9051   if privat then pr "private ";
9052   if public then pr "public ";
9053   if native then pr "native ";
9054
9055   (* return type *)
9056   (match fst style with
9057    | RErr -> pr "void ";
9058    | RInt _ -> pr "int ";
9059    | RInt64 _ -> pr "long ";
9060    | RBool _ -> pr "boolean ";
9061    | RConstString _ | RConstOptString _ | RString _
9062    | RBufferOut _ -> pr "String ";
9063    | RStringList _ -> pr "String[] ";
9064    | RStruct (_, typ) ->
9065        let name = java_name_of_struct typ in
9066        pr "%s " name;
9067    | RStructList (_, typ) ->
9068        let name = java_name_of_struct typ in
9069        pr "%s[] " name;
9070    | RHashtable _ -> pr "HashMap<String,String> ";
9071   );
9072
9073   if native then pr "_%s " name else pr "%s " name;
9074   pr "(";
9075   let needs_comma = ref false in
9076   if native then (
9077     pr "long g";
9078     needs_comma := true
9079   );
9080
9081   (* args *)
9082   List.iter (
9083     fun arg ->
9084       if !needs_comma then pr ", ";
9085       needs_comma := true;
9086
9087       match arg with
9088       | Pathname n
9089       | Device n | Dev_or_Path n
9090       | String n
9091       | OptString n
9092       | FileIn n
9093       | FileOut n ->
9094           pr "String %s" n
9095       | StringList n | DeviceList n ->
9096           pr "String[] %s" n
9097       | Bool n ->
9098           pr "boolean %s" n
9099       | Int n ->
9100           pr "int %s" n
9101       | Int64 n ->
9102           pr "long %s" n
9103   ) (snd style);
9104
9105   pr ")\n";
9106   pr "    throws LibGuestFSException";
9107   if semicolon then pr ";"
9108
9109 and generate_java_struct jtyp cols =
9110   generate_header CStyle LGPLv2;
9111
9112   pr "\
9113 package com.redhat.et.libguestfs;
9114
9115 /**
9116  * Libguestfs %s structure.
9117  *
9118  * @author rjones
9119  * @see GuestFS
9120  */
9121 public class %s {
9122 " jtyp jtyp;
9123
9124   List.iter (
9125     function
9126     | name, FString
9127     | name, FUUID
9128     | name, FBuffer -> pr "  public String %s;\n" name
9129     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9130     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9131     | name, FChar -> pr "  public char %s;\n" name
9132     | name, FOptPercent ->
9133         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9134         pr "  public float %s;\n" name
9135   ) cols;
9136
9137   pr "}\n"
9138
9139 and generate_java_c () =
9140   generate_header CStyle LGPLv2;
9141
9142   pr "\
9143 #include <stdio.h>
9144 #include <stdlib.h>
9145 #include <string.h>
9146
9147 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9148 #include \"guestfs.h\"
9149
9150 /* Note that this function returns.  The exception is not thrown
9151  * until after the wrapper function returns.
9152  */
9153 static void
9154 throw_exception (JNIEnv *env, const char *msg)
9155 {
9156   jclass cl;
9157   cl = (*env)->FindClass (env,
9158                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9159   (*env)->ThrowNew (env, cl, msg);
9160 }
9161
9162 JNIEXPORT jlong JNICALL
9163 Java_com_redhat_et_libguestfs_GuestFS__1create
9164   (JNIEnv *env, jobject obj)
9165 {
9166   guestfs_h *g;
9167
9168   g = guestfs_create ();
9169   if (g == NULL) {
9170     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9171     return 0;
9172   }
9173   guestfs_set_error_handler (g, NULL, NULL);
9174   return (jlong) (long) g;
9175 }
9176
9177 JNIEXPORT void JNICALL
9178 Java_com_redhat_et_libguestfs_GuestFS__1close
9179   (JNIEnv *env, jobject obj, jlong jg)
9180 {
9181   guestfs_h *g = (guestfs_h *) (long) jg;
9182   guestfs_close (g);
9183 }
9184
9185 ";
9186
9187   List.iter (
9188     fun (name, style, _, _, _, _, _) ->
9189       pr "JNIEXPORT ";
9190       (match fst style with
9191        | RErr -> pr "void ";
9192        | RInt _ -> pr "jint ";
9193        | RInt64 _ -> pr "jlong ";
9194        | RBool _ -> pr "jboolean ";
9195        | RConstString _ | RConstOptString _ | RString _
9196        | RBufferOut _ -> pr "jstring ";
9197        | RStruct _ | RHashtable _ ->
9198            pr "jobject ";
9199        | RStringList _ | RStructList _ ->
9200            pr "jobjectArray ";
9201       );
9202       pr "JNICALL\n";
9203       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9204       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9205       pr "\n";
9206       pr "  (JNIEnv *env, jobject obj, jlong jg";
9207       List.iter (
9208         function
9209         | Pathname n
9210         | Device n | Dev_or_Path n
9211         | String n
9212         | OptString n
9213         | FileIn n
9214         | FileOut n ->
9215             pr ", jstring j%s" n
9216         | StringList n | DeviceList n ->
9217             pr ", jobjectArray j%s" n
9218         | Bool n ->
9219             pr ", jboolean j%s" n
9220         | Int n ->
9221             pr ", jint j%s" n
9222         | Int64 n ->
9223             pr ", jlong j%s" n
9224       ) (snd style);
9225       pr ")\n";
9226       pr "{\n";
9227       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9228       let error_code, no_ret =
9229         match fst style with
9230         | RErr -> pr "  int r;\n"; "-1", ""
9231         | RBool _
9232         | RInt _ -> pr "  int r;\n"; "-1", "0"
9233         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9234         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9235         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9236         | RString _ ->
9237             pr "  jstring jr;\n";
9238             pr "  char *r;\n"; "NULL", "NULL"
9239         | RStringList _ ->
9240             pr "  jobjectArray jr;\n";
9241             pr "  int r_len;\n";
9242             pr "  jclass cl;\n";
9243             pr "  jstring jstr;\n";
9244             pr "  char **r;\n"; "NULL", "NULL"
9245         | RStruct (_, typ) ->
9246             pr "  jobject jr;\n";
9247             pr "  jclass cl;\n";
9248             pr "  jfieldID fl;\n";
9249             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9250         | RStructList (_, typ) ->
9251             pr "  jobjectArray jr;\n";
9252             pr "  jclass cl;\n";
9253             pr "  jfieldID fl;\n";
9254             pr "  jobject jfl;\n";
9255             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9256         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9257         | RBufferOut _ ->
9258             pr "  jstring jr;\n";
9259             pr "  char *r;\n";
9260             pr "  size_t size;\n";
9261             "NULL", "NULL" in
9262       List.iter (
9263         function
9264         | Pathname n
9265         | Device n | Dev_or_Path n
9266         | String n
9267         | OptString n
9268         | FileIn n
9269         | FileOut n ->
9270             pr "  const char *%s;\n" n
9271         | StringList n | DeviceList n ->
9272             pr "  int %s_len;\n" n;
9273             pr "  const char **%s;\n" n
9274         | Bool n
9275         | Int n ->
9276             pr "  int %s;\n" n
9277         | Int64 n ->
9278             pr "  int64_t %s;\n" n
9279       ) (snd style);
9280
9281       let needs_i =
9282         (match fst style with
9283          | RStringList _ | RStructList _ -> true
9284          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9285          | RConstOptString _
9286          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9287           List.exists (function
9288                        | StringList _ -> true
9289                        | DeviceList _ -> true
9290                        | _ -> false) (snd style) in
9291       if needs_i then
9292         pr "  int i;\n";
9293
9294       pr "\n";
9295
9296       (* Get the parameters. *)
9297       List.iter (
9298         function
9299         | Pathname n
9300         | Device n | Dev_or_Path n
9301         | String n
9302         | FileIn n
9303         | FileOut n ->
9304             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9305         | OptString n ->
9306             (* This is completely undocumented, but Java null becomes
9307              * a NULL parameter.
9308              *)
9309             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9310         | StringList n | DeviceList n ->
9311             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9312             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9313             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9314             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9315               n;
9316             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9317             pr "  }\n";
9318             pr "  %s[%s_len] = NULL;\n" n n;
9319         | Bool n
9320         | Int n
9321         | Int64 n ->
9322             pr "  %s = j%s;\n" n n
9323       ) (snd style);
9324
9325       (* Make the call. *)
9326       pr "  r = guestfs_%s " name;
9327       generate_c_call_args ~handle:"g" style;
9328       pr ";\n";
9329
9330       (* Release the parameters. *)
9331       List.iter (
9332         function
9333         | Pathname n
9334         | Device n | Dev_or_Path n
9335         | String n
9336         | FileIn n
9337         | FileOut n ->
9338             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9339         | OptString n ->
9340             pr "  if (j%s)\n" n;
9341             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9342         | StringList n | DeviceList n ->
9343             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9344             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9345               n;
9346             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9347             pr "  }\n";
9348             pr "  free (%s);\n" n
9349         | Bool n
9350         | Int n
9351         | Int64 n -> ()
9352       ) (snd style);
9353
9354       (* Check for errors. *)
9355       pr "  if (r == %s) {\n" error_code;
9356       pr "    throw_exception (env, guestfs_last_error (g));\n";
9357       pr "    return %s;\n" no_ret;
9358       pr "  }\n";
9359
9360       (* Return value. *)
9361       (match fst style with
9362        | RErr -> ()
9363        | RInt _ -> pr "  return (jint) r;\n"
9364        | RBool _ -> pr "  return (jboolean) r;\n"
9365        | RInt64 _ -> pr "  return (jlong) r;\n"
9366        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9367        | RConstOptString _ ->
9368            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9369        | RString _ ->
9370            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9371            pr "  free (r);\n";
9372            pr "  return jr;\n"
9373        | RStringList _ ->
9374            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9375            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9376            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9377            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9378            pr "  for (i = 0; i < r_len; ++i) {\n";
9379            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9380            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9381            pr "    free (r[i]);\n";
9382            pr "  }\n";
9383            pr "  free (r);\n";
9384            pr "  return jr;\n"
9385        | RStruct (_, typ) ->
9386            let jtyp = java_name_of_struct typ in
9387            let cols = cols_of_struct typ in
9388            generate_java_struct_return typ jtyp cols
9389        | RStructList (_, typ) ->
9390            let jtyp = java_name_of_struct typ in
9391            let cols = cols_of_struct typ in
9392            generate_java_struct_list_return typ jtyp cols
9393        | RHashtable _ ->
9394            (* XXX *)
9395            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9396            pr "  return NULL;\n"
9397        | RBufferOut _ ->
9398            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9399            pr "  free (r);\n";
9400            pr "  return jr;\n"
9401       );
9402
9403       pr "}\n";
9404       pr "\n"
9405   ) all_functions
9406
9407 and generate_java_struct_return typ jtyp cols =
9408   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9409   pr "  jr = (*env)->AllocObject (env, cl);\n";
9410   List.iter (
9411     function
9412     | name, FString ->
9413         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9414         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9415     | name, FUUID ->
9416         pr "  {\n";
9417         pr "    char s[33];\n";
9418         pr "    memcpy (s, r->%s, 32);\n" name;
9419         pr "    s[32] = 0;\n";
9420         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9421         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9422         pr "  }\n";
9423     | name, FBuffer ->
9424         pr "  {\n";
9425         pr "    int len = r->%s_len;\n" name;
9426         pr "    char s[len+1];\n";
9427         pr "    memcpy (s, r->%s, len);\n" name;
9428         pr "    s[len] = 0;\n";
9429         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9430         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9431         pr "  }\n";
9432     | name, (FBytes|FUInt64|FInt64) ->
9433         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9434         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9435     | name, (FUInt32|FInt32) ->
9436         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9437         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9438     | name, FOptPercent ->
9439         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9440         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9441     | name, FChar ->
9442         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9443         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9444   ) cols;
9445   pr "  free (r);\n";
9446   pr "  return jr;\n"
9447
9448 and generate_java_struct_list_return typ jtyp cols =
9449   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9450   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9451   pr "  for (i = 0; i < r->len; ++i) {\n";
9452   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9453   List.iter (
9454     function
9455     | name, FString ->
9456         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9457         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9458     | name, FUUID ->
9459         pr "    {\n";
9460         pr "      char s[33];\n";
9461         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9462         pr "      s[32] = 0;\n";
9463         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9464         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9465         pr "    }\n";
9466     | name, FBuffer ->
9467         pr "    {\n";
9468         pr "      int len = r->val[i].%s_len;\n" name;
9469         pr "      char s[len+1];\n";
9470         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9471         pr "      s[len] = 0;\n";
9472         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9473         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9474         pr "    }\n";
9475     | name, (FBytes|FUInt64|FInt64) ->
9476         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9477         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9478     | name, (FUInt32|FInt32) ->
9479         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9480         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9481     | name, FOptPercent ->
9482         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9483         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9484     | name, FChar ->
9485         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9486         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9487   ) cols;
9488   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9489   pr "  }\n";
9490   pr "  guestfs_free_%s_list (r);\n" typ;
9491   pr "  return jr;\n"
9492
9493 and generate_java_makefile_inc () =
9494   generate_header HashStyle GPLv2;
9495
9496   pr "java_built_sources = \\\n";
9497   List.iter (
9498     fun (typ, jtyp) ->
9499         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9500   ) java_structs;
9501   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9502
9503 and generate_haskell_hs () =
9504   generate_header HaskellStyle LGPLv2;
9505
9506   (* XXX We only know how to generate partial FFI for Haskell
9507    * at the moment.  Please help out!
9508    *)
9509   let can_generate style =
9510     match style with
9511     | RErr, _
9512     | RInt _, _
9513     | RInt64 _, _ -> true
9514     | RBool _, _
9515     | RConstString _, _
9516     | RConstOptString _, _
9517     | RString _, _
9518     | RStringList _, _
9519     | RStruct _, _
9520     | RStructList _, _
9521     | RHashtable _, _
9522     | RBufferOut _, _ -> false in
9523
9524   pr "\
9525 {-# INCLUDE <guestfs.h> #-}
9526 {-# LANGUAGE ForeignFunctionInterface #-}
9527
9528 module Guestfs (
9529   create";
9530
9531   (* List out the names of the actions we want to export. *)
9532   List.iter (
9533     fun (name, style, _, _, _, _, _) ->
9534       if can_generate style then pr ",\n  %s" name
9535   ) all_functions;
9536
9537   pr "
9538   ) where
9539
9540 -- Unfortunately some symbols duplicate ones already present
9541 -- in Prelude.  We don't know which, so we hard-code a list
9542 -- here.
9543 import Prelude hiding (truncate)
9544
9545 import Foreign
9546 import Foreign.C
9547 import Foreign.C.Types
9548 import IO
9549 import Control.Exception
9550 import Data.Typeable
9551
9552 data GuestfsS = GuestfsS            -- represents the opaque C struct
9553 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9554 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9555
9556 -- XXX define properly later XXX
9557 data PV = PV
9558 data VG = VG
9559 data LV = LV
9560 data IntBool = IntBool
9561 data Stat = Stat
9562 data StatVFS = StatVFS
9563 data Hashtable = Hashtable
9564
9565 foreign import ccall unsafe \"guestfs_create\" c_create
9566   :: IO GuestfsP
9567 foreign import ccall unsafe \"&guestfs_close\" c_close
9568   :: FunPtr (GuestfsP -> IO ())
9569 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9570   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9571
9572 create :: IO GuestfsH
9573 create = do
9574   p <- c_create
9575   c_set_error_handler p nullPtr nullPtr
9576   h <- newForeignPtr c_close p
9577   return h
9578
9579 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9580   :: GuestfsP -> IO CString
9581
9582 -- last_error :: GuestfsH -> IO (Maybe String)
9583 -- last_error h = do
9584 --   str <- withForeignPtr h (\\p -> c_last_error p)
9585 --   maybePeek peekCString str
9586
9587 last_error :: GuestfsH -> IO (String)
9588 last_error h = do
9589   str <- withForeignPtr h (\\p -> c_last_error p)
9590   if (str == nullPtr)
9591     then return \"no error\"
9592     else peekCString str
9593
9594 ";
9595
9596   (* Generate wrappers for each foreign function. *)
9597   List.iter (
9598     fun (name, style, _, _, _, _, _) ->
9599       if can_generate style then (
9600         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9601         pr "  :: ";
9602         generate_haskell_prototype ~handle:"GuestfsP" style;
9603         pr "\n";
9604         pr "\n";
9605         pr "%s :: " name;
9606         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9607         pr "\n";
9608         pr "%s %s = do\n" name
9609           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9610         pr "  r <- ";
9611         (* Convert pointer arguments using with* functions. *)
9612         List.iter (
9613           function
9614           | FileIn n
9615           | FileOut n
9616           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9617           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9618           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9619           | Bool _ | Int _ | Int64 _ -> ()
9620         ) (snd style);
9621         (* Convert integer arguments. *)
9622         let args =
9623           List.map (
9624             function
9625             | Bool n -> sprintf "(fromBool %s)" n
9626             | Int n -> sprintf "(fromIntegral %s)" n
9627             | Int64 n -> sprintf "(fromIntegral %s)" n
9628             | FileIn n | FileOut n
9629             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9630           ) (snd style) in
9631         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9632           (String.concat " " ("p" :: args));
9633         (match fst style with
9634          | RErr | RInt _ | RInt64 _ | RBool _ ->
9635              pr "  if (r == -1)\n";
9636              pr "    then do\n";
9637              pr "      err <- last_error h\n";
9638              pr "      fail err\n";
9639          | RConstString _ | RConstOptString _ | RString _
9640          | RStringList _ | RStruct _
9641          | RStructList _ | RHashtable _ | RBufferOut _ ->
9642              pr "  if (r == nullPtr)\n";
9643              pr "    then do\n";
9644              pr "      err <- last_error h\n";
9645              pr "      fail err\n";
9646         );
9647         (match fst style with
9648          | RErr ->
9649              pr "    else return ()\n"
9650          | RInt _ ->
9651              pr "    else return (fromIntegral r)\n"
9652          | RInt64 _ ->
9653              pr "    else return (fromIntegral r)\n"
9654          | RBool _ ->
9655              pr "    else return (toBool r)\n"
9656          | RConstString _
9657          | RConstOptString _
9658          | RString _
9659          | RStringList _
9660          | RStruct _
9661          | RStructList _
9662          | RHashtable _
9663          | RBufferOut _ ->
9664              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9665         );
9666         pr "\n";
9667       )
9668   ) all_functions
9669
9670 and generate_haskell_prototype ~handle ?(hs = false) style =
9671   pr "%s -> " handle;
9672   let string = if hs then "String" else "CString" in
9673   let int = if hs then "Int" else "CInt" in
9674   let bool = if hs then "Bool" else "CInt" in
9675   let int64 = if hs then "Integer" else "Int64" in
9676   List.iter (
9677     fun arg ->
9678       (match arg with
9679        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9680        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9681        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9682        | Bool _ -> pr "%s" bool
9683        | Int _ -> pr "%s" int
9684        | Int64 _ -> pr "%s" int
9685        | FileIn _ -> pr "%s" string
9686        | FileOut _ -> pr "%s" string
9687       );
9688       pr " -> ";
9689   ) (snd style);
9690   pr "IO (";
9691   (match fst style with
9692    | RErr -> if not hs then pr "CInt"
9693    | RInt _ -> pr "%s" int
9694    | RInt64 _ -> pr "%s" int64
9695    | RBool _ -> pr "%s" bool
9696    | RConstString _ -> pr "%s" string
9697    | RConstOptString _ -> pr "Maybe %s" string
9698    | RString _ -> pr "%s" string
9699    | RStringList _ -> pr "[%s]" string
9700    | RStruct (_, typ) ->
9701        let name = java_name_of_struct typ in
9702        pr "%s" name
9703    | RStructList (_, typ) ->
9704        let name = java_name_of_struct typ in
9705        pr "[%s]" name
9706    | RHashtable _ -> pr "Hashtable"
9707    | RBufferOut _ -> pr "%s" string
9708   );
9709   pr ")"
9710
9711 and generate_bindtests () =
9712   generate_header CStyle LGPLv2;
9713
9714   pr "\
9715 #include <stdio.h>
9716 #include <stdlib.h>
9717 #include <inttypes.h>
9718 #include <string.h>
9719
9720 #include \"guestfs.h\"
9721 #include \"guestfs-internal.h\"
9722 #include \"guestfs-internal-actions.h\"
9723 #include \"guestfs_protocol.h\"
9724
9725 #define error guestfs_error
9726 #define safe_calloc guestfs_safe_calloc
9727 #define safe_malloc guestfs_safe_malloc
9728
9729 static void
9730 print_strings (char *const *argv)
9731 {
9732   int argc;
9733
9734   printf (\"[\");
9735   for (argc = 0; argv[argc] != NULL; ++argc) {
9736     if (argc > 0) printf (\", \");
9737     printf (\"\\\"%%s\\\"\", argv[argc]);
9738   }
9739   printf (\"]\\n\");
9740 }
9741
9742 /* The test0 function prints its parameters to stdout. */
9743 ";
9744
9745   let test0, tests =
9746     match test_functions with
9747     | [] -> assert false
9748     | test0 :: tests -> test0, tests in
9749
9750   let () =
9751     let (name, style, _, _, _, _, _) = test0 in
9752     generate_prototype ~extern:false ~semicolon:false ~newline:true
9753       ~handle:"g" ~prefix:"guestfs__" name style;
9754     pr "{\n";
9755     List.iter (
9756       function
9757       | Pathname n
9758       | Device n | Dev_or_Path n
9759       | String n
9760       | FileIn n
9761       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9762       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9763       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9764       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9765       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9766       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9767     ) (snd style);
9768     pr "  /* Java changes stdout line buffering so we need this: */\n";
9769     pr "  fflush (stdout);\n";
9770     pr "  return 0;\n";
9771     pr "}\n";
9772     pr "\n" in
9773
9774   List.iter (
9775     fun (name, style, _, _, _, _, _) ->
9776       if String.sub name (String.length name - 3) 3 <> "err" then (
9777         pr "/* Test normal return. */\n";
9778         generate_prototype ~extern:false ~semicolon:false ~newline:true
9779           ~handle:"g" ~prefix:"guestfs__" name style;
9780         pr "{\n";
9781         (match fst style with
9782          | RErr ->
9783              pr "  return 0;\n"
9784          | RInt _ ->
9785              pr "  int r;\n";
9786              pr "  sscanf (val, \"%%d\", &r);\n";
9787              pr "  return r;\n"
9788          | RInt64 _ ->
9789              pr "  int64_t r;\n";
9790              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9791              pr "  return r;\n"
9792          | RBool _ ->
9793              pr "  return STREQ (val, \"true\");\n"
9794          | RConstString _
9795          | RConstOptString _ ->
9796              (* Can't return the input string here.  Return a static
9797               * string so we ensure we get a segfault if the caller
9798               * tries to free it.
9799               *)
9800              pr "  return \"static string\";\n"
9801          | RString _ ->
9802              pr "  return strdup (val);\n"
9803          | RStringList _ ->
9804              pr "  char **strs;\n";
9805              pr "  int n, i;\n";
9806              pr "  sscanf (val, \"%%d\", &n);\n";
9807              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9808              pr "  for (i = 0; i < n; ++i) {\n";
9809              pr "    strs[i] = safe_malloc (g, 16);\n";
9810              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9811              pr "  }\n";
9812              pr "  strs[n] = NULL;\n";
9813              pr "  return strs;\n"
9814          | RStruct (_, typ) ->
9815              pr "  struct guestfs_%s *r;\n" typ;
9816              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9817              pr "  return r;\n"
9818          | RStructList (_, typ) ->
9819              pr "  struct guestfs_%s_list *r;\n" typ;
9820              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9821              pr "  sscanf (val, \"%%d\", &r->len);\n";
9822              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9823              pr "  return r;\n"
9824          | RHashtable _ ->
9825              pr "  char **strs;\n";
9826              pr "  int n, i;\n";
9827              pr "  sscanf (val, \"%%d\", &n);\n";
9828              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9829              pr "  for (i = 0; i < n; ++i) {\n";
9830              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9831              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9832              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9833              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9834              pr "  }\n";
9835              pr "  strs[n*2] = NULL;\n";
9836              pr "  return strs;\n"
9837          | RBufferOut _ ->
9838              pr "  return strdup (val);\n"
9839         );
9840         pr "}\n";
9841         pr "\n"
9842       ) else (
9843         pr "/* Test error return. */\n";
9844         generate_prototype ~extern:false ~semicolon:false ~newline:true
9845           ~handle:"g" ~prefix:"guestfs__" name style;
9846         pr "{\n";
9847         pr "  error (g, \"error\");\n";
9848         (match fst style with
9849          | RErr | RInt _ | RInt64 _ | RBool _ ->
9850              pr "  return -1;\n"
9851          | RConstString _ | RConstOptString _
9852          | RString _ | RStringList _ | RStruct _
9853          | RStructList _
9854          | RHashtable _
9855          | RBufferOut _ ->
9856              pr "  return NULL;\n"
9857         );
9858         pr "}\n";
9859         pr "\n"
9860       )
9861   ) tests
9862
9863 and generate_ocaml_bindtests () =
9864   generate_header OCamlStyle GPLv2;
9865
9866   pr "\
9867 let () =
9868   let g = Guestfs.create () in
9869 ";
9870
9871   let mkargs args =
9872     String.concat " " (
9873       List.map (
9874         function
9875         | CallString s -> "\"" ^ s ^ "\""
9876         | CallOptString None -> "None"
9877         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9878         | CallStringList xs ->
9879             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9880         | CallInt i when i >= 0 -> string_of_int i
9881         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9882         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9883         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9884         | CallBool b -> string_of_bool b
9885       ) args
9886     )
9887   in
9888
9889   generate_lang_bindtests (
9890     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9891   );
9892
9893   pr "print_endline \"EOF\"\n"
9894
9895 and generate_perl_bindtests () =
9896   pr "#!/usr/bin/perl -w\n";
9897   generate_header HashStyle GPLv2;
9898
9899   pr "\
9900 use strict;
9901
9902 use Sys::Guestfs;
9903
9904 my $g = Sys::Guestfs->new ();
9905 ";
9906
9907   let mkargs args =
9908     String.concat ", " (
9909       List.map (
9910         function
9911         | CallString s -> "\"" ^ s ^ "\""
9912         | CallOptString None -> "undef"
9913         | CallOptString (Some s) -> sprintf "\"%s\"" s
9914         | CallStringList xs ->
9915             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9916         | CallInt i -> string_of_int i
9917         | CallInt64 i -> Int64.to_string i
9918         | CallBool b -> if b then "1" else "0"
9919       ) args
9920     )
9921   in
9922
9923   generate_lang_bindtests (
9924     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9925   );
9926
9927   pr "print \"EOF\\n\"\n"
9928
9929 and generate_python_bindtests () =
9930   generate_header HashStyle GPLv2;
9931
9932   pr "\
9933 import guestfs
9934
9935 g = guestfs.GuestFS ()
9936 ";
9937
9938   let mkargs args =
9939     String.concat ", " (
9940       List.map (
9941         function
9942         | CallString s -> "\"" ^ s ^ "\""
9943         | CallOptString None -> "None"
9944         | CallOptString (Some s) -> sprintf "\"%s\"" s
9945         | CallStringList xs ->
9946             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9947         | CallInt i -> string_of_int i
9948         | CallInt64 i -> Int64.to_string i
9949         | CallBool b -> if b then "1" else "0"
9950       ) args
9951     )
9952   in
9953
9954   generate_lang_bindtests (
9955     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9956   );
9957
9958   pr "print \"EOF\"\n"
9959
9960 and generate_ruby_bindtests () =
9961   generate_header HashStyle GPLv2;
9962
9963   pr "\
9964 require 'guestfs'
9965
9966 g = Guestfs::create()
9967 ";
9968
9969   let mkargs args =
9970     String.concat ", " (
9971       List.map (
9972         function
9973         | CallString s -> "\"" ^ s ^ "\""
9974         | CallOptString None -> "nil"
9975         | CallOptString (Some s) -> sprintf "\"%s\"" s
9976         | CallStringList xs ->
9977             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9978         | CallInt i -> string_of_int i
9979         | CallInt64 i -> Int64.to_string i
9980         | CallBool b -> string_of_bool b
9981       ) args
9982     )
9983   in
9984
9985   generate_lang_bindtests (
9986     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9987   );
9988
9989   pr "print \"EOF\\n\"\n"
9990
9991 and generate_java_bindtests () =
9992   generate_header CStyle GPLv2;
9993
9994   pr "\
9995 import com.redhat.et.libguestfs.*;
9996
9997 public class Bindtests {
9998     public static void main (String[] argv)
9999     {
10000         try {
10001             GuestFS g = new GuestFS ();
10002 ";
10003
10004   let mkargs args =
10005     String.concat ", " (
10006       List.map (
10007         function
10008         | CallString s -> "\"" ^ s ^ "\""
10009         | CallOptString None -> "null"
10010         | CallOptString (Some s) -> sprintf "\"%s\"" s
10011         | CallStringList xs ->
10012             "new String[]{" ^
10013               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10014         | CallInt i -> string_of_int i
10015         | CallInt64 i -> Int64.to_string i
10016         | CallBool b -> string_of_bool b
10017       ) args
10018     )
10019   in
10020
10021   generate_lang_bindtests (
10022     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10023   );
10024
10025   pr "
10026             System.out.println (\"EOF\");
10027         }
10028         catch (Exception exn) {
10029             System.err.println (exn);
10030             System.exit (1);
10031         }
10032     }
10033 }
10034 "
10035
10036 and generate_haskell_bindtests () =
10037   generate_header HaskellStyle GPLv2;
10038
10039   pr "\
10040 module Bindtests where
10041 import qualified Guestfs
10042
10043 main = do
10044   g <- Guestfs.create
10045 ";
10046
10047   let mkargs args =
10048     String.concat " " (
10049       List.map (
10050         function
10051         | CallString s -> "\"" ^ s ^ "\""
10052         | CallOptString None -> "Nothing"
10053         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10054         | CallStringList xs ->
10055             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10056         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10057         | CallInt i -> string_of_int i
10058         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10059         | CallInt64 i -> Int64.to_string i
10060         | CallBool true -> "True"
10061         | CallBool false -> "False"
10062       ) args
10063     )
10064   in
10065
10066   generate_lang_bindtests (
10067     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10068   );
10069
10070   pr "  putStrLn \"EOF\"\n"
10071
10072 (* Language-independent bindings tests - we do it this way to
10073  * ensure there is parity in testing bindings across all languages.
10074  *)
10075 and generate_lang_bindtests call =
10076   call "test0" [CallString "abc"; CallOptString (Some "def");
10077                 CallStringList []; CallBool false;
10078                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10079   call "test0" [CallString "abc"; CallOptString None;
10080                 CallStringList []; CallBool false;
10081                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10082   call "test0" [CallString ""; CallOptString (Some "def");
10083                 CallStringList []; CallBool false;
10084                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10085   call "test0" [CallString ""; CallOptString (Some "");
10086                 CallStringList []; CallBool false;
10087                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10088   call "test0" [CallString "abc"; CallOptString (Some "def");
10089                 CallStringList ["1"]; CallBool false;
10090                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10091   call "test0" [CallString "abc"; CallOptString (Some "def");
10092                 CallStringList ["1"; "2"]; CallBool false;
10093                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10094   call "test0" [CallString "abc"; CallOptString (Some "def");
10095                 CallStringList ["1"]; CallBool true;
10096                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10097   call "test0" [CallString "abc"; CallOptString (Some "def");
10098                 CallStringList ["1"]; CallBool false;
10099                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10100   call "test0" [CallString "abc"; CallOptString (Some "def");
10101                 CallStringList ["1"]; CallBool false;
10102                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10103   call "test0" [CallString "abc"; CallOptString (Some "def");
10104                 CallStringList ["1"]; CallBool false;
10105                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10106   call "test0" [CallString "abc"; CallOptString (Some "def");
10107                 CallStringList ["1"]; CallBool false;
10108                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10109   call "test0" [CallString "abc"; CallOptString (Some "def");
10110                 CallStringList ["1"]; CallBool false;
10111                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10112   call "test0" [CallString "abc"; CallOptString (Some "def");
10113                 CallStringList ["1"]; CallBool false;
10114                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10115
10116 (* XXX Add here tests of the return and error functions. *)
10117
10118 (* This is used to generate the src/MAX_PROC_NR file which
10119  * contains the maximum procedure number, a surrogate for the
10120  * ABI version number.  See src/Makefile.am for the details.
10121  *)
10122 and generate_max_proc_nr () =
10123   let proc_nrs = List.map (
10124     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10125   ) daemon_functions in
10126
10127   let max_proc_nr = List.fold_left max 0 proc_nrs in
10128
10129   pr "%d\n" max_proc_nr
10130
10131 let output_to filename =
10132   let filename_new = filename ^ ".new" in
10133   chan := open_out filename_new;
10134   let close () =
10135     close_out !chan;
10136     chan := stdout;
10137
10138     (* Is the new file different from the current file? *)
10139     if Sys.file_exists filename && files_equal filename filename_new then
10140       Unix.unlink filename_new          (* same, so skip it *)
10141     else (
10142       (* different, overwrite old one *)
10143       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
10144       Unix.rename filename_new filename;
10145       Unix.chmod filename 0o444;
10146       printf "written %s\n%!" filename;
10147     )
10148   in
10149   close
10150
10151 (* Main program. *)
10152 let () =
10153   check_functions ();
10154
10155   if not (Sys.file_exists "HACKING") then (
10156     eprintf "\
10157 You are probably running this from the wrong directory.
10158 Run it from the top source directory using the command
10159   src/generator.ml
10160 ";
10161     exit 1
10162   );
10163
10164   let close = output_to "src/guestfs_protocol.x" in
10165   generate_xdr ();
10166   close ();
10167
10168   let close = output_to "src/guestfs-structs.h" in
10169   generate_structs_h ();
10170   close ();
10171
10172   let close = output_to "src/guestfs-actions.h" in
10173   generate_actions_h ();
10174   close ();
10175
10176   let close = output_to "src/guestfs-internal-actions.h" in
10177   generate_internal_actions_h ();
10178   close ();
10179
10180   let close = output_to "src/guestfs-actions.c" in
10181   generate_client_actions ();
10182   close ();
10183
10184   let close = output_to "daemon/actions.h" in
10185   generate_daemon_actions_h ();
10186   close ();
10187
10188   let close = output_to "daemon/stubs.c" in
10189   generate_daemon_actions ();
10190   close ();
10191
10192   let close = output_to "daemon/names.c" in
10193   generate_daemon_names ();
10194   close ();
10195
10196   let close = output_to "capitests/tests.c" in
10197   generate_tests ();
10198   close ();
10199
10200   let close = output_to "src/guestfs-bindtests.c" in
10201   generate_bindtests ();
10202   close ();
10203
10204   let close = output_to "fish/cmds.c" in
10205   generate_fish_cmds ();
10206   close ();
10207
10208   let close = output_to "fish/completion.c" in
10209   generate_fish_completion ();
10210   close ();
10211
10212   let close = output_to "guestfs-structs.pod" in
10213   generate_structs_pod ();
10214   close ();
10215
10216   let close = output_to "guestfs-actions.pod" in
10217   generate_actions_pod ();
10218   close ();
10219
10220   let close = output_to "guestfish-actions.pod" in
10221   generate_fish_actions_pod ();
10222   close ();
10223
10224   let close = output_to "ocaml/guestfs.mli" in
10225   generate_ocaml_mli ();
10226   close ();
10227
10228   let close = output_to "ocaml/guestfs.ml" in
10229   generate_ocaml_ml ();
10230   close ();
10231
10232   let close = output_to "ocaml/guestfs_c_actions.c" in
10233   generate_ocaml_c ();
10234   close ();
10235
10236   let close = output_to "ocaml/bindtests.ml" in
10237   generate_ocaml_bindtests ();
10238   close ();
10239
10240   let close = output_to "perl/Guestfs.xs" in
10241   generate_perl_xs ();
10242   close ();
10243
10244   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10245   generate_perl_pm ();
10246   close ();
10247
10248   let close = output_to "perl/bindtests.pl" in
10249   generate_perl_bindtests ();
10250   close ();
10251
10252   let close = output_to "python/guestfs-py.c" in
10253   generate_python_c ();
10254   close ();
10255
10256   let close = output_to "python/guestfs.py" in
10257   generate_python_py ();
10258   close ();
10259
10260   let close = output_to "python/bindtests.py" in
10261   generate_python_bindtests ();
10262   close ();
10263
10264   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10265   generate_ruby_c ();
10266   close ();
10267
10268   let close = output_to "ruby/bindtests.rb" in
10269   generate_ruby_bindtests ();
10270   close ();
10271
10272   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10273   generate_java_java ();
10274   close ();
10275
10276   List.iter (
10277     fun (typ, jtyp) ->
10278       let cols = cols_of_struct typ in
10279       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10280       let close = output_to filename in
10281       generate_java_struct jtyp cols;
10282       close ();
10283   ) java_structs;
10284
10285   let close = output_to "java/Makefile.inc" in
10286   generate_java_makefile_inc ();
10287   close ();
10288
10289   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10290   generate_java_c ();
10291   close ();
10292
10293   let close = output_to "java/Bindtests.java" in
10294   generate_java_bindtests ();
10295   close ();
10296
10297   let close = output_to "haskell/Guestfs.hs" in
10298   generate_haskell_hs ();
10299   close ();
10300
10301   let close = output_to "haskell/Bindtests.hs" in
10302   generate_haskell_bindtests ();
10303   close ();
10304
10305   let close = output_to "src/MAX_PROC_NR" in
10306   generate_max_proc_nr ();
10307   close ();
10308
10309   (* Always generate this file last, and unconditionally.  It's used
10310    * by the Makefile to know when we must re-run the generator.
10311    *)
10312   let chan = open_out "src/stamp-generator" in
10313   fprintf chan "1\n";
10314   close_out chan