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