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