guestfish: Fix printing of buffers in structs.
[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     (* These are treated as filenames (simple string parameters) in
146      * the C API and bindings.  But in the RPC protocol, we transfer
147      * the actual file content up to or down from the daemon.
148      * FileIn: local machine -> daemon (in request)
149      * FileOut: daemon -> local machine (in reply)
150      * In guestfish (only), the special name "-" means read from
151      * stdin or write to stdout.
152      *)
153   | FileIn of string
154   | FileOut of string
155 (* Not implemented:
156     (* Opaque buffer which can contain arbitrary 8 bit data.
157      * In the C API, this is expressed as <char *, int> pair.
158      * Most other languages have a string type which can contain
159      * ASCII NUL.  We use whatever type is appropriate for each
160      * language.
161      * Buffers are limited by the total message size.  To transfer
162      * large blocks of data, use FileIn/FileOut parameters instead.
163      * To return an arbitrary buffer, use RBufferOut.
164      *)
165   | BufferIn of string
166 *)
167
168 type flags =
169   | ProtocolLimitWarning  (* display warning about protocol size limits *)
170   | DangerWillRobinson    (* flags particularly dangerous commands *)
171   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
172   | FishAction of string  (* call this function in guestfish *)
173   | NotInFish             (* do not export via guestfish *)
174   | NotInDocs             (* do not add this function to documentation *)
175   | DeprecatedBy of string (* function is deprecated, use .. instead *)
176
177 (* You can supply zero or as many tests as you want per API call.
178  *
179  * Note that the test environment has 3 block devices, of size 500MB,
180  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181  * a fourth ISO block device with some known files on it (/dev/sdd).
182  *
183  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184  * Number of cylinders was 63 for IDE emulated disks with precisely
185  * the same size.  How exactly this is calculated is a mystery.
186  *
187  * The ISO block device (/dev/sdd) comes from images/test.iso.
188  *
189  * To be able to run the tests in a reasonable amount of time,
190  * the virtual machine and block devices are reused between tests.
191  * So don't try testing kill_subprocess :-x
192  *
193  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194  *
195  * Don't assume anything about the previous contents of the block
196  * devices.  Use 'Init*' to create some initial scenarios.
197  *
198  * You can add a prerequisite clause to any individual test.  This
199  * is a run-time check, which, if it fails, causes the test to be
200  * skipped.  Useful if testing a command which might not work on
201  * all variations of libguestfs builds.  A test that has prerequisite
202  * of 'Always' is run unconditionally.
203  *
204  * In addition, packagers can skip individual tests by setting the
205  * environment variables:     eg:
206  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
207  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
208  *)
209 type tests = (test_init * test_prereq * test) list
210 and test =
211     (* Run the command sequence and just expect nothing to fail. *)
212   | TestRun of seq
213
214     (* Run the command sequence and expect the output of the final
215      * command to be the string.
216      *)
217   | TestOutput of seq * string
218
219     (* Run the command sequence and expect the output of the final
220      * command to be the list of strings.
221      *)
222   | TestOutputList of seq * string list
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the list of block devices (could be either
226      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227      * character of each string).
228      *)
229   | TestOutputListOfDevices of seq * string list
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the integer.
233      *)
234   | TestOutputInt of seq * int
235
236     (* Run the command sequence and expect the output of the final
237      * command to be <op> <int>, eg. ">=", "1".
238      *)
239   | TestOutputIntOp of seq * string * int
240
241     (* Run the command sequence and expect the output of the final
242      * command to be a true value (!= 0 or != NULL).
243      *)
244   | TestOutputTrue of seq
245
246     (* Run the command sequence and expect the output of the final
247      * command to be a false value (== 0 or == NULL, but not an error).
248      *)
249   | TestOutputFalse of seq
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a list of the given length (but don't care about
253      * content).
254      *)
255   | TestOutputLength of seq * int
256
257     (* Run the command sequence and expect the output of the final
258      * command to be a buffer (RBufferOut), ie. string + size.
259      *)
260   | TestOutputBuffer of seq * string
261
262     (* Run the command sequence and expect the output of the final
263      * command to be a structure.
264      *)
265   | TestOutputStruct of seq * test_field_compare list
266
267     (* Run the command sequence and expect the final command (only)
268      * to fail.
269      *)
270   | TestLastFail of seq
271
272 and test_field_compare =
273   | CompareWithInt of string * int
274   | CompareWithIntOp of string * string * int
275   | CompareWithString of string * string
276   | CompareFieldsIntEq of string * string
277   | CompareFieldsStrEq of string * string
278
279 (* Test prerequisites. *)
280 and test_prereq =
281     (* Test always runs. *)
282   | Always
283
284     (* Test is currently disabled - eg. it fails, or it tests some
285      * unimplemented feature.
286      *)
287   | Disabled
288
289     (* 'string' is some C code (a function body) that should return
290      * true or false.  The test will run if the code returns true.
291      *)
292   | If of string
293
294     (* As for 'If' but the test runs _unless_ the code returns true. *)
295   | Unless of string
296
297 (* Some initial scenarios for testing. *)
298 and test_init =
299     (* Do nothing, block devices could contain random stuff including
300      * LVM PVs, and some filesystems might be mounted.  This is usually
301      * a bad idea.
302      *)
303   | InitNone
304
305     (* Block devices are empty and no filesystems are mounted. *)
306   | InitEmpty
307
308     (* /dev/sda contains a single partition /dev/sda1, with random
309      * content.  /dev/sdb and /dev/sdc may have random content.
310      * No LVM.
311      *)
312   | InitPartition
313
314     (* /dev/sda contains a single partition /dev/sda1, which is formatted
315      * as ext2, empty [except for lost+found] and mounted on /.
316      * /dev/sdb and /dev/sdc may have random content.
317      * No LVM.
318      *)
319   | InitBasicFS
320
321     (* /dev/sda:
322      *   /dev/sda1 (is a PV):
323      *     /dev/VG/LV (size 8MB):
324      *       formatted as ext2, empty [except for lost+found], mounted on /
325      * /dev/sdb and /dev/sdc may have random content.
326      *)
327   | InitBasicFSonLVM
328
329     (* /dev/sdd (the ISO, see images/ directory in source)
330      * is mounted on /
331      *)
332   | InitISOFS
333
334 (* Sequence of commands for testing. *)
335 and seq = cmd list
336 and cmd = string list
337
338 (* Note about long descriptions: When referring to another
339  * action, use the format C<guestfs_other> (ie. the full name of
340  * the C function).  This will be replaced as appropriate in other
341  * language bindings.
342  *
343  * Apart from that, long descriptions are just perldoc paragraphs.
344  *)
345
346 (* Generate a random UUID (used in tests). *)
347 let uuidgen () =
348   let chan = Unix.open_process_in "uuidgen" in
349   let uuid = input_line chan in
350   (match Unix.close_process_in chan with
351    | Unix.WEXITED 0 -> ()
352    | Unix.WEXITED _ ->
353        failwith "uuidgen: process exited with non-zero status"
354    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355        failwith "uuidgen: process signalled or stopped by signal"
356   );
357   uuid
358
359 (* These test functions are used in the language binding tests. *)
360
361 let test_all_args = [
362   String "str";
363   OptString "optstr";
364   StringList "strlist";
365   Bool "b";
366   Int "integer";
367   FileIn "filein";
368   FileOut "fileout";
369 ]
370
371 let test_all_rets = [
372   (* except for RErr, which is tested thoroughly elsewhere *)
373   "test0rint",         RInt "valout";
374   "test0rint64",       RInt64 "valout";
375   "test0rbool",        RBool "valout";
376   "test0rconststring", RConstString "valout";
377   "test0rconstoptstring", RConstOptString "valout";
378   "test0rstring",      RString "valout";
379   "test0rstringlist",  RStringList "valout";
380   "test0rstruct",      RStruct ("valout", "lvm_pv");
381   "test0rstructlist",  RStructList ("valout", "lvm_pv");
382   "test0rhashtable",   RHashtable "valout";
383 ]
384
385 let test_functions = [
386   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387    [],
388    "internal test function - do not use",
389    "\
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
393
394 It echos the contents of each parameter to stdout.
395
396 You probably don't want to call this function.");
397 ] @ List.flatten (
398   List.map (
399     fun (name, ret) ->
400       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401         [],
402         "internal test function - do not use",
403         "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 return type correctly.
407
408 It converts string C<val> to the return type.
409
410 You probably don't want to call this function.");
411        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412         [],
413         "internal test function - do not use",
414         "\
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
418
419 This function always returns an error.
420
421 You probably don't want to call this function.")]
422   ) test_all_rets
423 )
424
425 (* non_daemon_functions are any functions which don't get processed
426  * in the daemon, eg. functions for setting and getting local
427  * configuration values.
428  *)
429
430 let non_daemon_functions = test_functions @ [
431   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432    [],
433    "launch the qemu subprocess",
434    "\
435 Internally libguestfs is implemented by running a virtual machine
436 using L<qemu(1)>.
437
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
440
441   ("wait_ready", (RErr, []), -1, [NotInFish],
442    [],
443    "wait until the qemu subprocess launches (no op)",
444    "\
445 This function is a no op.
446
447 In versions of the API E<lt> 1.0.71 you had to call this function
448 just after calling C<guestfs_launch> to wait for the launch
449 to complete.  However this is no longer necessary because
450 C<guestfs_launch> now does the waiting.
451
452 If you see any calls to this function in code then you can just
453 remove them, unless you want to retain compatibility with older
454 versions of the API.");
455
456   ("kill_subprocess", (RErr, []), -1, [],
457    [],
458    "kill the qemu subprocess",
459    "\
460 This kills the qemu subprocess.  You should never need to call this.");
461
462   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
463    [],
464    "add an image to examine or modify",
465    "\
466 This function adds a virtual machine disk image C<filename> to the
467 guest.  The first time you call this function, the disk appears as IDE
468 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
469 so on.
470
471 You don't necessarily need to be root when using libguestfs.  However
472 you obviously do need sufficient permissions to access the filename
473 for whatever operations you want to perform (ie. read access if you
474 just want to read the image or write access if you want to modify the
475 image).
476
477 This is equivalent to the qemu parameter
478 C<-drive file=filename,cache=off,if=...>.
479 C<cache=off> is omitted in cases where it is not supported by
480 the underlying filesystem.
481
482 Note that this call checks for the existence of C<filename>.  This
483 stops you from specifying other types of drive which are supported
484 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
485 the general C<guestfs_config> call instead.");
486
487   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
488    [],
489    "add a CD-ROM disk image to examine",
490    "\
491 This function adds a virtual CD-ROM disk image to the guest.
492
493 This is equivalent to the qemu parameter C<-cdrom filename>.
494
495 Note that this call checks for the existence of C<filename>.  This
496 stops you from specifying other types of drive which are supported
497 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
498 the general C<guestfs_config> call instead.");
499
500   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
501    [],
502    "add a drive in snapshot mode (read-only)",
503    "\
504 This adds a drive in snapshot mode, making it effectively
505 read-only.
506
507 Note that writes to the device are allowed, and will be seen for
508 the duration of the guestfs handle, but they are written
509 to a temporary file which is discarded as soon as the guestfs
510 handle is closed.  We don't currently have any method to enable
511 changes to be committed, although qemu can support this.
512
513 This is equivalent to the qemu parameter
514 C<-drive file=filename,snapshot=on,if=...>.
515
516 Note that this call checks for the existence of C<filename>.  This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
519 the general C<guestfs_config> call instead.");
520
521   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
522    [],
523    "add qemu parameters",
524    "\
525 This can be used to add arbitrary qemu command line parameters
526 of the form C<-param value>.  Actually it's not quite arbitrary - we
527 prevent you from setting some parameters which would interfere with
528 parameters that we use.
529
530 The first character of C<param> string must be a C<-> (dash).
531
532 C<value> can be NULL.");
533
534   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
535    [],
536    "set the qemu binary",
537    "\
538 Set the qemu binary that we will use.
539
540 The default is chosen when the library was compiled by the
541 configure script.
542
543 You can also override this by setting the C<LIBGUESTFS_QEMU>
544 environment variable.
545
546 Setting C<qemu> to C<NULL> restores the default qemu binary.");
547
548   ("get_qemu", (RConstString "qemu", []), -1, [],
549    [InitNone, Always, TestRun (
550       [["get_qemu"]])],
551    "get the qemu binary",
552    "\
553 Return the current qemu binary.
554
555 This is always non-NULL.  If it wasn't set already, then this will
556 return the default qemu binary name.");
557
558   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
559    [],
560    "set the search path",
561    "\
562 Set the path that libguestfs searches for kernel and initrd.img.
563
564 The default is C<$libdir/guestfs> unless overridden by setting
565 C<LIBGUESTFS_PATH> environment variable.
566
567 Setting C<path> to C<NULL> restores the default path.");
568
569   ("get_path", (RConstString "path", []), -1, [],
570    [InitNone, Always, TestRun (
571       [["get_path"]])],
572    "get the search path",
573    "\
574 Return the current search path.
575
576 This is always non-NULL.  If it wasn't set already, then this will
577 return the default path.");
578
579   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
580    [],
581    "add options to kernel command line",
582    "\
583 This function is used to add additional options to the
584 guest kernel command line.
585
586 The default is C<NULL> unless overridden by setting
587 C<LIBGUESTFS_APPEND> environment variable.
588
589 Setting C<append> to C<NULL> means I<no> additional options
590 are passed (libguestfs always adds a few of its own).");
591
592   ("get_append", (RConstOptString "append", []), -1, [],
593    (* This cannot be tested with the current framework.  The
594     * function can return NULL in normal operations, which the
595     * test framework interprets as an error.
596     *)
597    [],
598    "get the additional kernel options",
599    "\
600 Return the additional kernel options which are added to the
601 guest kernel command line.
602
603 If C<NULL> then no options are added.");
604
605   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
606    [],
607    "set autosync mode",
608    "\
609 If C<autosync> is true, this enables autosync.  Libguestfs will make a
610 best effort attempt to run C<guestfs_umount_all> followed by
611 C<guestfs_sync> when the handle is closed
612 (also if the program exits without closing handles).
613
614 This is disabled by default (except in guestfish where it is
615 enabled by default).");
616
617   ("get_autosync", (RBool "autosync", []), -1, [],
618    [InitNone, Always, TestRun (
619       [["get_autosync"]])],
620    "get autosync mode",
621    "\
622 Get the autosync flag.");
623
624   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
625    [],
626    "set verbose mode",
627    "\
628 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
629
630 Verbose messages are disabled unless the environment variable
631 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
632
633   ("get_verbose", (RBool "verbose", []), -1, [],
634    [],
635    "get verbose mode",
636    "\
637 This returns the verbose messages flag.");
638
639   ("is_ready", (RBool "ready", []), -1, [],
640    [InitNone, Always, TestOutputTrue (
641       [["is_ready"]])],
642    "is ready to accept commands",
643    "\
644 This returns true iff this handle is ready to accept commands
645 (in the C<READY> state).
646
647 For more information on states, see L<guestfs(3)>.");
648
649   ("is_config", (RBool "config", []), -1, [],
650    [InitNone, Always, TestOutputFalse (
651       [["is_config"]])],
652    "is in configuration state",
653    "\
654 This returns true iff this handle is being configured
655 (in the C<CONFIG> state).
656
657 For more information on states, see L<guestfs(3)>.");
658
659   ("is_launching", (RBool "launching", []), -1, [],
660    [InitNone, Always, TestOutputFalse (
661       [["is_launching"]])],
662    "is launching subprocess",
663    "\
664 This returns true iff this handle is launching the subprocess
665 (in the C<LAUNCHING> state).
666
667 For more information on states, see L<guestfs(3)>.");
668
669   ("is_busy", (RBool "busy", []), -1, [],
670    [InitNone, Always, TestOutputFalse (
671       [["is_busy"]])],
672    "is busy processing a command",
673    "\
674 This returns true iff this handle is busy processing a command
675 (in the C<BUSY> state).
676
677 For more information on states, see L<guestfs(3)>.");
678
679   ("get_state", (RInt "state", []), -1, [],
680    [],
681    "get the current state",
682    "\
683 This returns the current state as an opaque integer.  This is
684 only useful for printing debug and internal error messages.
685
686 For more information on states, see L<guestfs(3)>.");
687
688   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
689    [InitNone, Always, TestOutputInt (
690       [["set_memsize"; "500"];
691        ["get_memsize"]], 500)],
692    "set memory allocated to the qemu subprocess",
693    "\
694 This sets the memory size in megabytes allocated to the
695 qemu subprocess.  This only has any effect if called before
696 C<guestfs_launch>.
697
698 You can also change this by setting the environment
699 variable C<LIBGUESTFS_MEMSIZE> before the handle is
700 created.
701
702 For more information on the architecture of libguestfs,
703 see L<guestfs(3)>.");
704
705   ("get_memsize", (RInt "memsize", []), -1, [],
706    [InitNone, Always, TestOutputIntOp (
707       [["get_memsize"]], ">=", 256)],
708    "get memory allocated to the qemu subprocess",
709    "\
710 This gets the memory size in megabytes allocated to the
711 qemu subprocess.
712
713 If C<guestfs_set_memsize> was not called
714 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
715 then this returns the compiled-in default value for memsize.
716
717 For more information on the architecture of libguestfs,
718 see L<guestfs(3)>.");
719
720   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
721    [InitNone, Always, TestOutputIntOp (
722       [["get_pid"]], ">=", 1)],
723    "get PID of qemu subprocess",
724    "\
725 Return the process ID of the qemu subprocess.  If there is no
726 qemu subprocess, then this will return an error.
727
728 This is an internal call used for debugging and testing.");
729
730   ("version", (RStruct ("version", "version"), []), -1, [],
731    [InitNone, Always, TestOutputStruct (
732       [["version"]], [CompareWithInt ("major", 1)])],
733    "get the library version number",
734    "\
735 Return the libguestfs version number that the program is linked
736 against.
737
738 Note that because of dynamic linking this is not necessarily
739 the version of libguestfs that you compiled against.  You can
740 compile the program, and then at runtime dynamically link
741 against a completely different C<libguestfs.so> library.
742
743 This call was added in version C<1.0.58>.  In previous
744 versions of libguestfs there was no way to get the version
745 number.  From C code you can use ELF weak linking tricks to find out if
746 this symbol exists (if it doesn't, then it's an earlier version).
747
748 The call returns a structure with four elements.  The first
749 three (C<major>, C<minor> and C<release>) are numbers and
750 correspond to the usual version triplet.  The fourth element
751 (C<extra>) is a string and is normally empty, but may be
752 used for distro-specific information.
753
754 To construct the original version string:
755 C<$major.$minor.$release$extra>
756
757 I<Note:> Don't use this call to test for availability
758 of features.  Distro backports makes this unreliable.");
759
760   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
761    [InitNone, Always, TestOutputTrue (
762       [["set_selinux"; "true"];
763        ["get_selinux"]])],
764    "set SELinux enabled or disabled at appliance boot",
765    "\
766 This sets the selinux flag that is passed to the appliance
767 at boot time.  The default is C<selinux=0> (disabled).
768
769 Note that if SELinux is enabled, it is always in
770 Permissive mode (C<enforcing=0>).
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_selinux", (RBool "selinux", []), -1, [],
776    [],
777    "get SELinux enabled flag",
778    "\
779 This returns the current setting of the selinux flag which
780 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
781
782 For more information on the architecture of libguestfs,
783 see L<guestfs(3)>.");
784
785   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
786    [InitNone, Always, TestOutputFalse (
787       [["set_trace"; "false"];
788        ["get_trace"]])],
789    "enable or disable command traces",
790    "\
791 If the command trace flag is set to 1, then commands are
792 printed on stdout before they are executed in a format
793 which is very similar to the one used by guestfish.  In
794 other words, you can run a program with this enabled, and
795 you will get out a script which you can feed to guestfish
796 to perform the same set of actions.
797
798 If you want to trace C API calls into libguestfs (and
799 other libraries) then possibly a better way is to use
800 the external ltrace(1) command.
801
802 Command traces are disabled unless the environment variable
803 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
804
805   ("get_trace", (RBool "trace", []), -1, [],
806    [],
807    "get command trace enabled flag",
808    "\
809 Return the command trace flag.");
810
811   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
812    [InitNone, Always, TestOutputFalse (
813       [["set_direct"; "false"];
814        ["get_direct"]])],
815    "enable or disable direct appliance mode",
816    "\
817 If the direct appliance mode flag is enabled, then stdin and
818 stdout are passed directly through to the appliance once it
819 is launched.
820
821 One consequence of this is that log messages aren't caught
822 by the library and handled by C<guestfs_set_log_message_callback>,
823 but go straight to stdout.
824
825 You probably don't want to use this unless you know what you
826 are doing.
827
828 The default is disabled.");
829
830   ("get_direct", (RBool "direct", []), -1, [],
831    [],
832    "get direct appliance mode flag",
833    "\
834 Return the direct appliance mode flag.");
835
836 ]
837
838 (* daemon_functions are any functions which cause some action
839  * to take place in the daemon.
840  *)
841
842 let daemon_functions = [
843   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
844    [InitEmpty, Always, TestOutput (
845       [["sfdiskM"; "/dev/sda"; ","];
846        ["mkfs"; "ext2"; "/dev/sda1"];
847        ["mount"; "/dev/sda1"; "/"];
848        ["write_file"; "/new"; "new file contents"; "0"];
849        ["cat"; "/new"]], "new file contents")],
850    "mount a guest disk at a position in the filesystem",
851    "\
852 Mount a guest disk at a position in the filesystem.  Block devices
853 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
854 the guest.  If those block devices contain partitions, they will have
855 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
856 names can be used.
857
858 The rules are the same as for L<mount(2)>:  A filesystem must
859 first be mounted on C</> before others can be mounted.  Other
860 filesystems can only be mounted on directories which already
861 exist.
862
863 The mounted filesystem is writable, if we have sufficient permissions
864 on the underlying device.
865
866 The filesystem options C<sync> and C<noatime> are set with this
867 call, in order to improve reliability.");
868
869   ("sync", (RErr, []), 2, [],
870    [ InitEmpty, Always, TestRun [["sync"]]],
871    "sync disks, writes are flushed through to the disk image",
872    "\
873 This syncs the disk, so that any writes are flushed through to the
874 underlying disk image.
875
876 You should always call this if you have modified a disk image, before
877 closing the handle.");
878
879   ("touch", (RErr, [Pathname "path"]), 3, [],
880    [InitBasicFS, Always, TestOutputTrue (
881       [["touch"; "/new"];
882        ["exists"; "/new"]])],
883    "update file timestamps or create a new file",
884    "\
885 Touch acts like the L<touch(1)> command.  It can be used to
886 update the timestamps on a file, or, if the file does not exist,
887 to create a new zero-length file.");
888
889   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
890    [InitISOFS, Always, TestOutput (
891       [["cat"; "/known-2"]], "abcdef\n")],
892    "list the contents of a file",
893    "\
894 Return the contents of the file named C<path>.
895
896 Note that this function cannot correctly handle binary files
897 (specifically, files containing C<\\0> character which is treated
898 as end of string).  For those you need to use the C<guestfs_read_file>
899 or C<guestfs_download> functions which have a more complex interface.");
900
901   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
902    [], (* XXX Tricky to test because it depends on the exact format
903         * of the 'ls -l' command, which changes between F10 and F11.
904         *)
905    "list the files in a directory (long format)",
906    "\
907 List the files in C<directory> (relative to the root directory,
908 there is no cwd) in the format of 'ls -la'.
909
910 This command is mostly useful for interactive sessions.  It
911 is I<not> intended that you try to parse the output string.");
912
913   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
914    [InitBasicFS, Always, TestOutputList (
915       [["touch"; "/new"];
916        ["touch"; "/newer"];
917        ["touch"; "/newest"];
918        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
919    "list the files in a directory",
920    "\
921 List the files in C<directory> (relative to the root directory,
922 there is no cwd).  The '.' and '..' entries are not returned, but
923 hidden files are shown.
924
925 This command is mostly useful for interactive sessions.  Programs
926 should probably use C<guestfs_readdir> instead.");
927
928   ("list_devices", (RStringList "devices", []), 7, [],
929    [InitEmpty, Always, TestOutputListOfDevices (
930       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
931    "list the block devices",
932    "\
933 List all the block devices.
934
935 The full block device names are returned, eg. C</dev/sda>");
936
937   ("list_partitions", (RStringList "partitions", []), 8, [],
938    [InitBasicFS, Always, TestOutputListOfDevices (
939       [["list_partitions"]], ["/dev/sda1"]);
940     InitEmpty, Always, TestOutputListOfDevices (
941       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
942        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
943    "list the partitions",
944    "\
945 List all the partitions detected on all block devices.
946
947 The full partition device names are returned, eg. C</dev/sda1>
948
949 This does not return logical volumes.  For that you will need to
950 call C<guestfs_lvs>.");
951
952   ("pvs", (RStringList "physvols", []), 9, [],
953    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
954       [["pvs"]], ["/dev/sda1"]);
955     InitEmpty, Always, TestOutputListOfDevices (
956       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
957        ["pvcreate"; "/dev/sda1"];
958        ["pvcreate"; "/dev/sda2"];
959        ["pvcreate"; "/dev/sda3"];
960        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
961    "list the LVM physical volumes (PVs)",
962    "\
963 List all the physical volumes detected.  This is the equivalent
964 of the L<pvs(8)> command.
965
966 This returns a list of just the device names that contain
967 PVs (eg. C</dev/sda2>).
968
969 See also C<guestfs_pvs_full>.");
970
971   ("vgs", (RStringList "volgroups", []), 10, [],
972    [InitBasicFSonLVM, Always, TestOutputList (
973       [["vgs"]], ["VG"]);
974     InitEmpty, Always, TestOutputList (
975       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
976        ["pvcreate"; "/dev/sda1"];
977        ["pvcreate"; "/dev/sda2"];
978        ["pvcreate"; "/dev/sda3"];
979        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
980        ["vgcreate"; "VG2"; "/dev/sda3"];
981        ["vgs"]], ["VG1"; "VG2"])],
982    "list the LVM volume groups (VGs)",
983    "\
984 List all the volumes groups detected.  This is the equivalent
985 of the L<vgs(8)> command.
986
987 This returns a list of just the volume group names that were
988 detected (eg. C<VolGroup00>).
989
990 See also C<guestfs_vgs_full>.");
991
992   ("lvs", (RStringList "logvols", []), 11, [],
993    [InitBasicFSonLVM, Always, TestOutputList (
994       [["lvs"]], ["/dev/VG/LV"]);
995     InitEmpty, Always, TestOutputList (
996       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
997        ["pvcreate"; "/dev/sda1"];
998        ["pvcreate"; "/dev/sda2"];
999        ["pvcreate"; "/dev/sda3"];
1000        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1001        ["vgcreate"; "VG2"; "/dev/sda3"];
1002        ["lvcreate"; "LV1"; "VG1"; "50"];
1003        ["lvcreate"; "LV2"; "VG1"; "50"];
1004        ["lvcreate"; "LV3"; "VG2"; "50"];
1005        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1006    "list the LVM logical volumes (LVs)",
1007    "\
1008 List all the logical volumes detected.  This is the equivalent
1009 of the L<lvs(8)> command.
1010
1011 This returns a list of the logical volume device names
1012 (eg. C</dev/VolGroup00/LogVol00>).
1013
1014 See also C<guestfs_lvs_full>.");
1015
1016   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1017    [], (* XXX how to test? *)
1018    "list the LVM physical volumes (PVs)",
1019    "\
1020 List all the physical volumes detected.  This is the equivalent
1021 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1022
1023   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1024    [], (* XXX how to test? *)
1025    "list the LVM volume groups (VGs)",
1026    "\
1027 List all the volumes groups detected.  This is the equivalent
1028 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1029
1030   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1031    [], (* XXX how to test? *)
1032    "list the LVM logical volumes (LVs)",
1033    "\
1034 List all the logical volumes detected.  This is the equivalent
1035 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1036
1037   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1038    [InitISOFS, Always, TestOutputList (
1039       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1040     InitISOFS, Always, TestOutputList (
1041       [["read_lines"; "/empty"]], [])],
1042    "read file as lines",
1043    "\
1044 Return the contents of the file named C<path>.
1045
1046 The file contents are returned as a list of lines.  Trailing
1047 C<LF> and C<CRLF> character sequences are I<not> returned.
1048
1049 Note that this function cannot correctly handle binary files
1050 (specifically, files containing C<\\0> character which is treated
1051 as end of line).  For those you need to use the C<guestfs_read_file>
1052 function which has a more complex interface.");
1053
1054   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1055    [], (* XXX Augeas code needs tests. *)
1056    "create a new Augeas handle",
1057    "\
1058 Create a new Augeas handle for editing configuration files.
1059 If there was any previous Augeas handle associated with this
1060 guestfs session, then it is closed.
1061
1062 You must call this before using any other C<guestfs_aug_*>
1063 commands.
1064
1065 C<root> is the filesystem root.  C<root> must not be NULL,
1066 use C</> instead.
1067
1068 The flags are the same as the flags defined in
1069 E<lt>augeas.hE<gt>, the logical I<or> of the following
1070 integers:
1071
1072 =over 4
1073
1074 =item C<AUG_SAVE_BACKUP> = 1
1075
1076 Keep the original file with a C<.augsave> extension.
1077
1078 =item C<AUG_SAVE_NEWFILE> = 2
1079
1080 Save changes into a file with extension C<.augnew>, and
1081 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1082
1083 =item C<AUG_TYPE_CHECK> = 4
1084
1085 Typecheck lenses (can be expensive).
1086
1087 =item C<AUG_NO_STDINC> = 8
1088
1089 Do not use standard load path for modules.
1090
1091 =item C<AUG_SAVE_NOOP> = 16
1092
1093 Make save a no-op, just record what would have been changed.
1094
1095 =item C<AUG_NO_LOAD> = 32
1096
1097 Do not load the tree in C<guestfs_aug_init>.
1098
1099 =back
1100
1101 To close the handle, you can call C<guestfs_aug_close>.
1102
1103 To find out more about Augeas, see L<http://augeas.net/>.");
1104
1105   ("aug_close", (RErr, []), 26, [],
1106    [], (* XXX Augeas code needs tests. *)
1107    "close the current Augeas handle",
1108    "\
1109 Close the current Augeas handle and free up any resources
1110 used by it.  After calling this, you have to call
1111 C<guestfs_aug_init> again before you can use any other
1112 Augeas functions.");
1113
1114   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1115    [], (* XXX Augeas code needs tests. *)
1116    "define an Augeas variable",
1117    "\
1118 Defines an Augeas variable C<name> whose value is the result
1119 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1120 undefined.
1121
1122 On success this returns the number of nodes in C<expr>, or
1123 C<0> if C<expr> evaluates to something which is not a nodeset.");
1124
1125   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1126    [], (* XXX Augeas code needs tests. *)
1127    "define an Augeas node",
1128    "\
1129 Defines a variable C<name> whose value is the result of
1130 evaluating C<expr>.
1131
1132 If C<expr> evaluates to an empty nodeset, a node is created,
1133 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1134 C<name> will be the nodeset containing that single node.
1135
1136 On success this returns a pair containing the
1137 number of nodes in the nodeset, and a boolean flag
1138 if a node was created.");
1139
1140   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1141    [], (* XXX Augeas code needs tests. *)
1142    "look up the value of an Augeas path",
1143    "\
1144 Look up the value associated with C<path>.  If C<path>
1145 matches exactly one node, the C<value> is returned.");
1146
1147   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1148    [], (* XXX Augeas code needs tests. *)
1149    "set Augeas path to value",
1150    "\
1151 Set the value associated with C<path> to C<value>.");
1152
1153   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1154    [], (* XXX Augeas code needs tests. *)
1155    "insert a sibling Augeas node",
1156    "\
1157 Create a new sibling C<label> for C<path>, inserting it into
1158 the tree before or after C<path> (depending on the boolean
1159 flag C<before>).
1160
1161 C<path> must match exactly one existing node in the tree, and
1162 C<label> must be a label, ie. not contain C</>, C<*> or end
1163 with a bracketed index C<[N]>.");
1164
1165   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1166    [], (* XXX Augeas code needs tests. *)
1167    "remove an Augeas path",
1168    "\
1169 Remove C<path> and all of its children.
1170
1171 On success this returns the number of entries which were removed.");
1172
1173   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1174    [], (* XXX Augeas code needs tests. *)
1175    "move Augeas node",
1176    "\
1177 Move the node C<src> to C<dest>.  C<src> must match exactly
1178 one node.  C<dest> is overwritten if it exists.");
1179
1180   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1181    [], (* XXX Augeas code needs tests. *)
1182    "return Augeas nodes which match augpath",
1183    "\
1184 Returns a list of paths which match the path expression C<path>.
1185 The returned paths are sufficiently qualified so that they match
1186 exactly one node in the current tree.");
1187
1188   ("aug_save", (RErr, []), 25, [],
1189    [], (* XXX Augeas code needs tests. *)
1190    "write all pending Augeas changes to disk",
1191    "\
1192 This writes all pending changes to disk.
1193
1194 The flags which were passed to C<guestfs_aug_init> affect exactly
1195 how files are saved.");
1196
1197   ("aug_load", (RErr, []), 27, [],
1198    [], (* XXX Augeas code needs tests. *)
1199    "load files into the tree",
1200    "\
1201 Load files into the tree.
1202
1203 See C<aug_load> in the Augeas documentation for the full gory
1204 details.");
1205
1206   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1207    [], (* XXX Augeas code needs tests. *)
1208    "list Augeas nodes under augpath",
1209    "\
1210 This is just a shortcut for listing C<guestfs_aug_match>
1211 C<path/*> and sorting the resulting nodes into alphabetical order.");
1212
1213   ("rm", (RErr, [Pathname "path"]), 29, [],
1214    [InitBasicFS, Always, TestRun
1215       [["touch"; "/new"];
1216        ["rm"; "/new"]];
1217     InitBasicFS, Always, TestLastFail
1218       [["rm"; "/new"]];
1219     InitBasicFS, Always, TestLastFail
1220       [["mkdir"; "/new"];
1221        ["rm"; "/new"]]],
1222    "remove a file",
1223    "\
1224 Remove the single file C<path>.");
1225
1226   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1227    [InitBasicFS, Always, TestRun
1228       [["mkdir"; "/new"];
1229        ["rmdir"; "/new"]];
1230     InitBasicFS, Always, TestLastFail
1231       [["rmdir"; "/new"]];
1232     InitBasicFS, Always, TestLastFail
1233       [["touch"; "/new"];
1234        ["rmdir"; "/new"]]],
1235    "remove a directory",
1236    "\
1237 Remove the single directory C<path>.");
1238
1239   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1240    [InitBasicFS, Always, TestOutputFalse
1241       [["mkdir"; "/new"];
1242        ["mkdir"; "/new/foo"];
1243        ["touch"; "/new/foo/bar"];
1244        ["rm_rf"; "/new"];
1245        ["exists"; "/new"]]],
1246    "remove a file or directory recursively",
1247    "\
1248 Remove the file or directory C<path>, recursively removing the
1249 contents if its a directory.  This is like the C<rm -rf> shell
1250 command.");
1251
1252   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1253    [InitBasicFS, Always, TestOutputTrue
1254       [["mkdir"; "/new"];
1255        ["is_dir"; "/new"]];
1256     InitBasicFS, Always, TestLastFail
1257       [["mkdir"; "/new/foo/bar"]]],
1258    "create a directory",
1259    "\
1260 Create a directory named C<path>.");
1261
1262   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1263    [InitBasicFS, Always, TestOutputTrue
1264       [["mkdir_p"; "/new/foo/bar"];
1265        ["is_dir"; "/new/foo/bar"]];
1266     InitBasicFS, Always, TestOutputTrue
1267       [["mkdir_p"; "/new/foo/bar"];
1268        ["is_dir"; "/new/foo"]];
1269     InitBasicFS, Always, TestOutputTrue
1270       [["mkdir_p"; "/new/foo/bar"];
1271        ["is_dir"; "/new"]];
1272     (* Regression tests for RHBZ#503133: *)
1273     InitBasicFS, Always, TestRun
1274       [["mkdir"; "/new"];
1275        ["mkdir_p"; "/new"]];
1276     InitBasicFS, Always, TestLastFail
1277       [["touch"; "/new"];
1278        ["mkdir_p"; "/new"]]],
1279    "create a directory and parents",
1280    "\
1281 Create a directory named C<path>, creating any parent directories
1282 as necessary.  This is like the C<mkdir -p> shell command.");
1283
1284   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1285    [], (* XXX Need stat command to test *)
1286    "change file mode",
1287    "\
1288 Change the mode (permissions) of C<path> to C<mode>.  Only
1289 numeric modes are supported.");
1290
1291   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1292    [], (* XXX Need stat command to test *)
1293    "change file owner and group",
1294    "\
1295 Change the file owner to C<owner> and group to C<group>.
1296
1297 Only numeric uid and gid are supported.  If you want to use
1298 names, you will need to locate and parse the password file
1299 yourself (Augeas support makes this relatively easy).");
1300
1301   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1302    [InitISOFS, Always, TestOutputTrue (
1303       [["exists"; "/empty"]]);
1304     InitISOFS, Always, TestOutputTrue (
1305       [["exists"; "/directory"]])],
1306    "test if file or directory exists",
1307    "\
1308 This returns C<true> if and only if there is a file, directory
1309 (or anything) with the given C<path> name.
1310
1311 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1312
1313   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1314    [InitISOFS, Always, TestOutputTrue (
1315       [["is_file"; "/known-1"]]);
1316     InitISOFS, Always, TestOutputFalse (
1317       [["is_file"; "/directory"]])],
1318    "test if file exists",
1319    "\
1320 This returns C<true> if and only if there is a file
1321 with the given C<path> name.  Note that it returns false for
1322 other objects like directories.
1323
1324 See also C<guestfs_stat>.");
1325
1326   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1327    [InitISOFS, Always, TestOutputFalse (
1328       [["is_dir"; "/known-3"]]);
1329     InitISOFS, Always, TestOutputTrue (
1330       [["is_dir"; "/directory"]])],
1331    "test if file exists",
1332    "\
1333 This returns C<true> if and only if there is a directory
1334 with the given C<path> name.  Note that it returns false for
1335 other objects like files.
1336
1337 See also C<guestfs_stat>.");
1338
1339   ("pvcreate", (RErr, [Device "device"]), 39, [],
1340    [InitEmpty, Always, TestOutputListOfDevices (
1341       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1342        ["pvcreate"; "/dev/sda1"];
1343        ["pvcreate"; "/dev/sda2"];
1344        ["pvcreate"; "/dev/sda3"];
1345        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1346    "create an LVM physical volume",
1347    "\
1348 This creates an LVM physical volume on the named C<device>,
1349 where C<device> should usually be a partition name such
1350 as C</dev/sda1>.");
1351
1352   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1353    [InitEmpty, Always, TestOutputList (
1354       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1355        ["pvcreate"; "/dev/sda1"];
1356        ["pvcreate"; "/dev/sda2"];
1357        ["pvcreate"; "/dev/sda3"];
1358        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1359        ["vgcreate"; "VG2"; "/dev/sda3"];
1360        ["vgs"]], ["VG1"; "VG2"])],
1361    "create an LVM volume group",
1362    "\
1363 This creates an LVM volume group called C<volgroup>
1364 from the non-empty list of physical volumes C<physvols>.");
1365
1366   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1367    [InitEmpty, Always, TestOutputList (
1368       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1369        ["pvcreate"; "/dev/sda1"];
1370        ["pvcreate"; "/dev/sda2"];
1371        ["pvcreate"; "/dev/sda3"];
1372        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1373        ["vgcreate"; "VG2"; "/dev/sda3"];
1374        ["lvcreate"; "LV1"; "VG1"; "50"];
1375        ["lvcreate"; "LV2"; "VG1"; "50"];
1376        ["lvcreate"; "LV3"; "VG2"; "50"];
1377        ["lvcreate"; "LV4"; "VG2"; "50"];
1378        ["lvcreate"; "LV5"; "VG2"; "50"];
1379        ["lvs"]],
1380       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1381        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1382    "create an LVM volume group",
1383    "\
1384 This creates an LVM volume group called C<logvol>
1385 on the volume group C<volgroup>, with C<size> megabytes.");
1386
1387   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1388    [InitEmpty, Always, TestOutput (
1389       [["sfdiskM"; "/dev/sda"; ","];
1390        ["mkfs"; "ext2"; "/dev/sda1"];
1391        ["mount"; "/dev/sda1"; "/"];
1392        ["write_file"; "/new"; "new file contents"; "0"];
1393        ["cat"; "/new"]], "new file contents")],
1394    "make a filesystem",
1395    "\
1396 This creates a filesystem on C<device> (usually a partition
1397 or LVM logical volume).  The filesystem type is C<fstype>, for
1398 example C<ext3>.");
1399
1400   ("sfdisk", (RErr, [Device "device";
1401                      Int "cyls"; Int "heads"; Int "sectors";
1402                      StringList "lines"]), 43, [DangerWillRobinson],
1403    [],
1404    "create partitions on a block device",
1405    "\
1406 This is a direct interface to the L<sfdisk(8)> program for creating
1407 partitions on block devices.
1408
1409 C<device> should be a block device, for example C</dev/sda>.
1410
1411 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1412 and sectors on the device, which are passed directly to sfdisk as
1413 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1414 of these, then the corresponding parameter is omitted.  Usually for
1415 'large' disks, you can just pass C<0> for these, but for small
1416 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1417 out the right geometry and you will need to tell it.
1418
1419 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1420 information refer to the L<sfdisk(8)> manpage.
1421
1422 To create a single partition occupying the whole disk, you would
1423 pass C<lines> as a single element list, when the single element being
1424 the string C<,> (comma).
1425
1426 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1427
1428   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1429    [InitBasicFS, Always, TestOutput (
1430       [["write_file"; "/new"; "new file contents"; "0"];
1431        ["cat"; "/new"]], "new file contents");
1432     InitBasicFS, Always, TestOutput (
1433       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1434        ["cat"; "/new"]], "\nnew file contents\n");
1435     InitBasicFS, Always, TestOutput (
1436       [["write_file"; "/new"; "\n\n"; "0"];
1437        ["cat"; "/new"]], "\n\n");
1438     InitBasicFS, Always, TestOutput (
1439       [["write_file"; "/new"; ""; "0"];
1440        ["cat"; "/new"]], "");
1441     InitBasicFS, Always, TestOutput (
1442       [["write_file"; "/new"; "\n\n\n"; "0"];
1443        ["cat"; "/new"]], "\n\n\n");
1444     InitBasicFS, Always, TestOutput (
1445       [["write_file"; "/new"; "\n"; "0"];
1446        ["cat"; "/new"]], "\n")],
1447    "create a file",
1448    "\
1449 This call creates a file called C<path>.  The contents of the
1450 file is the string C<content> (which can contain any 8 bit data),
1451 with length C<size>.
1452
1453 As a special case, if C<size> is C<0>
1454 then the length is calculated using C<strlen> (so in this case
1455 the content cannot contain embedded ASCII NULs).
1456
1457 I<NB.> Owing to a bug, writing content containing ASCII NUL
1458 characters does I<not> work, even if the length is specified.
1459 We hope to resolve this bug in a future version.  In the meantime
1460 use C<guestfs_upload>.");
1461
1462   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1463    [InitEmpty, Always, TestOutputListOfDevices (
1464       [["sfdiskM"; "/dev/sda"; ","];
1465        ["mkfs"; "ext2"; "/dev/sda1"];
1466        ["mount"; "/dev/sda1"; "/"];
1467        ["mounts"]], ["/dev/sda1"]);
1468     InitEmpty, Always, TestOutputList (
1469       [["sfdiskM"; "/dev/sda"; ","];
1470        ["mkfs"; "ext2"; "/dev/sda1"];
1471        ["mount"; "/dev/sda1"; "/"];
1472        ["umount"; "/"];
1473        ["mounts"]], [])],
1474    "unmount a filesystem",
1475    "\
1476 This unmounts the given filesystem.  The filesystem may be
1477 specified either by its mountpoint (path) or the device which
1478 contains the filesystem.");
1479
1480   ("mounts", (RStringList "devices", []), 46, [],
1481    [InitBasicFS, Always, TestOutputListOfDevices (
1482       [["mounts"]], ["/dev/sda1"])],
1483    "show mounted filesystems",
1484    "\
1485 This returns the list of currently mounted filesystems.  It returns
1486 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1487
1488 Some internal mounts are not shown.
1489
1490 See also: C<guestfs_mountpoints>");
1491
1492   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1493    [InitBasicFS, Always, TestOutputList (
1494       [["umount_all"];
1495        ["mounts"]], []);
1496     (* check that umount_all can unmount nested mounts correctly: *)
1497     InitEmpty, Always, TestOutputList (
1498       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1499        ["mkfs"; "ext2"; "/dev/sda1"];
1500        ["mkfs"; "ext2"; "/dev/sda2"];
1501        ["mkfs"; "ext2"; "/dev/sda3"];
1502        ["mount"; "/dev/sda1"; "/"];
1503        ["mkdir"; "/mp1"];
1504        ["mount"; "/dev/sda2"; "/mp1"];
1505        ["mkdir"; "/mp1/mp2"];
1506        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1507        ["mkdir"; "/mp1/mp2/mp3"];
1508        ["umount_all"];
1509        ["mounts"]], [])],
1510    "unmount all filesystems",
1511    "\
1512 This unmounts all mounted filesystems.
1513
1514 Some internal mounts are not unmounted by this call.");
1515
1516   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1517    [],
1518    "remove all LVM LVs, VGs and PVs",
1519    "\
1520 This command removes all LVM logical volumes, volume groups
1521 and physical volumes.");
1522
1523   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1524    [InitISOFS, Always, TestOutput (
1525       [["file"; "/empty"]], "empty");
1526     InitISOFS, Always, TestOutput (
1527       [["file"; "/known-1"]], "ASCII text");
1528     InitISOFS, Always, TestLastFail (
1529       [["file"; "/notexists"]])],
1530    "determine file type",
1531    "\
1532 This call uses the standard L<file(1)> command to determine
1533 the type or contents of the file.  This also works on devices,
1534 for example to find out whether a partition contains a filesystem.
1535
1536 This call will also transparently look inside various types
1537 of compressed file.
1538
1539 The exact command which runs is C<file -zbsL path>.  Note in
1540 particular that the filename is not prepended to the output
1541 (the C<-b> option).");
1542
1543   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1544    [InitBasicFS, Always, TestOutput (
1545       [["upload"; "test-command"; "/test-command"];
1546        ["chmod"; "0o755"; "/test-command"];
1547        ["command"; "/test-command 1"]], "Result1");
1548     InitBasicFS, Always, TestOutput (
1549       [["upload"; "test-command"; "/test-command"];
1550        ["chmod"; "0o755"; "/test-command"];
1551        ["command"; "/test-command 2"]], "Result2\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["upload"; "test-command"; "/test-command"];
1554        ["chmod"; "0o755"; "/test-command"];
1555        ["command"; "/test-command 3"]], "\nResult3");
1556     InitBasicFS, Always, TestOutput (
1557       [["upload"; "test-command"; "/test-command"];
1558        ["chmod"; "0o755"; "/test-command"];
1559        ["command"; "/test-command 4"]], "\nResult4\n");
1560     InitBasicFS, Always, TestOutput (
1561       [["upload"; "test-command"; "/test-command"];
1562        ["chmod"; "0o755"; "/test-command"];
1563        ["command"; "/test-command 5"]], "\nResult5\n\n");
1564     InitBasicFS, Always, TestOutput (
1565       [["upload"; "test-command"; "/test-command"];
1566        ["chmod"; "0o755"; "/test-command"];
1567        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1568     InitBasicFS, Always, TestOutput (
1569       [["upload"; "test-command"; "/test-command"];
1570        ["chmod"; "0o755"; "/test-command"];
1571        ["command"; "/test-command 7"]], "");
1572     InitBasicFS, Always, TestOutput (
1573       [["upload"; "test-command"; "/test-command"];
1574        ["chmod"; "0o755"; "/test-command"];
1575        ["command"; "/test-command 8"]], "\n");
1576     InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 9"]], "\n\n");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1588     InitBasicFS, Always, TestLastFail (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command"]])],
1592    "run a command from the guest filesystem",
1593    "\
1594 This call runs a command from the guest filesystem.  The
1595 filesystem must be mounted, and must contain a compatible
1596 operating system (ie. something Linux, with the same
1597 or compatible processor architecture).
1598
1599 The single parameter is an argv-style list of arguments.
1600 The first element is the name of the program to run.
1601 Subsequent elements are parameters.  The list must be
1602 non-empty (ie. must contain a program name).  Note that
1603 the command runs directly, and is I<not> invoked via
1604 the shell (see C<guestfs_sh>).
1605
1606 The return value is anything printed to I<stdout> by
1607 the command.
1608
1609 If the command returns a non-zero exit status, then
1610 this function returns an error message.  The error message
1611 string is the content of I<stderr> from the command.
1612
1613 The C<$PATH> environment variable will contain at least
1614 C</usr/bin> and C</bin>.  If you require a program from
1615 another location, you should provide the full path in the
1616 first parameter.
1617
1618 Shared libraries and data files required by the program
1619 must be available on filesystems which are mounted in the
1620 correct places.  It is the caller's responsibility to ensure
1621 all filesystems that are needed are mounted at the right
1622 locations.");
1623
1624   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1625    [InitBasicFS, Always, TestOutputList (
1626       [["upload"; "test-command"; "/test-command"];
1627        ["chmod"; "0o755"; "/test-command"];
1628        ["command_lines"; "/test-command 1"]], ["Result1"]);
1629     InitBasicFS, Always, TestOutputList (
1630       [["upload"; "test-command"; "/test-command"];
1631        ["chmod"; "0o755"; "/test-command"];
1632        ["command_lines"; "/test-command 2"]], ["Result2"]);
1633     InitBasicFS, Always, TestOutputList (
1634       [["upload"; "test-command"; "/test-command"];
1635        ["chmod"; "0o755"; "/test-command"];
1636        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1637     InitBasicFS, Always, TestOutputList (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1641     InitBasicFS, Always, TestOutputList (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1645     InitBasicFS, Always, TestOutputList (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1649     InitBasicFS, Always, TestOutputList (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command_lines"; "/test-command 7"]], []);
1653     InitBasicFS, Always, TestOutputList (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command_lines"; "/test-command 8"]], [""]);
1657     InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 9"]], ["";""]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1669    "run a command, returning lines",
1670    "\
1671 This is the same as C<guestfs_command>, but splits the
1672 result into a list of lines.
1673
1674 See also: C<guestfs_sh_lines>");
1675
1676   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1677    [InitISOFS, Always, TestOutputStruct (
1678       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1679    "get file information",
1680    "\
1681 Returns file information for the given C<path>.
1682
1683 This is the same as the C<stat(2)> system call.");
1684
1685   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1686    [InitISOFS, Always, TestOutputStruct (
1687       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1688    "get file information for a symbolic link",
1689    "\
1690 Returns file information for the given C<path>.
1691
1692 This is the same as C<guestfs_stat> except that if C<path>
1693 is a symbolic link, then the link is stat-ed, not the file it
1694 refers to.
1695
1696 This is the same as the C<lstat(2)> system call.");
1697
1698   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1699    [InitISOFS, Always, TestOutputStruct (
1700       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1701    "get file system statistics",
1702    "\
1703 Returns file system statistics for any mounted file system.
1704 C<path> should be a file or directory in the mounted file system
1705 (typically it is the mount point itself, but it doesn't need to be).
1706
1707 This is the same as the C<statvfs(2)> system call.");
1708
1709   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1710    [], (* XXX test *)
1711    "get ext2/ext3/ext4 superblock details",
1712    "\
1713 This returns the contents of the ext2, ext3 or ext4 filesystem
1714 superblock on C<device>.
1715
1716 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1717 manpage for more details.  The list of fields returned isn't
1718 clearly defined, and depends on both the version of C<tune2fs>
1719 that libguestfs was built against, and the filesystem itself.");
1720
1721   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1722    [InitEmpty, Always, TestOutputTrue (
1723       [["blockdev_setro"; "/dev/sda"];
1724        ["blockdev_getro"; "/dev/sda"]])],
1725    "set block device to read-only",
1726    "\
1727 Sets the block device named C<device> to read-only.
1728
1729 This uses the L<blockdev(8)> command.");
1730
1731   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1732    [InitEmpty, Always, TestOutputFalse (
1733       [["blockdev_setrw"; "/dev/sda"];
1734        ["blockdev_getro"; "/dev/sda"]])],
1735    "set block device to read-write",
1736    "\
1737 Sets the block device named C<device> to read-write.
1738
1739 This uses the L<blockdev(8)> command.");
1740
1741   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1742    [InitEmpty, Always, TestOutputTrue (
1743       [["blockdev_setro"; "/dev/sda"];
1744        ["blockdev_getro"; "/dev/sda"]])],
1745    "is block device set to read-only",
1746    "\
1747 Returns a boolean indicating if the block device is read-only
1748 (true if read-only, false if not).
1749
1750 This uses the L<blockdev(8)> command.");
1751
1752   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1753    [InitEmpty, Always, TestOutputInt (
1754       [["blockdev_getss"; "/dev/sda"]], 512)],
1755    "get sectorsize of block device",
1756    "\
1757 This returns the size of sectors on a block device.
1758 Usually 512, but can be larger for modern devices.
1759
1760 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1761 for that).
1762
1763 This uses the L<blockdev(8)> command.");
1764
1765   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1766    [InitEmpty, Always, TestOutputInt (
1767       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1768    "get blocksize of block device",
1769    "\
1770 This returns the block size of a device.
1771
1772 (Note this is different from both I<size in blocks> and
1773 I<filesystem block size>).
1774
1775 This uses the L<blockdev(8)> command.");
1776
1777   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1778    [], (* XXX test *)
1779    "set blocksize of block device",
1780    "\
1781 This sets the block size of a device.
1782
1783 (Note this is different from both I<size in blocks> and
1784 I<filesystem block size>).
1785
1786 This uses the L<blockdev(8)> command.");
1787
1788   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1789    [InitEmpty, Always, TestOutputInt (
1790       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1791    "get total size of device in 512-byte sectors",
1792    "\
1793 This returns the size of the device in units of 512-byte sectors
1794 (even if the sectorsize isn't 512 bytes ... weird).
1795
1796 See also C<guestfs_blockdev_getss> for the real sector size of
1797 the device, and C<guestfs_blockdev_getsize64> for the more
1798 useful I<size in bytes>.
1799
1800 This uses the L<blockdev(8)> command.");
1801
1802   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1803    [InitEmpty, Always, TestOutputInt (
1804       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1805    "get total size of device in bytes",
1806    "\
1807 This returns the size of the device in bytes.
1808
1809 See also C<guestfs_blockdev_getsz>.
1810
1811 This uses the L<blockdev(8)> command.");
1812
1813   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1814    [InitEmpty, Always, TestRun
1815       [["blockdev_flushbufs"; "/dev/sda"]]],
1816    "flush device buffers",
1817    "\
1818 This tells the kernel to flush internal buffers associated
1819 with C<device>.
1820
1821 This uses the L<blockdev(8)> command.");
1822
1823   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1824    [InitEmpty, Always, TestRun
1825       [["blockdev_rereadpt"; "/dev/sda"]]],
1826    "reread partition table",
1827    "\
1828 Reread the partition table on C<device>.
1829
1830 This uses the L<blockdev(8)> command.");
1831
1832   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1833    [InitBasicFS, Always, TestOutput (
1834       (* Pick a file from cwd which isn't likely to change. *)
1835       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1836        ["checksum"; "md5"; "/COPYING.LIB"]],
1837         Digest.to_hex (Digest.file "COPYING.LIB"))],
1838    "upload a file from the local machine",
1839    "\
1840 Upload local file C<filename> to C<remotefilename> on the
1841 filesystem.
1842
1843 C<filename> can also be a named pipe.
1844
1845 See also C<guestfs_download>.");
1846
1847   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1848    [InitBasicFS, Always, TestOutput (
1849       (* Pick a file from cwd which isn't likely to change. *)
1850       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1851        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1852        ["upload"; "testdownload.tmp"; "/upload"];
1853        ["checksum"; "md5"; "/upload"]],
1854         Digest.to_hex (Digest.file "COPYING.LIB"))],
1855    "download a file to the local machine",
1856    "\
1857 Download file C<remotefilename> and save it as C<filename>
1858 on the local machine.
1859
1860 C<filename> can also be a named pipe.
1861
1862 See also C<guestfs_upload>, C<guestfs_cat>.");
1863
1864   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1865    [InitISOFS, Always, TestOutput (
1866       [["checksum"; "crc"; "/known-3"]], "2891671662");
1867     InitISOFS, Always, TestLastFail (
1868       [["checksum"; "crc"; "/notexists"]]);
1869     InitISOFS, Always, TestOutput (
1870       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1879     InitISOFS, Always, TestOutput (
1880       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1881    "compute MD5, SHAx or CRC checksum of file",
1882    "\
1883 This call computes the MD5, SHAx or CRC checksum of the
1884 file named C<path>.
1885
1886 The type of checksum to compute is given by the C<csumtype>
1887 parameter which must have one of the following values:
1888
1889 =over 4
1890
1891 =item C<crc>
1892
1893 Compute the cyclic redundancy check (CRC) specified by POSIX
1894 for the C<cksum> command.
1895
1896 =item C<md5>
1897
1898 Compute the MD5 hash (using the C<md5sum> program).
1899
1900 =item C<sha1>
1901
1902 Compute the SHA1 hash (using the C<sha1sum> program).
1903
1904 =item C<sha224>
1905
1906 Compute the SHA224 hash (using the C<sha224sum> program).
1907
1908 =item C<sha256>
1909
1910 Compute the SHA256 hash (using the C<sha256sum> program).
1911
1912 =item C<sha384>
1913
1914 Compute the SHA384 hash (using the C<sha384sum> program).
1915
1916 =item C<sha512>
1917
1918 Compute the SHA512 hash (using the C<sha512sum> program).
1919
1920 =back
1921
1922 The checksum is returned as a printable string.");
1923
1924   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1925    [InitBasicFS, Always, TestOutput (
1926       [["tar_in"; "../images/helloworld.tar"; "/"];
1927        ["cat"; "/hello"]], "hello\n")],
1928    "unpack tarfile to directory",
1929    "\
1930 This command uploads and unpacks local file C<tarfile> (an
1931 I<uncompressed> tar file) into C<directory>.
1932
1933 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1934
1935   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1936    [],
1937    "pack directory into tarfile",
1938    "\
1939 This command packs the contents of C<directory> and downloads
1940 it to local file C<tarfile>.
1941
1942 To download a compressed tarball, use C<guestfs_tgz_out>.");
1943
1944   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1945    [InitBasicFS, Always, TestOutput (
1946       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1947        ["cat"; "/hello"]], "hello\n")],
1948    "unpack compressed tarball to directory",
1949    "\
1950 This command uploads and unpacks local file C<tarball> (a
1951 I<gzip compressed> tar file) into C<directory>.
1952
1953 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1954
1955   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1956    [],
1957    "pack directory into compressed tarball",
1958    "\
1959 This command packs the contents of C<directory> and downloads
1960 it to local file C<tarball>.
1961
1962 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1963
1964   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1965    [InitBasicFS, Always, TestLastFail (
1966       [["umount"; "/"];
1967        ["mount_ro"; "/dev/sda1"; "/"];
1968        ["touch"; "/new"]]);
1969     InitBasicFS, Always, TestOutput (
1970       [["write_file"; "/new"; "data"; "0"];
1971        ["umount"; "/"];
1972        ["mount_ro"; "/dev/sda1"; "/"];
1973        ["cat"; "/new"]], "data")],
1974    "mount a guest disk, read-only",
1975    "\
1976 This is the same as the C<guestfs_mount> command, but it
1977 mounts the filesystem with the read-only (I<-o ro>) flag.");
1978
1979   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1980    [],
1981    "mount a guest disk with mount options",
1982    "\
1983 This is the same as the C<guestfs_mount> command, but it
1984 allows you to set the mount options as for the
1985 L<mount(8)> I<-o> flag.");
1986
1987   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1988    [],
1989    "mount a guest disk with mount options and vfstype",
1990    "\
1991 This is the same as the C<guestfs_mount> command, but it
1992 allows you to set both the mount options and the vfstype
1993 as for the L<mount(8)> I<-o> and I<-t> flags.");
1994
1995   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1996    [],
1997    "debugging and internals",
1998    "\
1999 The C<guestfs_debug> command exposes some internals of
2000 C<guestfsd> (the guestfs daemon) that runs inside the
2001 qemu subprocess.
2002
2003 There is no comprehensive help for this command.  You have
2004 to look at the file C<daemon/debug.c> in the libguestfs source
2005 to find out what you can do.");
2006
2007   ("lvremove", (RErr, [Device "device"]), 77, [],
2008    [InitEmpty, Always, TestOutputList (
2009       [["sfdiskM"; "/dev/sda"; ","];
2010        ["pvcreate"; "/dev/sda1"];
2011        ["vgcreate"; "VG"; "/dev/sda1"];
2012        ["lvcreate"; "LV1"; "VG"; "50"];
2013        ["lvcreate"; "LV2"; "VG"; "50"];
2014        ["lvremove"; "/dev/VG/LV1"];
2015        ["lvs"]], ["/dev/VG/LV2"]);
2016     InitEmpty, Always, TestOutputList (
2017       [["sfdiskM"; "/dev/sda"; ","];
2018        ["pvcreate"; "/dev/sda1"];
2019        ["vgcreate"; "VG"; "/dev/sda1"];
2020        ["lvcreate"; "LV1"; "VG"; "50"];
2021        ["lvcreate"; "LV2"; "VG"; "50"];
2022        ["lvremove"; "/dev/VG"];
2023        ["lvs"]], []);
2024     InitEmpty, Always, TestOutputList (
2025       [["sfdiskM"; "/dev/sda"; ","];
2026        ["pvcreate"; "/dev/sda1"];
2027        ["vgcreate"; "VG"; "/dev/sda1"];
2028        ["lvcreate"; "LV1"; "VG"; "50"];
2029        ["lvcreate"; "LV2"; "VG"; "50"];
2030        ["lvremove"; "/dev/VG"];
2031        ["vgs"]], ["VG"])],
2032    "remove an LVM logical volume",
2033    "\
2034 Remove an LVM logical volume C<device>, where C<device> is
2035 the path to the LV, such as C</dev/VG/LV>.
2036
2037 You can also remove all LVs in a volume group by specifying
2038 the VG name, C</dev/VG>.");
2039
2040   ("vgremove", (RErr, [String "vgname"]), 78, [],
2041    [InitEmpty, Always, TestOutputList (
2042       [["sfdiskM"; "/dev/sda"; ","];
2043        ["pvcreate"; "/dev/sda1"];
2044        ["vgcreate"; "VG"; "/dev/sda1"];
2045        ["lvcreate"; "LV1"; "VG"; "50"];
2046        ["lvcreate"; "LV2"; "VG"; "50"];
2047        ["vgremove"; "VG"];
2048        ["lvs"]], []);
2049     InitEmpty, Always, TestOutputList (
2050       [["sfdiskM"; "/dev/sda"; ","];
2051        ["pvcreate"; "/dev/sda1"];
2052        ["vgcreate"; "VG"; "/dev/sda1"];
2053        ["lvcreate"; "LV1"; "VG"; "50"];
2054        ["lvcreate"; "LV2"; "VG"; "50"];
2055        ["vgremove"; "VG"];
2056        ["vgs"]], [])],
2057    "remove an LVM volume group",
2058    "\
2059 Remove an LVM volume group C<vgname>, (for example C<VG>).
2060
2061 This also forcibly removes all logical volumes in the volume
2062 group (if any).");
2063
2064   ("pvremove", (RErr, [Device "device"]), 79, [],
2065    [InitEmpty, Always, TestOutputListOfDevices (
2066       [["sfdiskM"; "/dev/sda"; ","];
2067        ["pvcreate"; "/dev/sda1"];
2068        ["vgcreate"; "VG"; "/dev/sda1"];
2069        ["lvcreate"; "LV1"; "VG"; "50"];
2070        ["lvcreate"; "LV2"; "VG"; "50"];
2071        ["vgremove"; "VG"];
2072        ["pvremove"; "/dev/sda1"];
2073        ["lvs"]], []);
2074     InitEmpty, Always, TestOutputListOfDevices (
2075       [["sfdiskM"; "/dev/sda"; ","];
2076        ["pvcreate"; "/dev/sda1"];
2077        ["vgcreate"; "VG"; "/dev/sda1"];
2078        ["lvcreate"; "LV1"; "VG"; "50"];
2079        ["lvcreate"; "LV2"; "VG"; "50"];
2080        ["vgremove"; "VG"];
2081        ["pvremove"; "/dev/sda1"];
2082        ["vgs"]], []);
2083     InitEmpty, Always, TestOutputListOfDevices (
2084       [["sfdiskM"; "/dev/sda"; ","];
2085        ["pvcreate"; "/dev/sda1"];
2086        ["vgcreate"; "VG"; "/dev/sda1"];
2087        ["lvcreate"; "LV1"; "VG"; "50"];
2088        ["lvcreate"; "LV2"; "VG"; "50"];
2089        ["vgremove"; "VG"];
2090        ["pvremove"; "/dev/sda1"];
2091        ["pvs"]], [])],
2092    "remove an LVM physical volume",
2093    "\
2094 This wipes a physical volume C<device> so that LVM will no longer
2095 recognise it.
2096
2097 The implementation uses the C<pvremove> command which refuses to
2098 wipe physical volumes that contain any volume groups, so you have
2099 to remove those first.");
2100
2101   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2102    [InitBasicFS, Always, TestOutput (
2103       [["set_e2label"; "/dev/sda1"; "testlabel"];
2104        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2105    "set the ext2/3/4 filesystem label",
2106    "\
2107 This sets the ext2/3/4 filesystem label of the filesystem on
2108 C<device> to C<label>.  Filesystem labels are limited to
2109 16 characters.
2110
2111 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2112 to return the existing label on a filesystem.");
2113
2114   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2115    [],
2116    "get the ext2/3/4 filesystem label",
2117    "\
2118 This returns the ext2/3/4 filesystem label of the filesystem on
2119 C<device>.");
2120
2121   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2122    (let uuid = uuidgen () in
2123     [InitBasicFS, Always, TestOutput (
2124        [["set_e2uuid"; "/dev/sda1"; uuid];
2125         ["get_e2uuid"; "/dev/sda1"]], uuid);
2126      InitBasicFS, Always, TestOutput (
2127        [["set_e2uuid"; "/dev/sda1"; "clear"];
2128         ["get_e2uuid"; "/dev/sda1"]], "");
2129      (* We can't predict what UUIDs will be, so just check the commands run. *)
2130      InitBasicFS, Always, TestRun (
2131        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2132      InitBasicFS, Always, TestRun (
2133        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2134    "set the ext2/3/4 filesystem UUID",
2135    "\
2136 This sets the ext2/3/4 filesystem UUID of the filesystem on
2137 C<device> to C<uuid>.  The format of the UUID and alternatives
2138 such as C<clear>, C<random> and C<time> are described in the
2139 L<tune2fs(8)> manpage.
2140
2141 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2142 to return the existing UUID of a filesystem.");
2143
2144   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2145    [],
2146    "get the ext2/3/4 filesystem UUID",
2147    "\
2148 This returns the ext2/3/4 filesystem UUID of the filesystem on
2149 C<device>.");
2150
2151   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2152    [InitBasicFS, Always, TestOutputInt (
2153       [["umount"; "/dev/sda1"];
2154        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2155     InitBasicFS, Always, TestOutputInt (
2156       [["umount"; "/dev/sda1"];
2157        ["zero"; "/dev/sda1"];
2158        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2159    "run the filesystem checker",
2160    "\
2161 This runs the filesystem checker (fsck) on C<device> which
2162 should have filesystem type C<fstype>.
2163
2164 The returned integer is the status.  See L<fsck(8)> for the
2165 list of status codes from C<fsck>.
2166
2167 Notes:
2168
2169 =over 4
2170
2171 =item *
2172
2173 Multiple status codes can be summed together.
2174
2175 =item *
2176
2177 A non-zero return code can mean \"success\", for example if
2178 errors have been corrected on the filesystem.
2179
2180 =item *
2181
2182 Checking or repairing NTFS volumes is not supported
2183 (by linux-ntfs).
2184
2185 =back
2186
2187 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2188
2189   ("zero", (RErr, [Device "device"]), 85, [],
2190    [InitBasicFS, Always, TestOutput (
2191       [["umount"; "/dev/sda1"];
2192        ["zero"; "/dev/sda1"];
2193        ["file"; "/dev/sda1"]], "data")],
2194    "write zeroes to the device",
2195    "\
2196 This command writes zeroes over the first few blocks of C<device>.
2197
2198 How many blocks are zeroed isn't specified (but it's I<not> enough
2199 to securely wipe the device).  It should be sufficient to remove
2200 any partition tables, filesystem superblocks and so on.
2201
2202 See also: C<guestfs_scrub_device>.");
2203
2204   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2205    (* Test disabled because grub-install incompatible with virtio-blk driver.
2206     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2207     *)
2208    [InitBasicFS, Disabled, TestOutputTrue (
2209       [["grub_install"; "/"; "/dev/sda1"];
2210        ["is_dir"; "/boot"]])],
2211    "install GRUB",
2212    "\
2213 This command installs GRUB (the Grand Unified Bootloader) on
2214 C<device>, with the root directory being C<root>.");
2215
2216   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2217    [InitBasicFS, Always, TestOutput (
2218       [["write_file"; "/old"; "file content"; "0"];
2219        ["cp"; "/old"; "/new"];
2220        ["cat"; "/new"]], "file content");
2221     InitBasicFS, Always, TestOutputTrue (
2222       [["write_file"; "/old"; "file content"; "0"];
2223        ["cp"; "/old"; "/new"];
2224        ["is_file"; "/old"]]);
2225     InitBasicFS, Always, TestOutput (
2226       [["write_file"; "/old"; "file content"; "0"];
2227        ["mkdir"; "/dir"];
2228        ["cp"; "/old"; "/dir/new"];
2229        ["cat"; "/dir/new"]], "file content")],
2230    "copy a file",
2231    "\
2232 This copies a file from C<src> to C<dest> where C<dest> is
2233 either a destination filename or destination directory.");
2234
2235   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2236    [InitBasicFS, Always, TestOutput (
2237       [["mkdir"; "/olddir"];
2238        ["mkdir"; "/newdir"];
2239        ["write_file"; "/olddir/file"; "file content"; "0"];
2240        ["cp_a"; "/olddir"; "/newdir"];
2241        ["cat"; "/newdir/olddir/file"]], "file content")],
2242    "copy a file or directory recursively",
2243    "\
2244 This copies a file or directory from C<src> to C<dest>
2245 recursively using the C<cp -a> command.");
2246
2247   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2248    [InitBasicFS, Always, TestOutput (
2249       [["write_file"; "/old"; "file content"; "0"];
2250        ["mv"; "/old"; "/new"];
2251        ["cat"; "/new"]], "file content");
2252     InitBasicFS, Always, TestOutputFalse (
2253       [["write_file"; "/old"; "file content"; "0"];
2254        ["mv"; "/old"; "/new"];
2255        ["is_file"; "/old"]])],
2256    "move a file",
2257    "\
2258 This moves a file from C<src> to C<dest> where C<dest> is
2259 either a destination filename or destination directory.");
2260
2261   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2262    [InitEmpty, Always, TestRun (
2263       [["drop_caches"; "3"]])],
2264    "drop kernel page cache, dentries and inodes",
2265    "\
2266 This instructs the guest kernel to drop its page cache,
2267 and/or dentries and inode caches.  The parameter C<whattodrop>
2268 tells the kernel what precisely to drop, see
2269 L<http://linux-mm.org/Drop_Caches>
2270
2271 Setting C<whattodrop> to 3 should drop everything.
2272
2273 This automatically calls L<sync(2)> before the operation,
2274 so that the maximum guest memory is freed.");
2275
2276   ("dmesg", (RString "kmsgs", []), 91, [],
2277    [InitEmpty, Always, TestRun (
2278       [["dmesg"]])],
2279    "return kernel messages",
2280    "\
2281 This returns the kernel messages (C<dmesg> output) from
2282 the guest kernel.  This is sometimes useful for extended
2283 debugging of problems.
2284
2285 Another way to get the same information is to enable
2286 verbose messages with C<guestfs_set_verbose> or by setting
2287 the environment variable C<LIBGUESTFS_DEBUG=1> before
2288 running the program.");
2289
2290   ("ping_daemon", (RErr, []), 92, [],
2291    [InitEmpty, Always, TestRun (
2292       [["ping_daemon"]])],
2293    "ping the guest daemon",
2294    "\
2295 This is a test probe into the guestfs daemon running inside
2296 the qemu subprocess.  Calling this function checks that the
2297 daemon responds to the ping message, without affecting the daemon
2298 or attached block device(s) in any other way.");
2299
2300   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2301    [InitBasicFS, Always, TestOutputTrue (
2302       [["write_file"; "/file1"; "contents of a file"; "0"];
2303        ["cp"; "/file1"; "/file2"];
2304        ["equal"; "/file1"; "/file2"]]);
2305     InitBasicFS, Always, TestOutputFalse (
2306       [["write_file"; "/file1"; "contents of a file"; "0"];
2307        ["write_file"; "/file2"; "contents of another file"; "0"];
2308        ["equal"; "/file1"; "/file2"]]);
2309     InitBasicFS, Always, TestLastFail (
2310       [["equal"; "/file1"; "/file2"]])],
2311    "test if two files have equal contents",
2312    "\
2313 This compares the two files C<file1> and C<file2> and returns
2314 true if their content is exactly equal, or false otherwise.
2315
2316 The external L<cmp(1)> program is used for the comparison.");
2317
2318   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2319    [InitISOFS, Always, TestOutputList (
2320       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2321     InitISOFS, Always, TestOutputList (
2322       [["strings"; "/empty"]], [])],
2323    "print the printable strings in a file",
2324    "\
2325 This runs the L<strings(1)> command on a file and returns
2326 the list of printable strings found.");
2327
2328   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2329    [InitISOFS, Always, TestOutputList (
2330       [["strings_e"; "b"; "/known-5"]], []);
2331     InitBasicFS, Disabled, TestOutputList (
2332       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2333        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2334    "print the printable strings in a file",
2335    "\
2336 This is like the C<guestfs_strings> command, but allows you to
2337 specify the encoding.
2338
2339 See the L<strings(1)> manpage for the full list of encodings.
2340
2341 Commonly useful encodings are C<l> (lower case L) which will
2342 show strings inside Windows/x86 files.
2343
2344 The returned strings are transcoded to UTF-8.");
2345
2346   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2347    [InitISOFS, Always, TestOutput (
2348       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2349     (* Test for RHBZ#501888c2 regression which caused large hexdump
2350      * commands to segfault.
2351      *)
2352     InitISOFS, Always, TestRun (
2353       [["hexdump"; "/100krandom"]])],
2354    "dump a file in hexadecimal",
2355    "\
2356 This runs C<hexdump -C> on the given C<path>.  The result is
2357 the human-readable, canonical hex dump of the file.");
2358
2359   ("zerofree", (RErr, [Device "device"]), 97, [],
2360    [InitNone, Always, TestOutput (
2361       [["sfdiskM"; "/dev/sda"; ","];
2362        ["mkfs"; "ext3"; "/dev/sda1"];
2363        ["mount"; "/dev/sda1"; "/"];
2364        ["write_file"; "/new"; "test file"; "0"];
2365        ["umount"; "/dev/sda1"];
2366        ["zerofree"; "/dev/sda1"];
2367        ["mount"; "/dev/sda1"; "/"];
2368        ["cat"; "/new"]], "test file")],
2369    "zero unused inodes and disk blocks on ext2/3 filesystem",
2370    "\
2371 This runs the I<zerofree> program on C<device>.  This program
2372 claims to zero unused inodes and disk blocks on an ext2/3
2373 filesystem, thus making it possible to compress the filesystem
2374 more effectively.
2375
2376 You should B<not> run this program if the filesystem is
2377 mounted.
2378
2379 It is possible that using this program can damage the filesystem
2380 or data on the filesystem.");
2381
2382   ("pvresize", (RErr, [Device "device"]), 98, [],
2383    [],
2384    "resize an LVM physical volume",
2385    "\
2386 This resizes (expands or shrinks) an existing LVM physical
2387 volume to match the new size of the underlying device.");
2388
2389   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2390                        Int "cyls"; Int "heads"; Int "sectors";
2391                        String "line"]), 99, [DangerWillRobinson],
2392    [],
2393    "modify a single partition on a block device",
2394    "\
2395 This runs L<sfdisk(8)> option to modify just the single
2396 partition C<n> (note: C<n> counts from 1).
2397
2398 For other parameters, see C<guestfs_sfdisk>.  You should usually
2399 pass C<0> for the cyls/heads/sectors parameters.");
2400
2401   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2402    [],
2403    "display the partition table",
2404    "\
2405 This displays the partition table on C<device>, in the
2406 human-readable output of the L<sfdisk(8)> command.  It is
2407 not intended to be parsed.");
2408
2409   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2410    [],
2411    "display the kernel geometry",
2412    "\
2413 This displays the kernel's idea of the geometry of C<device>.
2414
2415 The result is in human-readable format, and not designed to
2416 be parsed.");
2417
2418   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2419    [],
2420    "display the disk geometry from the partition table",
2421    "\
2422 This displays the disk geometry of C<device> read from the
2423 partition table.  Especially in the case where the underlying
2424 block device has been resized, this can be different from the
2425 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2426
2427 The result is in human-readable format, and not designed to
2428 be parsed.");
2429
2430   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2431    [],
2432    "activate or deactivate all volume groups",
2433    "\
2434 This command activates or (if C<activate> is false) deactivates
2435 all logical volumes in all volume groups.
2436 If activated, then they are made known to the
2437 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2438 then those devices disappear.
2439
2440 This command is the same as running C<vgchange -a y|n>");
2441
2442   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2443    [],
2444    "activate or deactivate some volume groups",
2445    "\
2446 This command activates or (if C<activate> is false) deactivates
2447 all logical volumes in the listed volume groups C<volgroups>.
2448 If activated, then they are made known to the
2449 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2450 then those devices disappear.
2451
2452 This command is the same as running C<vgchange -a y|n volgroups...>
2453
2454 Note that if C<volgroups> is an empty list then B<all> volume groups
2455 are activated or deactivated.");
2456
2457   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2458    [InitNone, Always, TestOutput (
2459       [["sfdiskM"; "/dev/sda"; ","];
2460        ["pvcreate"; "/dev/sda1"];
2461        ["vgcreate"; "VG"; "/dev/sda1"];
2462        ["lvcreate"; "LV"; "VG"; "10"];
2463        ["mkfs"; "ext2"; "/dev/VG/LV"];
2464        ["mount"; "/dev/VG/LV"; "/"];
2465        ["write_file"; "/new"; "test content"; "0"];
2466        ["umount"; "/"];
2467        ["lvresize"; "/dev/VG/LV"; "20"];
2468        ["e2fsck_f"; "/dev/VG/LV"];
2469        ["resize2fs"; "/dev/VG/LV"];
2470        ["mount"; "/dev/VG/LV"; "/"];
2471        ["cat"; "/new"]], "test content")],
2472    "resize an LVM logical volume",
2473    "\
2474 This resizes (expands or shrinks) an existing LVM logical
2475 volume to C<mbytes>.  When reducing, data in the reduced part
2476 is lost.");
2477
2478   ("resize2fs", (RErr, [Device "device"]), 106, [],
2479    [], (* lvresize tests this *)
2480    "resize an ext2/ext3 filesystem",
2481    "\
2482 This resizes an ext2 or ext3 filesystem to match the size of
2483 the underlying device.
2484
2485 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2486 on the C<device> before calling this command.  For unknown reasons
2487 C<resize2fs> sometimes gives an error about this and sometimes not.
2488 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2489 calling this function.");
2490
2491   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2492    [InitBasicFS, Always, TestOutputList (
2493       [["find"; "/"]], ["lost+found"]);
2494     InitBasicFS, Always, TestOutputList (
2495       [["touch"; "/a"];
2496        ["mkdir"; "/b"];
2497        ["touch"; "/b/c"];
2498        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2499     InitBasicFS, Always, TestOutputList (
2500       [["mkdir_p"; "/a/b/c"];
2501        ["touch"; "/a/b/c/d"];
2502        ["find"; "/a/b/"]], ["c"; "c/d"])],
2503    "find all files and directories",
2504    "\
2505 This command lists out all files and directories, recursively,
2506 starting at C<directory>.  It is essentially equivalent to
2507 running the shell command C<find directory -print> but some
2508 post-processing happens on the output, described below.
2509
2510 This returns a list of strings I<without any prefix>.  Thus
2511 if the directory structure was:
2512
2513  /tmp/a
2514  /tmp/b
2515  /tmp/c/d
2516
2517 then the returned list from C<guestfs_find> C</tmp> would be
2518 4 elements:
2519
2520  a
2521  b
2522  c
2523  c/d
2524
2525 If C<directory> is not a directory, then this command returns
2526 an error.
2527
2528 The returned list is sorted.
2529
2530 See also C<guestfs_find0>.");
2531
2532   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2533    [], (* lvresize tests this *)
2534    "check an ext2/ext3 filesystem",
2535    "\
2536 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2537 filesystem checker on C<device>, noninteractively (C<-p>),
2538 even if the filesystem appears to be clean (C<-f>).
2539
2540 This command is only needed because of C<guestfs_resize2fs>
2541 (q.v.).  Normally you should use C<guestfs_fsck>.");
2542
2543   ("sleep", (RErr, [Int "secs"]), 109, [],
2544    [InitNone, Always, TestRun (
2545       [["sleep"; "1"]])],
2546    "sleep for some seconds",
2547    "\
2548 Sleep for C<secs> seconds.");
2549
2550   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2551    [InitNone, Always, TestOutputInt (
2552       [["sfdiskM"; "/dev/sda"; ","];
2553        ["mkfs"; "ntfs"; "/dev/sda1"];
2554        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2555     InitNone, Always, TestOutputInt (
2556       [["sfdiskM"; "/dev/sda"; ","];
2557        ["mkfs"; "ext2"; "/dev/sda1"];
2558        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2559    "probe NTFS volume",
2560    "\
2561 This command runs the L<ntfs-3g.probe(8)> command which probes
2562 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2563 be mounted read-write, and some cannot be mounted at all).
2564
2565 C<rw> is a boolean flag.  Set it to true if you want to test
2566 if the volume can be mounted read-write.  Set it to false if
2567 you want to test if the volume can be mounted read-only.
2568
2569 The return value is an integer which C<0> if the operation
2570 would succeed, or some non-zero value documented in the
2571 L<ntfs-3g.probe(8)> manual page.");
2572
2573   ("sh", (RString "output", [String "command"]), 111, [],
2574    [], (* XXX needs tests *)
2575    "run a command via the shell",
2576    "\
2577 This call runs a command from the guest filesystem via the
2578 guest's C</bin/sh>.
2579
2580 This is like C<guestfs_command>, but passes the command to:
2581
2582  /bin/sh -c \"command\"
2583
2584 Depending on the guest's shell, this usually results in
2585 wildcards being expanded, shell expressions being interpolated
2586 and so on.
2587
2588 All the provisos about C<guestfs_command> apply to this call.");
2589
2590   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2591    [], (* XXX needs tests *)
2592    "run a command via the shell returning lines",
2593    "\
2594 This is the same as C<guestfs_sh>, but splits the result
2595 into a list of lines.
2596
2597 See also: C<guestfs_command_lines>");
2598
2599   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2600    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2601     * code in stubs.c, since all valid glob patterns must start with "/".
2602     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2603     *)
2604    [InitBasicFS, Always, TestOutputList (
2605       [["mkdir_p"; "/a/b/c"];
2606        ["touch"; "/a/b/c/d"];
2607        ["touch"; "/a/b/c/e"];
2608        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2609     InitBasicFS, Always, TestOutputList (
2610       [["mkdir_p"; "/a/b/c"];
2611        ["touch"; "/a/b/c/d"];
2612        ["touch"; "/a/b/c/e"];
2613        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2614     InitBasicFS, Always, TestOutputList (
2615       [["mkdir_p"; "/a/b/c"];
2616        ["touch"; "/a/b/c/d"];
2617        ["touch"; "/a/b/c/e"];
2618        ["glob_expand"; "/a/*/x/*"]], [])],
2619    "expand a wildcard path",
2620    "\
2621 This command searches for all the pathnames matching
2622 C<pattern> according to the wildcard expansion rules
2623 used by the shell.
2624
2625 If no paths match, then this returns an empty list
2626 (note: not an error).
2627
2628 It is just a wrapper around the C L<glob(3)> function
2629 with flags C<GLOB_MARK|GLOB_BRACE>.
2630 See that manual page for more details.");
2631
2632   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2633    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2634       [["scrub_device"; "/dev/sdc"]])],
2635    "scrub (securely wipe) a device",
2636    "\
2637 This command writes patterns over C<device> to make data retrieval
2638 more difficult.
2639
2640 It is an interface to the L<scrub(1)> program.  See that
2641 manual page for more details.");
2642
2643   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2644    [InitBasicFS, Always, TestRun (
2645       [["write_file"; "/file"; "content"; "0"];
2646        ["scrub_file"; "/file"]])],
2647    "scrub (securely wipe) a file",
2648    "\
2649 This command writes patterns over a file to make data retrieval
2650 more difficult.
2651
2652 The file is I<removed> after scrubbing.
2653
2654 It is an interface to the L<scrub(1)> program.  See that
2655 manual page for more details.");
2656
2657   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2658    [], (* XXX needs testing *)
2659    "scrub (securely wipe) free space",
2660    "\
2661 This command creates the directory C<dir> and then fills it
2662 with files until the filesystem is full, and scrubs the files
2663 as for C<guestfs_scrub_file>, and deletes them.
2664 The intention is to scrub any free space on the partition
2665 containing C<dir>.
2666
2667 It is an interface to the L<scrub(1)> program.  See that
2668 manual page for more details.");
2669
2670   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2671    [InitBasicFS, Always, TestRun (
2672       [["mkdir"; "/tmp"];
2673        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2674    "create a temporary directory",
2675    "\
2676 This command creates a temporary directory.  The
2677 C<template> parameter should be a full pathname for the
2678 temporary directory name with the final six characters being
2679 \"XXXXXX\".
2680
2681 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2682 the second one being suitable for Windows filesystems.
2683
2684 The name of the temporary directory that was created
2685 is returned.
2686
2687 The temporary directory is created with mode 0700
2688 and is owned by root.
2689
2690 The caller is responsible for deleting the temporary
2691 directory and its contents after use.
2692
2693 See also: L<mkdtemp(3)>");
2694
2695   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2696    [InitISOFS, Always, TestOutputInt (
2697       [["wc_l"; "/10klines"]], 10000)],
2698    "count lines in a file",
2699    "\
2700 This command counts the lines in a file, using the
2701 C<wc -l> external command.");
2702
2703   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2704    [InitISOFS, Always, TestOutputInt (
2705       [["wc_w"; "/10klines"]], 10000)],
2706    "count words in a file",
2707    "\
2708 This command counts the words in a file, using the
2709 C<wc -w> external command.");
2710
2711   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2712    [InitISOFS, Always, TestOutputInt (
2713       [["wc_c"; "/100kallspaces"]], 102400)],
2714    "count characters in a file",
2715    "\
2716 This command counts the characters in a file, using the
2717 C<wc -c> external command.");
2718
2719   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2720    [InitISOFS, Always, TestOutputList (
2721       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2722    "return first 10 lines of a file",
2723    "\
2724 This command returns up to the first 10 lines of a file as
2725 a list of strings.");
2726
2727   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2728    [InitISOFS, Always, TestOutputList (
2729       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2730     InitISOFS, Always, TestOutputList (
2731       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732     InitISOFS, Always, TestOutputList (
2733       [["head_n"; "0"; "/10klines"]], [])],
2734    "return first N lines of a file",
2735    "\
2736 If the parameter C<nrlines> is a positive number, this returns the first
2737 C<nrlines> lines of the file C<path>.
2738
2739 If the parameter C<nrlines> is a negative number, this returns lines
2740 from the file C<path>, excluding the last C<nrlines> lines.
2741
2742 If the parameter C<nrlines> is zero, this returns an empty list.");
2743
2744   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2745    [InitISOFS, Always, TestOutputList (
2746       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2747    "return last 10 lines of a file",
2748    "\
2749 This command returns up to the last 10 lines of a file as
2750 a list of strings.");
2751
2752   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2753    [InitISOFS, Always, TestOutputList (
2754       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2755     InitISOFS, Always, TestOutputList (
2756       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757     InitISOFS, Always, TestOutputList (
2758       [["tail_n"; "0"; "/10klines"]], [])],
2759    "return last N lines of a file",
2760    "\
2761 If the parameter C<nrlines> is a positive number, this returns the last
2762 C<nrlines> lines of the file C<path>.
2763
2764 If the parameter C<nrlines> is a negative number, this returns lines
2765 from the file C<path>, starting with the C<-nrlines>th line.
2766
2767 If the parameter C<nrlines> is zero, this returns an empty list.");
2768
2769   ("df", (RString "output", []), 125, [],
2770    [], (* XXX Tricky to test because it depends on the exact format
2771         * of the 'df' command and other imponderables.
2772         *)
2773    "report file system disk space usage",
2774    "\
2775 This command runs the C<df> command to report disk space used.
2776
2777 This command is mostly useful for interactive sessions.  It
2778 is I<not> intended that you try to parse the output string.
2779 Use C<statvfs> from programs.");
2780
2781   ("df_h", (RString "output", []), 126, [],
2782    [], (* XXX Tricky to test because it depends on the exact format
2783         * of the 'df' command and other imponderables.
2784         *)
2785    "report file system disk space usage (human readable)",
2786    "\
2787 This command runs the C<df -h> command to report disk space used
2788 in human-readable format.
2789
2790 This command is mostly useful for interactive sessions.  It
2791 is I<not> intended that you try to parse the output string.
2792 Use C<statvfs> from programs.");
2793
2794   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2797    "estimate file space usage",
2798    "\
2799 This command runs the C<du -s> command to estimate file space
2800 usage for C<path>.
2801
2802 C<path> can be a file or a directory.  If C<path> is a directory
2803 then the estimate includes the contents of the directory and all
2804 subdirectories (recursively).
2805
2806 The result is the estimated size in I<kilobytes>
2807 (ie. units of 1024 bytes).");
2808
2809   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2810    [InitISOFS, Always, TestOutputList (
2811       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2812    "list files in an initrd",
2813    "\
2814 This command lists out files contained in an initrd.
2815
2816 The files are listed without any initial C</> character.  The
2817 files are listed in the order they appear (not necessarily
2818 alphabetical).  Directory names are listed as separate items.
2819
2820 Old Linux kernels (2.4 and earlier) used a compressed ext2
2821 filesystem as initrd.  We I<only> support the newer initramfs
2822 format (compressed cpio files).");
2823
2824   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2825    [],
2826    "mount a file using the loop device",
2827    "\
2828 This command lets you mount C<file> (a filesystem image
2829 in a file) on a mount point.  It is entirely equivalent to
2830 the command C<mount -o loop file mountpoint>.");
2831
2832   ("mkswap", (RErr, [Device "device"]), 130, [],
2833    [InitEmpty, Always, TestRun (
2834       [["sfdiskM"; "/dev/sda"; ","];
2835        ["mkswap"; "/dev/sda1"]])],
2836    "create a swap partition",
2837    "\
2838 Create a swap partition on C<device>.");
2839
2840   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2841    [InitEmpty, Always, TestRun (
2842       [["sfdiskM"; "/dev/sda"; ","];
2843        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2844    "create a swap partition with a label",
2845    "\
2846 Create a swap partition on C<device> with label C<label>.
2847
2848 Note that you cannot attach a swap label to a block device
2849 (eg. C</dev/sda>), just to a partition.  This appears to be
2850 a limitation of the kernel or swap tools.");
2851
2852   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2853    (let uuid = uuidgen () in
2854     [InitEmpty, Always, TestRun (
2855        [["sfdiskM"; "/dev/sda"; ","];
2856         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2857    "create a swap partition with an explicit UUID",
2858    "\
2859 Create a swap partition on C<device> with UUID C<uuid>.");
2860
2861   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2862    [InitBasicFS, Always, TestOutputStruct (
2863       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2864        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2865        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2866     InitBasicFS, Always, TestOutputStruct (
2867       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2868        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2869    "make block, character or FIFO devices",
2870    "\
2871 This call creates block or character special devices, or
2872 named pipes (FIFOs).
2873
2874 The C<mode> parameter should be the mode, using the standard
2875 constants.  C<devmajor> and C<devminor> are the
2876 device major and minor numbers, only used when creating block
2877 and character special devices.");
2878
2879   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2880    [InitBasicFS, Always, TestOutputStruct (
2881       [["mkfifo"; "0o777"; "/node"];
2882        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2883    "make FIFO (named pipe)",
2884    "\
2885 This call creates a FIFO (named pipe) called C<path> with
2886 mode C<mode>.  It is just a convenient wrapper around
2887 C<guestfs_mknod>.");
2888
2889   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2890    [InitBasicFS, Always, TestOutputStruct (
2891       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2892        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2893    "make block device node",
2894    "\
2895 This call creates a block device node called C<path> with
2896 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2897 It is just a convenient wrapper around C<guestfs_mknod>.");
2898
2899   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2900    [InitBasicFS, Always, TestOutputStruct (
2901       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2902        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2903    "make char device node",
2904    "\
2905 This call creates a char device node called C<path> with
2906 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2907 It is just a convenient wrapper around C<guestfs_mknod>.");
2908
2909   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2910    [], (* XXX umask is one of those stateful things that we should
2911         * reset between each test.
2912         *)
2913    "set file mode creation mask (umask)",
2914    "\
2915 This function sets the mask used for creating new files and
2916 device nodes to C<mask & 0777>.
2917
2918 Typical umask values would be C<022> which creates new files
2919 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2920 C<002> which creates new files with permissions like
2921 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2922
2923 The default umask is C<022>.  This is important because it
2924 means that directories and device nodes will be created with
2925 C<0644> or C<0755> mode even if you specify C<0777>.
2926
2927 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2928
2929 This call returns the previous umask.");
2930
2931   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2932    [],
2933    "read directories entries",
2934    "\
2935 This returns the list of directory entries in directory C<dir>.
2936
2937 All entries in the directory are returned, including C<.> and
2938 C<..>.  The entries are I<not> sorted, but returned in the same
2939 order as the underlying filesystem.
2940
2941 Also this call returns basic file type information about each
2942 file.  The C<ftyp> field will contain one of the following characters:
2943
2944 =over 4
2945
2946 =item 'b'
2947
2948 Block special
2949
2950 =item 'c'
2951
2952 Char special
2953
2954 =item 'd'
2955
2956 Directory
2957
2958 =item 'f'
2959
2960 FIFO (named pipe)
2961
2962 =item 'l'
2963
2964 Symbolic link
2965
2966 =item 'r'
2967
2968 Regular file
2969
2970 =item 's'
2971
2972 Socket
2973
2974 =item 'u'
2975
2976 Unknown file type
2977
2978 =item '?'
2979
2980 The L<readdir(3)> returned a C<d_type> field with an
2981 unexpected value
2982
2983 =back
2984
2985 This function is primarily intended for use by programs.  To
2986 get a simple list of names, use C<guestfs_ls>.  To get a printable
2987 directory for human consumption, use C<guestfs_ll>.");
2988
2989   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2990    [],
2991    "create partitions on a block device",
2992    "\
2993 This is a simplified interface to the C<guestfs_sfdisk>
2994 command, where partition sizes are specified in megabytes
2995 only (rounded to the nearest cylinder) and you don't need
2996 to specify the cyls, heads and sectors parameters which
2997 were rarely if ever used anyway.
2998
2999 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3000
3001   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3002    [],
3003    "determine file type inside a compressed file",
3004    "\
3005 This command runs C<file> after first decompressing C<path>
3006 using C<method>.
3007
3008 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3009
3010 Since 1.0.63, use C<guestfs_file> instead which can now
3011 process compressed files.");
3012
3013   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3014    [],
3015    "list extended attributes of a file or directory",
3016    "\
3017 This call lists the extended attributes of the file or directory
3018 C<path>.
3019
3020 At the system call level, this is a combination of the
3021 L<listxattr(2)> and L<getxattr(2)> calls.
3022
3023 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3024
3025   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3026    [],
3027    "list extended attributes of a file or directory",
3028    "\
3029 This is the same as C<guestfs_getxattrs>, but if C<path>
3030 is a symbolic link, then it returns the extended attributes
3031 of the link itself.");
3032
3033   ("setxattr", (RErr, [String "xattr";
3034                        String "val"; Int "vallen"; (* will be BufferIn *)
3035                        Pathname "path"]), 143, [],
3036    [],
3037    "set extended attribute of a file or directory",
3038    "\
3039 This call sets the extended attribute named C<xattr>
3040 of the file C<path> to the value C<val> (of length C<vallen>).
3041 The value is arbitrary 8 bit data.
3042
3043 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3044
3045   ("lsetxattr", (RErr, [String "xattr";
3046                         String "val"; Int "vallen"; (* will be BufferIn *)
3047                         Pathname "path"]), 144, [],
3048    [],
3049    "set extended attribute of a file or directory",
3050    "\
3051 This is the same as C<guestfs_setxattr>, but if C<path>
3052 is a symbolic link, then it sets an extended attribute
3053 of the link itself.");
3054
3055   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3056    [],
3057    "remove extended attribute of a file or directory",
3058    "\
3059 This call removes the extended attribute named C<xattr>
3060 of the file C<path>.
3061
3062 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3063
3064   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3065    [],
3066    "remove extended attribute of a file or directory",
3067    "\
3068 This is the same as C<guestfs_removexattr>, but if C<path>
3069 is a symbolic link, then it removes an extended attribute
3070 of the link itself.");
3071
3072   ("mountpoints", (RHashtable "mps", []), 147, [],
3073    [],
3074    "show mountpoints",
3075    "\
3076 This call is similar to C<guestfs_mounts>.  That call returns
3077 a list of devices.  This one returns a hash table (map) of
3078 device name to directory where the device is mounted.");
3079
3080   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3081   (* This is a special case: while you would expect a parameter
3082    * of type "Pathname", that doesn't work, because it implies
3083    * NEED_ROOT in the generated calling code in stubs.c, and
3084    * this function cannot use NEED_ROOT.
3085    *)
3086    [],
3087    "create a mountpoint",
3088    "\
3089 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3090 specialized calls that can be used to create extra mountpoints
3091 before mounting the first filesystem.
3092
3093 These calls are I<only> necessary in some very limited circumstances,
3094 mainly the case where you want to mount a mix of unrelated and/or
3095 read-only filesystems together.
3096
3097 For example, live CDs often contain a \"Russian doll\" nest of
3098 filesystems, an ISO outer layer, with a squashfs image inside, with
3099 an ext2/3 image inside that.  You can unpack this as follows
3100 in guestfish:
3101
3102  add-ro Fedora-11-i686-Live.iso
3103  run
3104  mkmountpoint /cd
3105  mkmountpoint /squash
3106  mkmountpoint /ext3
3107  mount /dev/sda /cd
3108  mount-loop /cd/LiveOS/squashfs.img /squash
3109  mount-loop /squash/LiveOS/ext3fs.img /ext3
3110
3111 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3112
3113   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3114    [],
3115    "remove a mountpoint",
3116    "\
3117 This calls removes a mountpoint that was previously created
3118 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3119 for full details.");
3120
3121   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3122    [InitISOFS, Always, TestOutputBuffer (
3123       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3124    "read a file",
3125    "\
3126 This calls returns the contents of the file C<path> as a
3127 buffer.
3128
3129 Unlike C<guestfs_cat>, this function can correctly
3130 handle files that contain embedded ASCII NUL characters.
3131 However unlike C<guestfs_download>, this function is limited
3132 in the total size of file that can be handled.");
3133
3134   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3135    [InitISOFS, Always, TestOutputList (
3136       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3137     InitISOFS, Always, TestOutputList (
3138       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3139    "return lines matching a pattern",
3140    "\
3141 This calls the external C<grep> program and returns the
3142 matching lines.");
3143
3144   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3145    [InitISOFS, Always, TestOutputList (
3146       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3147    "return lines matching a pattern",
3148    "\
3149 This calls the external C<egrep> program and returns the
3150 matching lines.");
3151
3152   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3153    [InitISOFS, Always, TestOutputList (
3154       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3155    "return lines matching a pattern",
3156    "\
3157 This calls the external C<fgrep> program and returns the
3158 matching lines.");
3159
3160   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3161    [InitISOFS, Always, TestOutputList (
3162       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3163    "return lines matching a pattern",
3164    "\
3165 This calls the external C<grep -i> program and returns the
3166 matching lines.");
3167
3168   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3169    [InitISOFS, Always, TestOutputList (
3170       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3171    "return lines matching a pattern",
3172    "\
3173 This calls the external C<egrep -i> program and returns the
3174 matching lines.");
3175
3176   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3177    [InitISOFS, Always, TestOutputList (
3178       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3179    "return lines matching a pattern",
3180    "\
3181 This calls the external C<fgrep -i> program and returns the
3182 matching lines.");
3183
3184   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3185    [InitISOFS, Always, TestOutputList (
3186       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3187    "return lines matching a pattern",
3188    "\
3189 This calls the external C<zgrep> program and returns the
3190 matching lines.");
3191
3192   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3193    [InitISOFS, Always, TestOutputList (
3194       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3195    "return lines matching a pattern",
3196    "\
3197 This calls the external C<zegrep> program and returns the
3198 matching lines.");
3199
3200   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3201    [InitISOFS, Always, TestOutputList (
3202       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3203    "return lines matching a pattern",
3204    "\
3205 This calls the external C<zfgrep> program and returns the
3206 matching lines.");
3207
3208   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3209    [InitISOFS, Always, TestOutputList (
3210       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3211    "return lines matching a pattern",
3212    "\
3213 This calls the external C<zgrep -i> program and returns the
3214 matching lines.");
3215
3216   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3217    [InitISOFS, Always, TestOutputList (
3218       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3219    "return lines matching a pattern",
3220    "\
3221 This calls the external C<zegrep -i> program and returns the
3222 matching lines.");
3223
3224   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3225    [InitISOFS, Always, TestOutputList (
3226       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3227    "return lines matching a pattern",
3228    "\
3229 This calls the external C<zfgrep -i> program and returns the
3230 matching lines.");
3231
3232   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3233    [InitISOFS, Always, TestOutput (
3234       [["realpath"; "/../directory"]], "/directory")],
3235    "canonicalized absolute pathname",
3236    "\
3237 Return the canonicalized absolute pathname of C<path>.  The
3238 returned path has no C<.>, C<..> or symbolic link path elements.");
3239
3240   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3241    [InitBasicFS, Always, TestOutputStruct (
3242       [["touch"; "/a"];
3243        ["ln"; "/a"; "/b"];
3244        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3245    "create a hard link",
3246    "\
3247 This command creates a hard link using the C<ln> command.");
3248
3249   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3250    [InitBasicFS, Always, TestOutputStruct (
3251       [["touch"; "/a"];
3252        ["touch"; "/b"];
3253        ["ln_f"; "/a"; "/b"];
3254        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3255    "create a hard link",
3256    "\
3257 This command creates a hard link using the C<ln -f> command.
3258 The C<-f> option removes the link (C<linkname>) if it exists already.");
3259
3260   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3261    [InitBasicFS, Always, TestOutputStruct (
3262       [["touch"; "/a"];
3263        ["ln_s"; "a"; "/b"];
3264        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3265    "create a symbolic link",
3266    "\
3267 This command creates a symbolic link using the C<ln -s> command.");
3268
3269   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3270    [InitBasicFS, Always, TestOutput (
3271       [["mkdir_p"; "/a/b"];
3272        ["touch"; "/a/b/c"];
3273        ["ln_sf"; "../d"; "/a/b/c"];
3274        ["readlink"; "/a/b/c"]], "../d")],
3275    "create a symbolic link",
3276    "\
3277 This command creates a symbolic link using the C<ln -sf> command,
3278 The C<-f> option removes the link (C<linkname>) if it exists already.");
3279
3280   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3281    [] (* XXX tested above *),
3282    "read the target of a symbolic link",
3283    "\
3284 This command reads the target of a symbolic link.");
3285
3286   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["fallocate"; "/a"; "1000000"];
3289        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3290    "preallocate a file in the guest filesystem",
3291    "\
3292 This command preallocates a file (containing zero bytes) named
3293 C<path> of size C<len> bytes.  If the file exists already, it
3294 is overwritten.
3295
3296 Do not confuse this with the guestfish-specific
3297 C<alloc> command which allocates a file in the host and
3298 attaches it as a device.");
3299
3300   ("swapon_device", (RErr, [Device "device"]), 170, [],
3301    [InitPartition, Always, TestRun (
3302       [["mkswap"; "/dev/sda1"];
3303        ["swapon_device"; "/dev/sda1"];
3304        ["swapoff_device"; "/dev/sda1"]])],
3305    "enable swap on device",
3306    "\
3307 This command enables the libguestfs appliance to use the
3308 swap device or partition named C<device>.  The increased
3309 memory is made available for all commands, for example
3310 those run using C<guestfs_command> or C<guestfs_sh>.
3311
3312 Note that you should not swap to existing guest swap
3313 partitions unless you know what you are doing.  They may
3314 contain hibernation information, or other information that
3315 the guest doesn't want you to trash.  You also risk leaking
3316 information about the host to the guest this way.  Instead,
3317 attach a new host device to the guest and swap on that.");
3318
3319   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3320    [], (* XXX tested by swapon_device *)
3321    "disable swap on device",
3322    "\
3323 This command disables the libguestfs appliance swap
3324 device or partition named C<device>.
3325 See C<guestfs_swapon_device>.");
3326
3327   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3328    [InitBasicFS, Always, TestRun (
3329       [["fallocate"; "/swap"; "8388608"];
3330        ["mkswap_file"; "/swap"];
3331        ["swapon_file"; "/swap"];
3332        ["swapoff_file"; "/swap"]])],
3333    "enable swap on file",
3334    "\
3335 This command enables swap to a file.
3336 See C<guestfs_swapon_device> for other notes.");
3337
3338   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3339    [], (* XXX tested by swapon_file *)
3340    "disable swap on file",
3341    "\
3342 This command disables the libguestfs appliance swap on file.");
3343
3344   ("swapon_label", (RErr, [String "label"]), 174, [],
3345    [InitEmpty, Always, TestRun (
3346       [["sfdiskM"; "/dev/sdb"; ","];
3347        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3348        ["swapon_label"; "swapit"];
3349        ["swapoff_label"; "swapit"];
3350        ["zero"; "/dev/sdb"];
3351        ["blockdev_rereadpt"; "/dev/sdb"]])],
3352    "enable swap on labeled swap partition",
3353    "\
3354 This command enables swap to a labeled swap partition.
3355 See C<guestfs_swapon_device> for other notes.");
3356
3357   ("swapoff_label", (RErr, [String "label"]), 175, [],
3358    [], (* XXX tested by swapon_label *)
3359    "disable swap on labeled swap partition",
3360    "\
3361 This command disables the libguestfs appliance swap on
3362 labeled swap partition.");
3363
3364   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3365    (let uuid = uuidgen () in
3366     [InitEmpty, Always, TestRun (
3367        [["mkswap_U"; uuid; "/dev/sdb"];
3368         ["swapon_uuid"; uuid];
3369         ["swapoff_uuid"; uuid]])]),
3370    "enable swap on swap partition by UUID",
3371    "\
3372 This command enables swap to a swap partition with the given UUID.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3376    [], (* XXX tested by swapon_uuid *)
3377    "disable swap on swap partition by UUID",
3378    "\
3379 This command disables the libguestfs appliance swap partition
3380 with the given UUID.");
3381
3382   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3383    [InitBasicFS, Always, TestRun (
3384       [["fallocate"; "/swap"; "8388608"];
3385        ["mkswap_file"; "/swap"]])],
3386    "create a swap file",
3387    "\
3388 Create a swap file.
3389
3390 This command just writes a swap file signature to an existing
3391 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3392
3393   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3394    [InitISOFS, Always, TestRun (
3395       [["inotify_init"; "0"]])],
3396    "create an inotify handle",
3397    "\
3398 This command creates a new inotify handle.
3399 The inotify subsystem can be used to notify events which happen to
3400 objects in the guest filesystem.
3401
3402 C<maxevents> is the maximum number of events which will be
3403 queued up between calls to C<guestfs_inotify_read> or
3404 C<guestfs_inotify_files>.
3405 If this is passed as C<0>, then the kernel (or previously set)
3406 default is used.  For Linux 2.6.29 the default was 16384 events.
3407 Beyond this limit, the kernel throws away events, but records
3408 the fact that it threw them away by setting a flag
3409 C<IN_Q_OVERFLOW> in the returned structure list (see
3410 C<guestfs_inotify_read>).
3411
3412 Before any events are generated, you have to add some
3413 watches to the internal watch list.  See:
3414 C<guestfs_inotify_add_watch>,
3415 C<guestfs_inotify_rm_watch> and
3416 C<guestfs_inotify_watch_all>.
3417
3418 Queued up events should be read periodically by calling
3419 C<guestfs_inotify_read>
3420 (or C<guestfs_inotify_files> which is just a helpful
3421 wrapper around C<guestfs_inotify_read>).  If you don't
3422 read the events out often enough then you risk the internal
3423 queue overflowing.
3424
3425 The handle should be closed after use by calling
3426 C<guestfs_inotify_close>.  This also removes any
3427 watches automatically.
3428
3429 See also L<inotify(7)> for an overview of the inotify interface
3430 as exposed by the Linux kernel, which is roughly what we expose
3431 via libguestfs.  Note that there is one global inotify handle
3432 per libguestfs instance.");
3433
3434   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3435    [InitBasicFS, Always, TestOutputList (
3436       [["inotify_init"; "0"];
3437        ["inotify_add_watch"; "/"; "1073741823"];
3438        ["touch"; "/a"];
3439        ["touch"; "/b"];
3440        ["inotify_files"]], ["a"; "b"])],
3441    "add an inotify watch",
3442    "\
3443 Watch C<path> for the events listed in C<mask>.
3444
3445 Note that if C<path> is a directory then events within that
3446 directory are watched, but this does I<not> happen recursively
3447 (in subdirectories).
3448
3449 Note for non-C or non-Linux callers: the inotify events are
3450 defined by the Linux kernel ABI and are listed in
3451 C</usr/include/sys/inotify.h>.");
3452
3453   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3454    [],
3455    "remove an inotify watch",
3456    "\
3457 Remove a previously defined inotify watch.
3458 See C<guestfs_inotify_add_watch>.");
3459
3460   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3461    [],
3462    "return list of inotify events",
3463    "\
3464 Return the complete queue of events that have happened
3465 since the previous read call.
3466
3467 If no events have happened, this returns an empty list.
3468
3469 I<Note>: In order to make sure that all events have been
3470 read, you must call this function repeatedly until it
3471 returns an empty list.  The reason is that the call will
3472 read events up to the maximum appliance-to-host message
3473 size and leave remaining events in the queue.");
3474
3475   ("inotify_files", (RStringList "paths", []), 183, [],
3476    [],
3477    "return list of watched files that had events",
3478    "\
3479 This function is a helpful wrapper around C<guestfs_inotify_read>
3480 which just returns a list of pathnames of objects that were
3481 touched.  The returned pathnames are sorted and deduplicated.");
3482
3483   ("inotify_close", (RErr, []), 184, [],
3484    [],
3485    "close the inotify handle",
3486    "\
3487 This closes the inotify handle which was previously
3488 opened by inotify_init.  It removes all watches, throws
3489 away any pending events, and deallocates all resources.");
3490
3491   ("setcon", (RErr, [String "context"]), 185, [],
3492    [],
3493    "set SELinux security context",
3494    "\
3495 This sets the SELinux security context of the daemon
3496 to the string C<context>.
3497
3498 See the documentation about SELINUX in L<guestfs(3)>.");
3499
3500   ("getcon", (RString "context", []), 186, [],
3501    [],
3502    "get SELinux security context",
3503    "\
3504 This gets the SELinux security context of the daemon.
3505
3506 See the documentation about SELINUX in L<guestfs(3)>,
3507 and C<guestfs_setcon>");
3508
3509   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3510    [InitEmpty, Always, TestOutput (
3511       [["sfdiskM"; "/dev/sda"; ","];
3512        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3513        ["mount"; "/dev/sda1"; "/"];
3514        ["write_file"; "/new"; "new file contents"; "0"];
3515        ["cat"; "/new"]], "new file contents")],
3516    "make a filesystem with block size",
3517    "\
3518 This call is similar to C<guestfs_mkfs>, but it allows you to
3519 control the block size of the resulting filesystem.  Supported
3520 block sizes depend on the filesystem type, but typically they
3521 are C<1024>, C<2048> or C<4096> only.");
3522
3523   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3524    [InitEmpty, Always, TestOutput (
3525       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3526        ["mke2journal"; "4096"; "/dev/sda1"];
3527        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3528        ["mount"; "/dev/sda2"; "/"];
3529        ["write_file"; "/new"; "new file contents"; "0"];
3530        ["cat"; "/new"]], "new file contents")],
3531    "make ext2/3/4 external journal",
3532    "\
3533 This creates an ext2 external journal on C<device>.  It is equivalent
3534 to the command:
3535
3536  mke2fs -O journal_dev -b blocksize device");
3537
3538   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3539    [InitEmpty, Always, TestOutput (
3540       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3541        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3542        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3543        ["mount"; "/dev/sda2"; "/"];
3544        ["write_file"; "/new"; "new file contents"; "0"];
3545        ["cat"; "/new"]], "new file contents")],
3546    "make ext2/3/4 external journal with label",
3547    "\
3548 This creates an ext2 external journal on C<device> with label C<label>.");
3549
3550   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3551    (let uuid = uuidgen () in
3552     [InitEmpty, Always, TestOutput (
3553        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3554         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3555         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3556         ["mount"; "/dev/sda2"; "/"];
3557         ["write_file"; "/new"; "new file contents"; "0"];
3558         ["cat"; "/new"]], "new file contents")]),
3559    "make ext2/3/4 external journal with UUID",
3560    "\
3561 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3562
3563   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3564    [],
3565    "make ext2/3/4 filesystem with external journal",
3566    "\
3567 This creates an ext2/3/4 filesystem on C<device> with
3568 an external journal on C<journal>.  It is equivalent
3569 to the command:
3570
3571  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3572
3573 See also C<guestfs_mke2journal>.");
3574
3575   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3576    [],
3577    "make ext2/3/4 filesystem with external journal",
3578    "\
3579 This creates an ext2/3/4 filesystem on C<device> with
3580 an external journal on the journal labeled C<label>.
3581
3582 See also C<guestfs_mke2journal_L>.");
3583
3584   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3585    [],
3586    "make ext2/3/4 filesystem with external journal",
3587    "\
3588 This creates an ext2/3/4 filesystem on C<device> with
3589 an external journal on the journal with UUID C<uuid>.
3590
3591 See also C<guestfs_mke2journal_U>.");
3592
3593   ("modprobe", (RErr, [String "modulename"]), 194, [],
3594    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3595    "load a kernel module",
3596    "\
3597 This loads a kernel module in the appliance.
3598
3599 The kernel module must have been whitelisted when libguestfs
3600 was built (see C<appliance/kmod.whitelist.in> in the source).");
3601
3602   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3603    [InitNone, Always, TestOutput (
3604      [["echo_daemon"; "This is a test"]], "This is a test"
3605    )],
3606    "echo arguments back to the client",
3607    "\
3608 This command concatenate the list of C<words> passed with single spaces between
3609 them and returns the resulting string.
3610
3611 You can use this command to test the connection through to the daemon.
3612
3613 See also C<guestfs_ping_daemon>.");
3614
3615   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3616    [], (* There is a regression test for this. *)
3617    "find all files and directories, returning NUL-separated list",
3618    "\
3619 This command lists out all files and directories, recursively,
3620 starting at C<directory>, placing the resulting list in the
3621 external file called C<files>.
3622
3623 This command works the same way as C<guestfs_find> with the
3624 following exceptions:
3625
3626 =over 4
3627
3628 =item *
3629
3630 The resulting list is written to an external file.
3631
3632 =item *
3633
3634 Items (filenames) in the result are separated
3635 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3636
3637 =item *
3638
3639 This command is not limited in the number of names that it
3640 can return.
3641
3642 =item *
3643
3644 The result list is not sorted.
3645
3646 =back");
3647
3648   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3649    [InitISOFS, Always, TestOutput (
3650       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3651     InitISOFS, Always, TestOutput (
3652       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3653     InitISOFS, Always, TestOutput (
3654       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3655     InitISOFS, Always, TestLastFail (
3656       [["case_sensitive_path"; "/Known-1/"]]);
3657     InitBasicFS, Always, TestOutput (
3658       [["mkdir"; "/a"];
3659        ["mkdir"; "/a/bbb"];
3660        ["touch"; "/a/bbb/c"];
3661        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3662     InitBasicFS, Always, TestOutput (
3663       [["mkdir"; "/a"];
3664        ["mkdir"; "/a/bbb"];
3665        ["touch"; "/a/bbb/c"];
3666        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3667     InitBasicFS, Always, TestLastFail (
3668       [["mkdir"; "/a"];
3669        ["mkdir"; "/a/bbb"];
3670        ["touch"; "/a/bbb/c"];
3671        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3672    "return true path on case-insensitive filesystem",
3673    "\
3674 This can be used to resolve case insensitive paths on
3675 a filesystem which is case sensitive.  The use case is
3676 to resolve paths which you have read from Windows configuration
3677 files or the Windows Registry, to the true path.
3678
3679 The command handles a peculiarity of the Linux ntfs-3g
3680 filesystem driver (and probably others), which is that although
3681 the underlying filesystem is case-insensitive, the driver
3682 exports the filesystem to Linux as case-sensitive.
3683
3684 One consequence of this is that special directories such
3685 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3686 (or other things) depending on the precise details of how
3687 they were created.  In Windows itself this would not be
3688 a problem.
3689
3690 Bug or feature?  You decide:
3691 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3692
3693 This function resolves the true case of each element in the
3694 path and returns the case-sensitive path.
3695
3696 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3697 might return C<\"/WINDOWS/system32\"> (the exact return value
3698 would depend on details of how the directories were originally
3699 created under Windows).
3700
3701 I<Note>:
3702 This function does not handle drive names, backslashes etc.
3703
3704 See also C<guestfs_realpath>.");
3705
3706   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3707    [InitBasicFS, Always, TestOutput (
3708       [["vfs_type"; "/dev/sda1"]], "ext2")],
3709    "get the Linux VFS type corresponding to a mounted device",
3710    "\
3711 This command gets the block device type corresponding to
3712 a mounted device called C<device>.
3713
3714 Usually the result is the name of the Linux VFS module that
3715 is used to mount this device (probably determined automatically
3716 if you used the C<guestfs_mount> call).");
3717
3718 ]
3719
3720 let all_functions = non_daemon_functions @ daemon_functions
3721
3722 (* In some places we want the functions to be displayed sorted
3723  * alphabetically, so this is useful:
3724  *)
3725 let all_functions_sorted =
3726   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3727                compare n1 n2) all_functions
3728
3729 (* Field types for structures. *)
3730 type field =
3731   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3732   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3733   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3734   | FUInt32
3735   | FInt32
3736   | FUInt64
3737   | FInt64
3738   | FBytes                      (* Any int measure that counts bytes. *)
3739   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3740   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3741
3742 (* Because we generate extra parsing code for LVM command line tools,
3743  * we have to pull out the LVM columns separately here.
3744  *)
3745 let lvm_pv_cols = [
3746   "pv_name", FString;
3747   "pv_uuid", FUUID;
3748   "pv_fmt", FString;
3749   "pv_size", FBytes;
3750   "dev_size", FBytes;
3751   "pv_free", FBytes;
3752   "pv_used", FBytes;
3753   "pv_attr", FString (* XXX *);
3754   "pv_pe_count", FInt64;
3755   "pv_pe_alloc_count", FInt64;
3756   "pv_tags", FString;
3757   "pe_start", FBytes;
3758   "pv_mda_count", FInt64;
3759   "pv_mda_free", FBytes;
3760   (* Not in Fedora 10:
3761      "pv_mda_size", FBytes;
3762   *)
3763 ]
3764 let lvm_vg_cols = [
3765   "vg_name", FString;
3766   "vg_uuid", FUUID;
3767   "vg_fmt", FString;
3768   "vg_attr", FString (* XXX *);
3769   "vg_size", FBytes;
3770   "vg_free", FBytes;
3771   "vg_sysid", FString;
3772   "vg_extent_size", FBytes;
3773   "vg_extent_count", FInt64;
3774   "vg_free_count", FInt64;
3775   "max_lv", FInt64;
3776   "max_pv", FInt64;
3777   "pv_count", FInt64;
3778   "lv_count", FInt64;
3779   "snap_count", FInt64;
3780   "vg_seqno", FInt64;
3781   "vg_tags", FString;
3782   "vg_mda_count", FInt64;
3783   "vg_mda_free", FBytes;
3784   (* Not in Fedora 10:
3785      "vg_mda_size", FBytes;
3786   *)
3787 ]
3788 let lvm_lv_cols = [
3789   "lv_name", FString;
3790   "lv_uuid", FUUID;
3791   "lv_attr", FString (* XXX *);
3792   "lv_major", FInt64;
3793   "lv_minor", FInt64;
3794   "lv_kernel_major", FInt64;
3795   "lv_kernel_minor", FInt64;
3796   "lv_size", FBytes;
3797   "seg_count", FInt64;
3798   "origin", FString;
3799   "snap_percent", FOptPercent;
3800   "copy_percent", FOptPercent;
3801   "move_pv", FString;
3802   "lv_tags", FString;
3803   "mirror_log", FString;
3804   "modules", FString;
3805 ]
3806
3807 (* Names and fields in all structures (in RStruct and RStructList)
3808  * that we support.
3809  *)
3810 let structs = [
3811   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3812    * not use this struct in any new code.
3813    *)
3814   "int_bool", [
3815     "i", FInt32;                (* for historical compatibility *)
3816     "b", FInt32;                (* for historical compatibility *)
3817   ];
3818
3819   (* LVM PVs, VGs, LVs. *)
3820   "lvm_pv", lvm_pv_cols;
3821   "lvm_vg", lvm_vg_cols;
3822   "lvm_lv", lvm_lv_cols;
3823
3824   (* Column names and types from stat structures.
3825    * NB. Can't use things like 'st_atime' because glibc header files
3826    * define some of these as macros.  Ugh.
3827    *)
3828   "stat", [
3829     "dev", FInt64;
3830     "ino", FInt64;
3831     "mode", FInt64;
3832     "nlink", FInt64;
3833     "uid", FInt64;
3834     "gid", FInt64;
3835     "rdev", FInt64;
3836     "size", FInt64;
3837     "blksize", FInt64;
3838     "blocks", FInt64;
3839     "atime", FInt64;
3840     "mtime", FInt64;
3841     "ctime", FInt64;
3842   ];
3843   "statvfs", [
3844     "bsize", FInt64;
3845     "frsize", FInt64;
3846     "blocks", FInt64;
3847     "bfree", FInt64;
3848     "bavail", FInt64;
3849     "files", FInt64;
3850     "ffree", FInt64;
3851     "favail", FInt64;
3852     "fsid", FInt64;
3853     "flag", FInt64;
3854     "namemax", FInt64;
3855   ];
3856
3857   (* Column names in dirent structure. *)
3858   "dirent", [
3859     "ino", FInt64;
3860     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3861     "ftyp", FChar;
3862     "name", FString;
3863   ];
3864
3865   (* Version numbers. *)
3866   "version", [
3867     "major", FInt64;
3868     "minor", FInt64;
3869     "release", FInt64;
3870     "extra", FString;
3871   ];
3872
3873   (* Extended attribute. *)
3874   "xattr", [
3875     "attrname", FString;
3876     "attrval", FBuffer;
3877   ];
3878
3879   (* Inotify events. *)
3880   "inotify_event", [
3881     "in_wd", FInt64;
3882     "in_mask", FUInt32;
3883     "in_cookie", FUInt32;
3884     "in_name", FString;
3885   ];
3886 ] (* end of structs *)
3887
3888 (* Ugh, Java has to be different ..
3889  * These names are also used by the Haskell bindings.
3890  *)
3891 let java_structs = [
3892   "int_bool", "IntBool";
3893   "lvm_pv", "PV";
3894   "lvm_vg", "VG";
3895   "lvm_lv", "LV";
3896   "stat", "Stat";
3897   "statvfs", "StatVFS";
3898   "dirent", "Dirent";
3899   "version", "Version";
3900   "xattr", "XAttr";
3901   "inotify_event", "INotifyEvent";
3902 ]
3903
3904 (* What structs are actually returned. *)
3905 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3906
3907 (* Returns a list of RStruct/RStructList structs that are returned
3908  * by any function.  Each element of returned list is a pair:
3909  *
3910  * (structname, RStructOnly)
3911  *    == there exists function which returns RStruct (_, structname)
3912  * (structname, RStructListOnly)
3913  *    == there exists function which returns RStructList (_, structname)
3914  * (structname, RStructAndList)
3915  *    == there are functions returning both RStruct (_, structname)
3916  *                                      and RStructList (_, structname)
3917  *)
3918 let rstructs_used_by functions =
3919   (* ||| is a "logical OR" for rstructs_used_t *)
3920   let (|||) a b =
3921     match a, b with
3922     | RStructAndList, _
3923     | _, RStructAndList -> RStructAndList
3924     | RStructOnly, RStructListOnly
3925     | RStructListOnly, RStructOnly -> RStructAndList
3926     | RStructOnly, RStructOnly -> RStructOnly
3927     | RStructListOnly, RStructListOnly -> RStructListOnly
3928   in
3929
3930   let h = Hashtbl.create 13 in
3931
3932   (* if elem->oldv exists, update entry using ||| operator,
3933    * else just add elem->newv to the hash
3934    *)
3935   let update elem newv =
3936     try  let oldv = Hashtbl.find h elem in
3937          Hashtbl.replace h elem (newv ||| oldv)
3938     with Not_found -> Hashtbl.add h elem newv
3939   in
3940
3941   List.iter (
3942     fun (_, style, _, _, _, _, _) ->
3943       match fst style with
3944       | RStruct (_, structname) -> update structname RStructOnly
3945       | RStructList (_, structname) -> update structname RStructListOnly
3946       | _ -> ()
3947   ) functions;
3948
3949   (* return key->values as a list of (key,value) *)
3950   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3951
3952 (* Used for testing language bindings. *)
3953 type callt =
3954   | CallString of string
3955   | CallOptString of string option
3956   | CallStringList of string list
3957   | CallInt of int
3958   | CallBool of bool
3959
3960 (* Used to memoize the result of pod2text. *)
3961 let pod2text_memo_filename = "src/.pod2text.data"
3962 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3963   try
3964     let chan = open_in pod2text_memo_filename in
3965     let v = input_value chan in
3966     close_in chan;
3967     v
3968   with
3969     _ -> Hashtbl.create 13
3970 let pod2text_memo_updated () =
3971   let chan = open_out pod2text_memo_filename in
3972   output_value chan pod2text_memo;
3973   close_out chan
3974
3975 (* Useful functions.
3976  * Note we don't want to use any external OCaml libraries which
3977  * makes this a bit harder than it should be.
3978  *)
3979 let failwithf fs = ksprintf failwith fs
3980
3981 let replace_char s c1 c2 =
3982   let s2 = String.copy s in
3983   let r = ref false in
3984   for i = 0 to String.length s2 - 1 do
3985     if String.unsafe_get s2 i = c1 then (
3986       String.unsafe_set s2 i c2;
3987       r := true
3988     )
3989   done;
3990   if not !r then s else s2
3991
3992 let isspace c =
3993   c = ' '
3994   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3995
3996 let triml ?(test = isspace) str =
3997   let i = ref 0 in
3998   let n = ref (String.length str) in
3999   while !n > 0 && test str.[!i]; do
4000     decr n;
4001     incr i
4002   done;
4003   if !i = 0 then str
4004   else String.sub str !i !n
4005
4006 let trimr ?(test = isspace) str =
4007   let n = ref (String.length str) in
4008   while !n > 0 && test str.[!n-1]; do
4009     decr n
4010   done;
4011   if !n = String.length str then str
4012   else String.sub str 0 !n
4013
4014 let trim ?(test = isspace) str =
4015   trimr ~test (triml ~test str)
4016
4017 let rec find s sub =
4018   let len = String.length s in
4019   let sublen = String.length sub in
4020   let rec loop i =
4021     if i <= len-sublen then (
4022       let rec loop2 j =
4023         if j < sublen then (
4024           if s.[i+j] = sub.[j] then loop2 (j+1)
4025           else -1
4026         ) else
4027           i (* found *)
4028       in
4029       let r = loop2 0 in
4030       if r = -1 then loop (i+1) else r
4031     ) else
4032       -1 (* not found *)
4033   in
4034   loop 0
4035
4036 let rec replace_str s s1 s2 =
4037   let len = String.length s in
4038   let sublen = String.length s1 in
4039   let i = find s s1 in
4040   if i = -1 then s
4041   else (
4042     let s' = String.sub s 0 i in
4043     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4044     s' ^ s2 ^ replace_str s'' s1 s2
4045   )
4046
4047 let rec string_split sep str =
4048   let len = String.length str in
4049   let seplen = String.length sep in
4050   let i = find str sep in
4051   if i = -1 then [str]
4052   else (
4053     let s' = String.sub str 0 i in
4054     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4055     s' :: string_split sep s''
4056   )
4057
4058 let files_equal n1 n2 =
4059   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4060   match Sys.command cmd with
4061   | 0 -> true
4062   | 1 -> false
4063   | i -> failwithf "%s: failed with error code %d" cmd i
4064
4065 let rec filter_map f = function
4066   | [] -> []
4067   | x :: xs ->
4068       match f x with
4069       | Some y -> y :: filter_map f xs
4070       | None -> filter_map f xs
4071
4072 let rec find_map f = function
4073   | [] -> raise Not_found
4074   | x :: xs ->
4075       match f x with
4076       | Some y -> y
4077       | None -> find_map f xs
4078
4079 let iteri f xs =
4080   let rec loop i = function
4081     | [] -> ()
4082     | x :: xs -> f i x; loop (i+1) xs
4083   in
4084   loop 0 xs
4085
4086 let mapi f xs =
4087   let rec loop i = function
4088     | [] -> []
4089     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4090   in
4091   loop 0 xs
4092
4093 let name_of_argt = function
4094   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4095   | StringList n | DeviceList n | Bool n | Int n
4096   | FileIn n | FileOut n -> n
4097
4098 let java_name_of_struct typ =
4099   try List.assoc typ java_structs
4100   with Not_found ->
4101     failwithf
4102       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4103
4104 let cols_of_struct typ =
4105   try List.assoc typ structs
4106   with Not_found ->
4107     failwithf "cols_of_struct: unknown struct %s" typ
4108
4109 let seq_of_test = function
4110   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4111   | TestOutputListOfDevices (s, _)
4112   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4113   | TestOutputTrue s | TestOutputFalse s
4114   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4115   | TestOutputStruct (s, _)
4116   | TestLastFail s -> s
4117
4118 (* Handling for function flags. *)
4119 let protocol_limit_warning =
4120   "Because of the message protocol, there is a transfer limit
4121 of somewhere between 2MB and 4MB.  To transfer large files you should use
4122 FTP."
4123
4124 let danger_will_robinson =
4125   "B<This command is dangerous.  Without careful use you
4126 can easily destroy all your data>."
4127
4128 let deprecation_notice flags =
4129   try
4130     let alt =
4131       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4132     let txt =
4133       sprintf "This function is deprecated.
4134 In new code, use the C<%s> call instead.
4135
4136 Deprecated functions will not be removed from the API, but the
4137 fact that they are deprecated indicates that there are problems
4138 with correct use of these functions." alt in
4139     Some txt
4140   with
4141     Not_found -> None
4142
4143 (* Check function names etc. for consistency. *)
4144 let check_functions () =
4145   let contains_uppercase str =
4146     let len = String.length str in
4147     let rec loop i =
4148       if i >= len then false
4149       else (
4150         let c = str.[i] in
4151         if c >= 'A' && c <= 'Z' then true
4152         else loop (i+1)
4153       )
4154     in
4155     loop 0
4156   in
4157
4158   (* Check function names. *)
4159   List.iter (
4160     fun (name, _, _, _, _, _, _) ->
4161       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4162         failwithf "function name %s does not need 'guestfs' prefix" name;
4163       if name = "" then
4164         failwithf "function name is empty";
4165       if name.[0] < 'a' || name.[0] > 'z' then
4166         failwithf "function name %s must start with lowercase a-z" name;
4167       if String.contains name '-' then
4168         failwithf "function name %s should not contain '-', use '_' instead."
4169           name
4170   ) all_functions;
4171
4172   (* Check function parameter/return names. *)
4173   List.iter (
4174     fun (name, style, _, _, _, _, _) ->
4175       let check_arg_ret_name n =
4176         if contains_uppercase n then
4177           failwithf "%s param/ret %s should not contain uppercase chars"
4178             name n;
4179         if String.contains n '-' || String.contains n '_' then
4180           failwithf "%s param/ret %s should not contain '-' or '_'"
4181             name n;
4182         if n = "value" then
4183           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;
4184         if n = "int" || n = "char" || n = "short" || n = "long" then
4185           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4186         if n = "i" || n = "n" then
4187           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4188         if n = "argv" || n = "args" then
4189           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4190
4191         (* List Haskell, OCaml and C keywords here.
4192          * http://www.haskell.org/haskellwiki/Keywords
4193          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4194          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4195          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4196          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4197          * Omitting _-containing words, since they're handled above.
4198          * Omitting the OCaml reserved word, "val", is ok,
4199          * and saves us from renaming several parameters.
4200          *)
4201         let reserved = [
4202           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4203           "char"; "class"; "const"; "constraint"; "continue"; "data";
4204           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4205           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4206           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4207           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4208           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4209           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4210           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4211           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4212           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4213           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4214           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4215           "volatile"; "when"; "where"; "while";
4216           ] in
4217         if List.mem n reserved then
4218           failwithf "%s has param/ret using reserved word %s" name n;
4219       in
4220
4221       (match fst style with
4222        | RErr -> ()
4223        | RInt n | RInt64 n | RBool n
4224        | RConstString n | RConstOptString n | RString n
4225        | RStringList n | RStruct (n, _) | RStructList (n, _)
4226        | RHashtable n | RBufferOut n ->
4227            check_arg_ret_name n
4228       );
4229       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4230   ) all_functions;
4231
4232   (* Check short descriptions. *)
4233   List.iter (
4234     fun (name, _, _, _, _, shortdesc, _) ->
4235       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4236         failwithf "short description of %s should begin with lowercase." name;
4237       let c = shortdesc.[String.length shortdesc-1] in
4238       if c = '\n' || c = '.' then
4239         failwithf "short description of %s should not end with . or \\n." name
4240   ) all_functions;
4241
4242   (* Check long dscriptions. *)
4243   List.iter (
4244     fun (name, _, _, _, _, _, longdesc) ->
4245       if longdesc.[String.length longdesc-1] = '\n' then
4246         failwithf "long description of %s should not end with \\n." name
4247   ) all_functions;
4248
4249   (* Check proc_nrs. *)
4250   List.iter (
4251     fun (name, _, proc_nr, _, _, _, _) ->
4252       if proc_nr <= 0 then
4253         failwithf "daemon function %s should have proc_nr > 0" name
4254   ) daemon_functions;
4255
4256   List.iter (
4257     fun (name, _, proc_nr, _, _, _, _) ->
4258       if proc_nr <> -1 then
4259         failwithf "non-daemon function %s should have proc_nr -1" name
4260   ) non_daemon_functions;
4261
4262   let proc_nrs =
4263     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4264       daemon_functions in
4265   let proc_nrs =
4266     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4267   let rec loop = function
4268     | [] -> ()
4269     | [_] -> ()
4270     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4271         loop rest
4272     | (name1,nr1) :: (name2,nr2) :: _ ->
4273         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4274           name1 name2 nr1 nr2
4275   in
4276   loop proc_nrs;
4277
4278   (* Check tests. *)
4279   List.iter (
4280     function
4281       (* Ignore functions that have no tests.  We generate a
4282        * warning when the user does 'make check' instead.
4283        *)
4284     | name, _, _, _, [], _, _ -> ()
4285     | name, _, _, _, tests, _, _ ->
4286         let funcs =
4287           List.map (
4288             fun (_, _, test) ->
4289               match seq_of_test test with
4290               | [] ->
4291                   failwithf "%s has a test containing an empty sequence" name
4292               | cmds -> List.map List.hd cmds
4293           ) tests in
4294         let funcs = List.flatten funcs in
4295
4296         let tested = List.mem name funcs in
4297
4298         if not tested then
4299           failwithf "function %s has tests but does not test itself" name
4300   ) all_functions
4301
4302 (* 'pr' prints to the current output file. *)
4303 let chan = ref stdout
4304 let pr fs = ksprintf (output_string !chan) fs
4305
4306 (* Generate a header block in a number of standard styles. *)
4307 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4308 type license = GPLv2 | LGPLv2
4309
4310 let generate_header comment license =
4311   let c = match comment with
4312     | CStyle ->     pr "/* "; " *"
4313     | HashStyle ->  pr "# ";  "#"
4314     | OCamlStyle -> pr "(* "; " *"
4315     | HaskellStyle -> pr "{- "; "  " in
4316   pr "libguestfs generated file\n";
4317   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4318   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4319   pr "%s\n" c;
4320   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4321   pr "%s\n" c;
4322   (match license with
4323    | GPLv2 ->
4324        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4325        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4326        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4327        pr "%s (at your option) any later version.\n" c;
4328        pr "%s\n" c;
4329        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4330        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4331        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4332        pr "%s GNU General Public License for more details.\n" c;
4333        pr "%s\n" c;
4334        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4335        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4336        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4337
4338    | LGPLv2 ->
4339        pr "%s This library is free software; you can redistribute it and/or\n" c;
4340        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4341        pr "%s License as published by the Free Software Foundation; either\n" c;
4342        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4343        pr "%s\n" c;
4344        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4345        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4346        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4347        pr "%s Lesser General Public License for more details.\n" c;
4348        pr "%s\n" c;
4349        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4350        pr "%s License along with this library; if not, write to the Free Software\n" c;
4351        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4352   );
4353   (match comment with
4354    | CStyle -> pr " */\n"
4355    | HashStyle -> ()
4356    | OCamlStyle -> pr " *)\n"
4357    | HaskellStyle -> pr "-}\n"
4358   );
4359   pr "\n"
4360
4361 (* Start of main code generation functions below this line. *)
4362
4363 (* Generate the pod documentation for the C API. *)
4364 let rec generate_actions_pod () =
4365   List.iter (
4366     fun (shortname, style, _, flags, _, _, longdesc) ->
4367       if not (List.mem NotInDocs flags) then (
4368         let name = "guestfs_" ^ shortname in
4369         pr "=head2 %s\n\n" name;
4370         pr " ";
4371         generate_prototype ~extern:false ~handle:"handle" name style;
4372         pr "\n\n";
4373         pr "%s\n\n" longdesc;
4374         (match fst style with
4375          | RErr ->
4376              pr "This function returns 0 on success or -1 on error.\n\n"
4377          | RInt _ ->
4378              pr "On error this function returns -1.\n\n"
4379          | RInt64 _ ->
4380              pr "On error this function returns -1.\n\n"
4381          | RBool _ ->
4382              pr "This function returns a C truth value on success or -1 on error.\n\n"
4383          | RConstString _ ->
4384              pr "This function returns a string, or NULL on error.
4385 The string is owned by the guest handle and must I<not> be freed.\n\n"
4386          | RConstOptString _ ->
4387              pr "This function returns a string which may be NULL.
4388 There is way to return an error from this function.
4389 The string is owned by the guest handle and must I<not> be freed.\n\n"
4390          | RString _ ->
4391              pr "This function returns a string, or NULL on error.
4392 I<The caller must free the returned string after use>.\n\n"
4393          | RStringList _ ->
4394              pr "This function returns a NULL-terminated array of strings
4395 (like L<environ(3)>), or NULL if there was an error.
4396 I<The caller must free the strings and the array after use>.\n\n"
4397          | RStruct (_, typ) ->
4398              pr "This function returns a C<struct guestfs_%s *>,
4399 or NULL if there was an error.
4400 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4401          | RStructList (_, typ) ->
4402              pr "This function returns a C<struct guestfs_%s_list *>
4403 (see E<lt>guestfs-structs.hE<gt>),
4404 or NULL if there was an error.
4405 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4406          | RHashtable _ ->
4407              pr "This function returns a NULL-terminated array of
4408 strings, or NULL if there was an error.
4409 The array of strings will always have length C<2n+1>, where
4410 C<n> keys and values alternate, followed by the trailing NULL entry.
4411 I<The caller must free the strings and the array after use>.\n\n"
4412          | RBufferOut _ ->
4413              pr "This function returns a buffer, or NULL on error.
4414 The size of the returned buffer is written to C<*size_r>.
4415 I<The caller must free the returned buffer after use>.\n\n"
4416         );
4417         if List.mem ProtocolLimitWarning flags then
4418           pr "%s\n\n" protocol_limit_warning;
4419         if List.mem DangerWillRobinson flags then
4420           pr "%s\n\n" danger_will_robinson;
4421         match deprecation_notice flags with
4422         | None -> ()
4423         | Some txt -> pr "%s\n\n" txt
4424       )
4425   ) all_functions_sorted
4426
4427 and generate_structs_pod () =
4428   (* Structs documentation. *)
4429   List.iter (
4430     fun (typ, cols) ->
4431       pr "=head2 guestfs_%s\n" typ;
4432       pr "\n";
4433       pr " struct guestfs_%s {\n" typ;
4434       List.iter (
4435         function
4436         | name, FChar -> pr "   char %s;\n" name
4437         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4438         | name, FInt32 -> pr "   int32_t %s;\n" name
4439         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4440         | name, FInt64 -> pr "   int64_t %s;\n" name
4441         | name, FString -> pr "   char *%s;\n" name
4442         | name, FBuffer ->
4443             pr "   /* The next two fields describe a byte array. */\n";
4444             pr "   uint32_t %s_len;\n" name;
4445             pr "   char *%s;\n" name
4446         | name, FUUID ->
4447             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4448             pr "   char %s[32];\n" name
4449         | name, FOptPercent ->
4450             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4451             pr "   float %s;\n" name
4452       ) cols;
4453       pr " };\n";
4454       pr " \n";
4455       pr " struct guestfs_%s_list {\n" typ;
4456       pr "   uint32_t len; /* Number of elements in list. */\n";
4457       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4458       pr " };\n";
4459       pr " \n";
4460       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4461       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4462         typ typ;
4463       pr "\n"
4464   ) structs
4465
4466 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4467  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4468  *
4469  * We have to use an underscore instead of a dash because otherwise
4470  * rpcgen generates incorrect code.
4471  *
4472  * This header is NOT exported to clients, but see also generate_structs_h.
4473  *)
4474 and generate_xdr () =
4475   generate_header CStyle LGPLv2;
4476
4477   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4478   pr "typedef string str<>;\n";
4479   pr "\n";
4480
4481   (* Internal structures. *)
4482   List.iter (
4483     function
4484     | typ, cols ->
4485         pr "struct guestfs_int_%s {\n" typ;
4486         List.iter (function
4487                    | name, FChar -> pr "  char %s;\n" name
4488                    | name, FString -> pr "  string %s<>;\n" name
4489                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4490                    | name, FUUID -> pr "  opaque %s[32];\n" name
4491                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4492                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4493                    | name, FOptPercent -> pr "  float %s;\n" name
4494                   ) cols;
4495         pr "};\n";
4496         pr "\n";
4497         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4498         pr "\n";
4499   ) structs;
4500
4501   List.iter (
4502     fun (shortname, style, _, _, _, _, _) ->
4503       let name = "guestfs_" ^ shortname in
4504
4505       (match snd style with
4506        | [] -> ()
4507        | args ->
4508            pr "struct %s_args {\n" name;
4509            List.iter (
4510              function
4511              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4512              | OptString n -> pr "  str *%s;\n" n
4513              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4514              | Bool n -> pr "  bool %s;\n" n
4515              | Int n -> pr "  int %s;\n" n
4516              | FileIn _ | FileOut _ -> ()
4517            ) args;
4518            pr "};\n\n"
4519       );
4520       (match fst style with
4521        | RErr -> ()
4522        | RInt n ->
4523            pr "struct %s_ret {\n" name;
4524            pr "  int %s;\n" n;
4525            pr "};\n\n"
4526        | RInt64 n ->
4527            pr "struct %s_ret {\n" name;
4528            pr "  hyper %s;\n" n;
4529            pr "};\n\n"
4530        | RBool n ->
4531            pr "struct %s_ret {\n" name;
4532            pr "  bool %s;\n" n;
4533            pr "};\n\n"
4534        | RConstString _ | RConstOptString _ ->
4535            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4536        | RString n ->
4537            pr "struct %s_ret {\n" name;
4538            pr "  string %s<>;\n" n;
4539            pr "};\n\n"
4540        | RStringList n ->
4541            pr "struct %s_ret {\n" name;
4542            pr "  str %s<>;\n" n;
4543            pr "};\n\n"
4544        | RStruct (n, typ) ->
4545            pr "struct %s_ret {\n" name;
4546            pr "  guestfs_int_%s %s;\n" typ n;
4547            pr "};\n\n"
4548        | RStructList (n, typ) ->
4549            pr "struct %s_ret {\n" name;
4550            pr "  guestfs_int_%s_list %s;\n" typ n;
4551            pr "};\n\n"
4552        | RHashtable n ->
4553            pr "struct %s_ret {\n" name;
4554            pr "  str %s<>;\n" n;
4555            pr "};\n\n"
4556        | RBufferOut n ->
4557            pr "struct %s_ret {\n" name;
4558            pr "  opaque %s<>;\n" n;
4559            pr "};\n\n"
4560       );
4561   ) daemon_functions;
4562
4563   (* Table of procedure numbers. *)
4564   pr "enum guestfs_procedure {\n";
4565   List.iter (
4566     fun (shortname, _, proc_nr, _, _, _, _) ->
4567       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4568   ) daemon_functions;
4569   pr "  GUESTFS_PROC_NR_PROCS\n";
4570   pr "};\n";
4571   pr "\n";
4572
4573   (* Having to choose a maximum message size is annoying for several
4574    * reasons (it limits what we can do in the API), but it (a) makes
4575    * the protocol a lot simpler, and (b) provides a bound on the size
4576    * of the daemon which operates in limited memory space.  For large
4577    * file transfers you should use FTP.
4578    *)
4579   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4580   pr "\n";
4581
4582   (* Message header, etc. *)
4583   pr "\
4584 /* The communication protocol is now documented in the guestfs(3)
4585  * manpage.
4586  */
4587
4588 const GUESTFS_PROGRAM = 0x2000F5F5;
4589 const GUESTFS_PROTOCOL_VERSION = 1;
4590
4591 /* These constants must be larger than any possible message length. */
4592 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4593 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4594
4595 enum guestfs_message_direction {
4596   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4597   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4598 };
4599
4600 enum guestfs_message_status {
4601   GUESTFS_STATUS_OK = 0,
4602   GUESTFS_STATUS_ERROR = 1
4603 };
4604
4605 const GUESTFS_ERROR_LEN = 256;
4606
4607 struct guestfs_message_error {
4608   string error_message<GUESTFS_ERROR_LEN>;
4609 };
4610
4611 struct guestfs_message_header {
4612   unsigned prog;                     /* GUESTFS_PROGRAM */
4613   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4614   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4615   guestfs_message_direction direction;
4616   unsigned serial;                   /* message serial number */
4617   guestfs_message_status status;
4618 };
4619
4620 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4621
4622 struct guestfs_chunk {
4623   int cancel;                        /* if non-zero, transfer is cancelled */
4624   /* data size is 0 bytes if the transfer has finished successfully */
4625   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4626 };
4627 "
4628
4629 (* Generate the guestfs-structs.h file. *)
4630 and generate_structs_h () =
4631   generate_header CStyle LGPLv2;
4632
4633   (* This is a public exported header file containing various
4634    * structures.  The structures are carefully written to have
4635    * exactly the same in-memory format as the XDR structures that
4636    * we use on the wire to the daemon.  The reason for creating
4637    * copies of these structures here is just so we don't have to
4638    * export the whole of guestfs_protocol.h (which includes much
4639    * unrelated and XDR-dependent stuff that we don't want to be
4640    * public, or required by clients).
4641    *
4642    * To reiterate, we will pass these structures to and from the
4643    * client with a simple assignment or memcpy, so the format
4644    * must be identical to what rpcgen / the RFC defines.
4645    *)
4646
4647   (* Public structures. *)
4648   List.iter (
4649     fun (typ, cols) ->
4650       pr "struct guestfs_%s {\n" typ;
4651       List.iter (
4652         function
4653         | name, FChar -> pr "  char %s;\n" name
4654         | name, FString -> pr "  char *%s;\n" name
4655         | name, FBuffer ->
4656             pr "  uint32_t %s_len;\n" name;
4657             pr "  char *%s;\n" name
4658         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4659         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4660         | name, FInt32 -> pr "  int32_t %s;\n" name
4661         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4662         | name, FInt64 -> pr "  int64_t %s;\n" name
4663         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4664       ) cols;
4665       pr "};\n";
4666       pr "\n";
4667       pr "struct guestfs_%s_list {\n" typ;
4668       pr "  uint32_t len;\n";
4669       pr "  struct guestfs_%s *val;\n" typ;
4670       pr "};\n";
4671       pr "\n";
4672       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4673       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4674       pr "\n"
4675   ) structs
4676
4677 (* Generate the guestfs-actions.h file. *)
4678 and generate_actions_h () =
4679   generate_header CStyle LGPLv2;
4680   List.iter (
4681     fun (shortname, style, _, _, _, _, _) ->
4682       let name = "guestfs_" ^ shortname in
4683       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4684         name style
4685   ) all_functions
4686
4687 (* Generate the guestfs-internal-actions.h file. *)
4688 and generate_internal_actions_h () =
4689   generate_header CStyle LGPLv2;
4690   List.iter (
4691     fun (shortname, style, _, _, _, _, _) ->
4692       let name = "guestfs__" ^ shortname in
4693       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4694         name style
4695   ) non_daemon_functions
4696
4697 (* Generate the client-side dispatch stubs. *)
4698 and generate_client_actions () =
4699   generate_header CStyle LGPLv2;
4700
4701   pr "\
4702 #include <stdio.h>
4703 #include <stdlib.h>
4704
4705 #include \"guestfs.h\"
4706 #include \"guestfs-internal-actions.h\"
4707 #include \"guestfs_protocol.h\"
4708
4709 #define error guestfs_error
4710 //#define perrorf guestfs_perrorf
4711 //#define safe_malloc guestfs_safe_malloc
4712 #define safe_realloc guestfs_safe_realloc
4713 //#define safe_strdup guestfs_safe_strdup
4714 #define safe_memdup guestfs_safe_memdup
4715
4716 /* Check the return message from a call for validity. */
4717 static int
4718 check_reply_header (guestfs_h *g,
4719                     const struct guestfs_message_header *hdr,
4720                     unsigned int proc_nr, unsigned int serial)
4721 {
4722   if (hdr->prog != GUESTFS_PROGRAM) {
4723     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4724     return -1;
4725   }
4726   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4727     error (g, \"wrong protocol version (%%d/%%d)\",
4728            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4729     return -1;
4730   }
4731   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4732     error (g, \"unexpected message direction (%%d/%%d)\",
4733            hdr->direction, GUESTFS_DIRECTION_REPLY);
4734     return -1;
4735   }
4736   if (hdr->proc != proc_nr) {
4737     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4738     return -1;
4739   }
4740   if (hdr->serial != serial) {
4741     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4742     return -1;
4743   }
4744
4745   return 0;
4746 }
4747
4748 /* Check we are in the right state to run a high-level action. */
4749 static int
4750 check_state (guestfs_h *g, const char *caller)
4751 {
4752   if (!guestfs__is_ready (g)) {
4753     if (guestfs__is_config (g) || guestfs__is_launching (g))
4754       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4755         caller);
4756     else
4757       error (g, \"%%s called from the wrong state, %%d != READY\",
4758         caller, guestfs__get_state (g));
4759     return -1;
4760   }
4761   return 0;
4762 }
4763
4764 ";
4765
4766   (* Generate code to generate guestfish call traces. *)
4767   let trace_call shortname style =
4768     pr "  if (guestfs__get_trace (g)) {\n";
4769
4770     let needs_i =
4771       List.exists (function
4772                    | StringList _ | DeviceList _ -> true
4773                    | _ -> false) (snd style) in
4774     if needs_i then (
4775       pr "    int i;\n";
4776       pr "\n"
4777     );
4778
4779     pr "    printf (\"%s\");\n" shortname;
4780     List.iter (
4781       function
4782       | String n                        (* strings *)
4783       | Device n
4784       | Pathname n
4785       | Dev_or_Path n
4786       | FileIn n
4787       | FileOut n ->
4788           (* guestfish doesn't support string escaping, so neither do we *)
4789           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4790       | OptString n ->                  (* string option *)
4791           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4792           pr "    else printf (\" null\");\n"
4793       | StringList n
4794       | DeviceList n ->                 (* string list *)
4795           pr "    putchar (' ');\n";
4796           pr "    putchar ('\"');\n";
4797           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4798           pr "      if (i > 0) putchar (' ');\n";
4799           pr "      fputs (%s[i], stdout);\n" n;
4800           pr "    }\n";
4801           pr "    putchar ('\"');\n";
4802       | Bool n ->                       (* boolean *)
4803           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4804       | Int n ->                        (* int *)
4805           pr "    printf (\" %%d\", %s);\n" n
4806     ) (snd style);
4807     pr "    putchar ('\\n');\n";
4808     pr "  }\n";
4809     pr "\n";
4810   in
4811
4812   (* For non-daemon functions, generate a wrapper around each function. *)
4813   List.iter (
4814     fun (shortname, style, _, _, _, _, _) ->
4815       let name = "guestfs_" ^ shortname in
4816
4817       generate_prototype ~extern:false ~semicolon:false ~newline:true
4818         ~handle:"g" name style;
4819       pr "{\n";
4820       trace_call shortname style;
4821       pr "  return guestfs__%s " shortname;
4822       generate_c_call_args ~handle:"g" style;
4823       pr ";\n";
4824       pr "}\n";
4825       pr "\n"
4826   ) non_daemon_functions;
4827
4828   (* Client-side stubs for each function. *)
4829   List.iter (
4830     fun (shortname, style, _, _, _, _, _) ->
4831       let name = "guestfs_" ^ shortname in
4832
4833       (* Generate the action stub. *)
4834       generate_prototype ~extern:false ~semicolon:false ~newline:true
4835         ~handle:"g" name style;
4836
4837       let error_code =
4838         match fst style with
4839         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4840         | RConstString _ | RConstOptString _ ->
4841             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4842         | RString _ | RStringList _
4843         | RStruct _ | RStructList _
4844         | RHashtable _ | RBufferOut _ ->
4845             "NULL" in
4846
4847       pr "{\n";
4848
4849       (match snd style with
4850        | [] -> ()
4851        | _ -> pr "  struct %s_args args;\n" name
4852       );
4853
4854       pr "  guestfs_message_header hdr;\n";
4855       pr "  guestfs_message_error err;\n";
4856       let has_ret =
4857         match fst style with
4858         | RErr -> false
4859         | RConstString _ | RConstOptString _ ->
4860             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4861         | RInt _ | RInt64 _
4862         | RBool _ | RString _ | RStringList _
4863         | RStruct _ | RStructList _
4864         | RHashtable _ | RBufferOut _ ->
4865             pr "  struct %s_ret ret;\n" name;
4866             true in
4867
4868       pr "  int serial;\n";
4869       pr "  int r;\n";
4870       pr "\n";
4871       trace_call shortname style;
4872       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4873       pr "  guestfs___set_busy (g);\n";
4874       pr "\n";
4875
4876       (* Send the main header and arguments. *)
4877       (match snd style with
4878        | [] ->
4879            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4880              (String.uppercase shortname)
4881        | args ->
4882            List.iter (
4883              function
4884              | Pathname n | Device n | Dev_or_Path n | String n ->
4885                  pr "  args.%s = (char *) %s;\n" n n
4886              | OptString n ->
4887                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4888              | StringList n | DeviceList n ->
4889                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4890                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4891              | Bool n ->
4892                  pr "  args.%s = %s;\n" n n
4893              | Int n ->
4894                  pr "  args.%s = %s;\n" n n
4895              | FileIn _ | FileOut _ -> ()
4896            ) args;
4897            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4898              (String.uppercase shortname);
4899            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4900              name;
4901       );
4902       pr "  if (serial == -1) {\n";
4903       pr "    guestfs___end_busy (g);\n";
4904       pr "    return %s;\n" error_code;
4905       pr "  }\n";
4906       pr "\n";
4907
4908       (* Send any additional files (FileIn) requested. *)
4909       let need_read_reply_label = ref false in
4910       List.iter (
4911         function
4912         | FileIn n ->
4913             pr "  r = guestfs___send_file (g, %s);\n" n;
4914             pr "  if (r == -1) {\n";
4915             pr "    guestfs___end_busy (g);\n";
4916             pr "    return %s;\n" error_code;
4917             pr "  }\n";
4918             pr "  if (r == -2) /* daemon cancelled */\n";
4919             pr "    goto read_reply;\n";
4920             need_read_reply_label := true;
4921             pr "\n";
4922         | _ -> ()
4923       ) (snd style);
4924
4925       (* Wait for the reply from the remote end. *)
4926       if !need_read_reply_label then pr " read_reply:\n";
4927       pr "  memset (&hdr, 0, sizeof hdr);\n";
4928       pr "  memset (&err, 0, sizeof err);\n";
4929       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
4930       pr "\n";
4931       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
4932       if not has_ret then
4933         pr "NULL, NULL"
4934       else
4935         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
4936       pr ");\n";
4937
4938       pr "  if (r == -1) {\n";
4939       pr "    guestfs___end_busy (g);\n";
4940       pr "    return %s;\n" error_code;
4941       pr "  }\n";
4942       pr "\n";
4943
4944       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4945         (String.uppercase shortname);
4946       pr "    guestfs___end_busy (g);\n";
4947       pr "    return %s;\n" error_code;
4948       pr "  }\n";
4949       pr "\n";
4950
4951       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
4952       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
4953       pr "    free (err.error_message);\n";
4954       pr "    guestfs___end_busy (g);\n";
4955       pr "    return %s;\n" error_code;
4956       pr "  }\n";
4957       pr "\n";
4958
4959       (* Expecting to receive further files (FileOut)? *)
4960       List.iter (
4961         function
4962         | FileOut n ->
4963             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
4964             pr "    guestfs___end_busy (g);\n";
4965             pr "    return %s;\n" error_code;
4966             pr "  }\n";
4967             pr "\n";
4968         | _ -> ()
4969       ) (snd style);
4970
4971       pr "  guestfs___end_busy (g);\n";
4972
4973       (match fst style with
4974        | RErr -> pr "  return 0;\n"
4975        | RInt n | RInt64 n | RBool n ->
4976            pr "  return ret.%s;\n" n
4977        | RConstString _ | RConstOptString _ ->
4978            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4979        | RString n ->
4980            pr "  return ret.%s; /* caller will free */\n" n
4981        | RStringList n | RHashtable n ->
4982            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4983            pr "  ret.%s.%s_val =\n" n n;
4984            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
4985            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
4986              n n;
4987            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
4988            pr "  return ret.%s.%s_val;\n" n n
4989        | RStruct (n, _) ->
4990            pr "  /* caller will free this */\n";
4991            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4992        | RStructList (n, _) ->
4993            pr "  /* caller will free this */\n";
4994            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4995        | RBufferOut n ->
4996            pr "  *size_r = ret.%s.%s_len;\n" n n;
4997            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
4998       );
4999
5000       pr "}\n\n"
5001   ) daemon_functions;
5002
5003   (* Functions to free structures. *)
5004   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5005   pr " * structure format is identical to the XDR format.  See note in\n";
5006   pr " * generator.ml.\n";
5007   pr " */\n";
5008   pr "\n";
5009
5010   List.iter (
5011     fun (typ, _) ->
5012       pr "void\n";
5013       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5014       pr "{\n";
5015       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5016       pr "  free (x);\n";
5017       pr "}\n";
5018       pr "\n";
5019
5020       pr "void\n";
5021       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5022       pr "{\n";
5023       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5024       pr "  free (x);\n";
5025       pr "}\n";
5026       pr "\n";
5027
5028   ) structs;
5029
5030 (* Generate daemon/actions.h. *)
5031 and generate_daemon_actions_h () =
5032   generate_header CStyle GPLv2;
5033
5034   pr "#include \"../src/guestfs_protocol.h\"\n";
5035   pr "\n";
5036
5037   List.iter (
5038     fun (name, style, _, _, _, _, _) ->
5039       generate_prototype
5040         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5041         name style;
5042   ) daemon_functions
5043
5044 (* Generate the server-side stubs. *)
5045 and generate_daemon_actions () =
5046   generate_header CStyle GPLv2;
5047
5048   pr "#include <config.h>\n";
5049   pr "\n";
5050   pr "#include <stdio.h>\n";
5051   pr "#include <stdlib.h>\n";
5052   pr "#include <string.h>\n";
5053   pr "#include <inttypes.h>\n";
5054   pr "#include <rpc/types.h>\n";
5055   pr "#include <rpc/xdr.h>\n";
5056   pr "\n";
5057   pr "#include \"daemon.h\"\n";
5058   pr "#include \"c-ctype.h\"\n";
5059   pr "#include \"../src/guestfs_protocol.h\"\n";
5060   pr "#include \"actions.h\"\n";
5061   pr "\n";
5062
5063   List.iter (
5064     fun (name, style, _, _, _, _, _) ->
5065       (* Generate server-side stubs. *)
5066       pr "static void %s_stub (XDR *xdr_in)\n" name;
5067       pr "{\n";
5068       let error_code =
5069         match fst style with
5070         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5071         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5072         | RBool _ -> pr "  int r;\n"; "-1"
5073         | RConstString _ | RConstOptString _ ->
5074             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5075         | RString _ -> pr "  char *r;\n"; "NULL"
5076         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5077         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5078         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5079         | RBufferOut _ ->
5080             pr "  size_t size;\n";
5081             pr "  char *r;\n";
5082             "NULL" in
5083
5084       (match snd style with
5085        | [] -> ()
5086        | args ->
5087            pr "  struct guestfs_%s_args args;\n" name;
5088            List.iter (
5089              function
5090              | Device n | Dev_or_Path n
5091              | Pathname n
5092              | String n -> ()
5093              | OptString n -> pr "  char *%s;\n" n
5094              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5095              | Bool n -> pr "  int %s;\n" n
5096              | Int n -> pr "  int %s;\n" n
5097              | FileIn _ | FileOut _ -> ()
5098            ) args
5099       );
5100       pr "\n";
5101
5102       (match snd style with
5103        | [] -> ()
5104        | args ->
5105            pr "  memset (&args, 0, sizeof args);\n";
5106            pr "\n";
5107            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5108            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5109            pr "    return;\n";
5110            pr "  }\n";
5111            let pr_args n =
5112              pr "  char *%s = args.%s;\n" n n
5113            in
5114            let pr_list_handling_code n =
5115              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5116              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5117              pr "  if (%s == NULL) {\n" n;
5118              pr "    reply_with_perror (\"realloc\");\n";
5119              pr "    goto done;\n";
5120              pr "  }\n";
5121              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5122              pr "  args.%s.%s_val = %s;\n" n n n;
5123            in
5124            List.iter (
5125              function
5126              | Pathname n ->
5127                  pr_args n;
5128                  pr "  ABS_PATH (%s, goto done);\n" n;
5129              | Device n ->
5130                  pr_args n;
5131                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5132              | Dev_or_Path n ->
5133                  pr_args n;
5134                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5135              | String n -> pr_args n
5136              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5137              | StringList n ->
5138                  pr_list_handling_code n;
5139              | DeviceList n ->
5140                  pr_list_handling_code n;
5141                  pr "  /* Ensure that each is a device,\n";
5142                  pr "   * and perform device name translation. */\n";
5143                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5144                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5145                  pr "  }\n";
5146              | Bool n -> pr "  %s = args.%s;\n" n n
5147              | Int n -> pr "  %s = args.%s;\n" n n
5148              | FileIn _ | FileOut _ -> ()
5149            ) args;
5150            pr "\n"
5151       );
5152
5153
5154       (* this is used at least for do_equal *)
5155       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5156         (* Emit NEED_ROOT just once, even when there are two or
5157            more Pathname args *)
5158         pr "  NEED_ROOT (goto done);\n";
5159       );
5160
5161       (* Don't want to call the impl with any FileIn or FileOut
5162        * parameters, since these go "outside" the RPC protocol.
5163        *)
5164       let args' =
5165         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5166           (snd style) in
5167       pr "  r = do_%s " name;
5168       generate_c_call_args (fst style, args');
5169       pr ";\n";
5170
5171       pr "  if (r == %s)\n" error_code;
5172       pr "    /* do_%s has already called reply_with_error */\n" name;
5173       pr "    goto done;\n";
5174       pr "\n";
5175
5176       (* If there are any FileOut parameters, then the impl must
5177        * send its own reply.
5178        *)
5179       let no_reply =
5180         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5181       if no_reply then
5182         pr "  /* do_%s has already sent a reply */\n" name
5183       else (
5184         match fst style with
5185         | RErr -> pr "  reply (NULL, NULL);\n"
5186         | RInt n | RInt64 n | RBool n ->
5187             pr "  struct guestfs_%s_ret ret;\n" name;
5188             pr "  ret.%s = r;\n" n;
5189             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5190               name
5191         | RConstString _ | RConstOptString _ ->
5192             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5193         | RString n ->
5194             pr "  struct guestfs_%s_ret ret;\n" name;
5195             pr "  ret.%s = r;\n" n;
5196             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5197               name;
5198             pr "  free (r);\n"
5199         | RStringList n | RHashtable n ->
5200             pr "  struct guestfs_%s_ret ret;\n" name;
5201             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5202             pr "  ret.%s.%s_val = r;\n" n n;
5203             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5204               name;
5205             pr "  free_strings (r);\n"
5206         | RStruct (n, _) ->
5207             pr "  struct guestfs_%s_ret ret;\n" name;
5208             pr "  ret.%s = *r;\n" n;
5209             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5210               name;
5211             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5212               name
5213         | RStructList (n, _) ->
5214             pr "  struct guestfs_%s_ret ret;\n" name;
5215             pr "  ret.%s = *r;\n" n;
5216             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5217               name;
5218             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5219               name
5220         | RBufferOut n ->
5221             pr "  struct guestfs_%s_ret ret;\n" name;
5222             pr "  ret.%s.%s_val = r;\n" n n;
5223             pr "  ret.%s.%s_len = size;\n" n n;
5224             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5225               name;
5226             pr "  free (r);\n"
5227       );
5228
5229       (* Free the args. *)
5230       (match snd style with
5231        | [] ->
5232            pr "done: ;\n";
5233        | _ ->
5234            pr "done:\n";
5235            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5236              name
5237       );
5238
5239       pr "}\n\n";
5240   ) daemon_functions;
5241
5242   (* Dispatch function. *)
5243   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5244   pr "{\n";
5245   pr "  switch (proc_nr) {\n";
5246
5247   List.iter (
5248     fun (name, style, _, _, _, _, _) ->
5249       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5250       pr "      %s_stub (xdr_in);\n" name;
5251       pr "      break;\n"
5252   ) daemon_functions;
5253
5254   pr "    default:\n";
5255   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";
5256   pr "  }\n";
5257   pr "}\n";
5258   pr "\n";
5259
5260   (* LVM columns and tokenization functions. *)
5261   (* XXX This generates crap code.  We should rethink how we
5262    * do this parsing.
5263    *)
5264   List.iter (
5265     function
5266     | typ, cols ->
5267         pr "static const char *lvm_%s_cols = \"%s\";\n"
5268           typ (String.concat "," (List.map fst cols));
5269         pr "\n";
5270
5271         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5272         pr "{\n";
5273         pr "  char *tok, *p, *next;\n";
5274         pr "  int i, j;\n";
5275         pr "\n";
5276         (*
5277           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5278           pr "\n";
5279         *)
5280         pr "  if (!str) {\n";
5281         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5282         pr "    return -1;\n";
5283         pr "  }\n";
5284         pr "  if (!*str || c_isspace (*str)) {\n";
5285         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5286         pr "    return -1;\n";
5287         pr "  }\n";
5288         pr "  tok = str;\n";
5289         List.iter (
5290           fun (name, coltype) ->
5291             pr "  if (!tok) {\n";
5292             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5293             pr "    return -1;\n";
5294             pr "  }\n";
5295             pr "  p = strchrnul (tok, ',');\n";
5296             pr "  if (*p) next = p+1; else next = NULL;\n";
5297             pr "  *p = '\\0';\n";
5298             (match coltype with
5299              | FString ->
5300                  pr "  r->%s = strdup (tok);\n" name;
5301                  pr "  if (r->%s == NULL) {\n" name;
5302                  pr "    perror (\"strdup\");\n";
5303                  pr "    return -1;\n";
5304                  pr "  }\n"
5305              | FUUID ->
5306                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5307                  pr "    if (tok[j] == '\\0') {\n";
5308                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5309                  pr "      return -1;\n";
5310                  pr "    } else if (tok[j] != '-')\n";
5311                  pr "      r->%s[i++] = tok[j];\n" name;
5312                  pr "  }\n";
5313              | FBytes ->
5314                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5315                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5316                  pr "    return -1;\n";
5317                  pr "  }\n";
5318              | FInt64 ->
5319                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5320                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5321                  pr "    return -1;\n";
5322                  pr "  }\n";
5323              | FOptPercent ->
5324                  pr "  if (tok[0] == '\\0')\n";
5325                  pr "    r->%s = -1;\n" name;
5326                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5327                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5328                  pr "    return -1;\n";
5329                  pr "  }\n";
5330              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5331                  assert false (* can never be an LVM column *)
5332             );
5333             pr "  tok = next;\n";
5334         ) cols;
5335
5336         pr "  if (tok != NULL) {\n";
5337         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5338         pr "    return -1;\n";
5339         pr "  }\n";
5340         pr "  return 0;\n";
5341         pr "}\n";
5342         pr "\n";
5343
5344         pr "guestfs_int_lvm_%s_list *\n" typ;
5345         pr "parse_command_line_%ss (void)\n" typ;
5346         pr "{\n";
5347         pr "  char *out, *err;\n";
5348         pr "  char *p, *pend;\n";
5349         pr "  int r, i;\n";
5350         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5351         pr "  void *newp;\n";
5352         pr "\n";
5353         pr "  ret = malloc (sizeof *ret);\n";
5354         pr "  if (!ret) {\n";
5355         pr "    reply_with_perror (\"malloc\");\n";
5356         pr "    return NULL;\n";
5357         pr "  }\n";
5358         pr "\n";
5359         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5360         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5361         pr "\n";
5362         pr "  r = command (&out, &err,\n";
5363         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5364         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5365         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5366         pr "  if (r == -1) {\n";
5367         pr "    reply_with_error (\"%%s\", err);\n";
5368         pr "    free (out);\n";
5369         pr "    free (err);\n";
5370         pr "    free (ret);\n";
5371         pr "    return NULL;\n";
5372         pr "  }\n";
5373         pr "\n";
5374         pr "  free (err);\n";
5375         pr "\n";
5376         pr "  /* Tokenize each line of the output. */\n";
5377         pr "  p = out;\n";
5378         pr "  i = 0;\n";
5379         pr "  while (p) {\n";
5380         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5381         pr "    if (pend) {\n";
5382         pr "      *pend = '\\0';\n";
5383         pr "      pend++;\n";
5384         pr "    }\n";
5385         pr "\n";
5386         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5387         pr "      p++;\n";
5388         pr "\n";
5389         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5390         pr "      p = pend;\n";
5391         pr "      continue;\n";
5392         pr "    }\n";
5393         pr "\n";
5394         pr "    /* Allocate some space to store this next entry. */\n";
5395         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5396         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5397         pr "    if (newp == NULL) {\n";
5398         pr "      reply_with_perror (\"realloc\");\n";
5399         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5400         pr "      free (ret);\n";
5401         pr "      free (out);\n";
5402         pr "      return NULL;\n";
5403         pr "    }\n";
5404         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5405         pr "\n";
5406         pr "    /* Tokenize the next entry. */\n";
5407         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5408         pr "    if (r == -1) {\n";
5409         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5410         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5411         pr "      free (ret);\n";
5412         pr "      free (out);\n";
5413         pr "      return NULL;\n";
5414         pr "    }\n";
5415         pr "\n";
5416         pr "    ++i;\n";
5417         pr "    p = pend;\n";
5418         pr "  }\n";
5419         pr "\n";
5420         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5421         pr "\n";
5422         pr "  free (out);\n";
5423         pr "  return ret;\n";
5424         pr "}\n"
5425
5426   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5427
5428 (* Generate a list of function names, for debugging in the daemon.. *)
5429 and generate_daemon_names () =
5430   generate_header CStyle GPLv2;
5431
5432   pr "#include <config.h>\n";
5433   pr "\n";
5434   pr "#include \"daemon.h\"\n";
5435   pr "\n";
5436
5437   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5438   pr "const char *function_names[] = {\n";
5439   List.iter (
5440     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5441   ) daemon_functions;
5442   pr "};\n";
5443
5444 (* Generate the tests. *)
5445 and generate_tests () =
5446   generate_header CStyle GPLv2;
5447
5448   pr "\
5449 #include <stdio.h>
5450 #include <stdlib.h>
5451 #include <string.h>
5452 #include <unistd.h>
5453 #include <sys/types.h>
5454 #include <fcntl.h>
5455
5456 #include \"guestfs.h\"
5457
5458 static guestfs_h *g;
5459 static int suppress_error = 0;
5460
5461 static void print_error (guestfs_h *g, void *data, const char *msg)
5462 {
5463   if (!suppress_error)
5464     fprintf (stderr, \"%%s\\n\", msg);
5465 }
5466
5467 /* FIXME: nearly identical code appears in fish.c */
5468 static void print_strings (char *const *argv)
5469 {
5470   int argc;
5471
5472   for (argc = 0; argv[argc] != NULL; ++argc)
5473     printf (\"\\t%%s\\n\", argv[argc]);
5474 }
5475
5476 /*
5477 static void print_table (char const *const *argv)
5478 {
5479   int i;
5480
5481   for (i = 0; argv[i] != NULL; i += 2)
5482     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5483 }
5484 */
5485
5486 ";
5487
5488   (* Generate a list of commands which are not tested anywhere. *)
5489   pr "static void no_test_warnings (void)\n";
5490   pr "{\n";
5491
5492   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5493   List.iter (
5494     fun (_, _, _, _, tests, _, _) ->
5495       let tests = filter_map (
5496         function
5497         | (_, (Always|If _|Unless _), test) -> Some test
5498         | (_, Disabled, _) -> None
5499       ) tests in
5500       let seq = List.concat (List.map seq_of_test tests) in
5501       let cmds_tested = List.map List.hd seq in
5502       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5503   ) all_functions;
5504
5505   List.iter (
5506     fun (name, _, _, _, _, _, _) ->
5507       if not (Hashtbl.mem hash name) then
5508         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5509   ) all_functions;
5510
5511   pr "}\n";
5512   pr "\n";
5513
5514   (* Generate the actual tests.  Note that we generate the tests
5515    * in reverse order, deliberately, so that (in general) the
5516    * newest tests run first.  This makes it quicker and easier to
5517    * debug them.
5518    *)
5519   let test_names =
5520     List.map (
5521       fun (name, _, _, _, tests, _, _) ->
5522         mapi (generate_one_test name) tests
5523     ) (List.rev all_functions) in
5524   let test_names = List.concat test_names in
5525   let nr_tests = List.length test_names in
5526
5527   pr "\
5528 int main (int argc, char *argv[])
5529 {
5530   char c = 0;
5531   unsigned long int n_failed = 0;
5532   const char *filename;
5533   int fd;
5534   int nr_tests, test_num = 0;
5535
5536   setbuf (stdout, NULL);
5537
5538   no_test_warnings ();
5539
5540   g = guestfs_create ();
5541   if (g == NULL) {
5542     printf (\"guestfs_create FAILED\\n\");
5543     exit (1);
5544   }
5545
5546   guestfs_set_error_handler (g, print_error, NULL);
5547
5548   guestfs_set_path (g, \"../appliance\");
5549
5550   filename = \"test1.img\";
5551   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5552   if (fd == -1) {
5553     perror (filename);
5554     exit (1);
5555   }
5556   if (lseek (fd, %d, SEEK_SET) == -1) {
5557     perror (\"lseek\");
5558     close (fd);
5559     unlink (filename);
5560     exit (1);
5561   }
5562   if (write (fd, &c, 1) == -1) {
5563     perror (\"write\");
5564     close (fd);
5565     unlink (filename);
5566     exit (1);
5567   }
5568   if (close (fd) == -1) {
5569     perror (filename);
5570     unlink (filename);
5571     exit (1);
5572   }
5573   if (guestfs_add_drive (g, filename) == -1) {
5574     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5575     exit (1);
5576   }
5577
5578   filename = \"test2.img\";
5579   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5580   if (fd == -1) {
5581     perror (filename);
5582     exit (1);
5583   }
5584   if (lseek (fd, %d, SEEK_SET) == -1) {
5585     perror (\"lseek\");
5586     close (fd);
5587     unlink (filename);
5588     exit (1);
5589   }
5590   if (write (fd, &c, 1) == -1) {
5591     perror (\"write\");
5592     close (fd);
5593     unlink (filename);
5594     exit (1);
5595   }
5596   if (close (fd) == -1) {
5597     perror (filename);
5598     unlink (filename);
5599     exit (1);
5600   }
5601   if (guestfs_add_drive (g, filename) == -1) {
5602     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5603     exit (1);
5604   }
5605
5606   filename = \"test3.img\";
5607   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5608   if (fd == -1) {
5609     perror (filename);
5610     exit (1);
5611   }
5612   if (lseek (fd, %d, SEEK_SET) == -1) {
5613     perror (\"lseek\");
5614     close (fd);
5615     unlink (filename);
5616     exit (1);
5617   }
5618   if (write (fd, &c, 1) == -1) {
5619     perror (\"write\");
5620     close (fd);
5621     unlink (filename);
5622     exit (1);
5623   }
5624   if (close (fd) == -1) {
5625     perror (filename);
5626     unlink (filename);
5627     exit (1);
5628   }
5629   if (guestfs_add_drive (g, filename) == -1) {
5630     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5631     exit (1);
5632   }
5633
5634   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5635     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5636     exit (1);
5637   }
5638
5639   if (guestfs_launch (g) == -1) {
5640     printf (\"guestfs_launch FAILED\\n\");
5641     exit (1);
5642   }
5643
5644   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5645   alarm (600);
5646
5647   /* Cancel previous alarm. */
5648   alarm (0);
5649
5650   nr_tests = %d;
5651
5652 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5653
5654   iteri (
5655     fun i test_name ->
5656       pr "  test_num++;\n";
5657       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5658       pr "  if (%s () == -1) {\n" test_name;
5659       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5660       pr "    n_failed++;\n";
5661       pr "  }\n";
5662   ) test_names;
5663   pr "\n";
5664
5665   pr "  guestfs_close (g);\n";
5666   pr "  unlink (\"test1.img\");\n";
5667   pr "  unlink (\"test2.img\");\n";
5668   pr "  unlink (\"test3.img\");\n";
5669   pr "\n";
5670
5671   pr "  if (n_failed > 0) {\n";
5672   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5673   pr "    exit (1);\n";
5674   pr "  }\n";
5675   pr "\n";
5676
5677   pr "  exit (0);\n";
5678   pr "}\n"
5679
5680 and generate_one_test name i (init, prereq, test) =
5681   let test_name = sprintf "test_%s_%d" name i in
5682
5683   pr "\
5684 static int %s_skip (void)
5685 {
5686   const char *str;
5687
5688   str = getenv (\"TEST_ONLY\");
5689   if (str)
5690     return strstr (str, \"%s\") == NULL;
5691   str = getenv (\"SKIP_%s\");
5692   if (str && strcmp (str, \"1\") == 0) return 1;
5693   str = getenv (\"SKIP_TEST_%s\");
5694   if (str && strcmp (str, \"1\") == 0) return 1;
5695   return 0;
5696 }
5697
5698 " test_name name (String.uppercase test_name) (String.uppercase name);
5699
5700   (match prereq with
5701    | Disabled | Always -> ()
5702    | If code | Unless code ->
5703        pr "static int %s_prereq (void)\n" test_name;
5704        pr "{\n";
5705        pr "  %s\n" code;
5706        pr "}\n";
5707        pr "\n";
5708   );
5709
5710   pr "\
5711 static int %s (void)
5712 {
5713   if (%s_skip ()) {
5714     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5715     return 0;
5716   }
5717
5718 " test_name test_name test_name;
5719
5720   (match prereq with
5721    | Disabled ->
5722        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5723    | If _ ->
5724        pr "  if (! %s_prereq ()) {\n" test_name;
5725        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5726        pr "    return 0;\n";
5727        pr "  }\n";
5728        pr "\n";
5729        generate_one_test_body name i test_name init test;
5730    | Unless _ ->
5731        pr "  if (%s_prereq ()) {\n" test_name;
5732        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5733        pr "    return 0;\n";
5734        pr "  }\n";
5735        pr "\n";
5736        generate_one_test_body name i test_name init test;
5737    | Always ->
5738        generate_one_test_body name i test_name init test
5739   );
5740
5741   pr "  return 0;\n";
5742   pr "}\n";
5743   pr "\n";
5744   test_name
5745
5746 and generate_one_test_body name i test_name init test =
5747   (match init with
5748    | InitNone (* XXX at some point, InitNone and InitEmpty became
5749                * folded together as the same thing.  Really we should
5750                * make InitNone do nothing at all, but the tests may
5751                * need to be checked to make sure this is OK.
5752                *)
5753    | InitEmpty ->
5754        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5755        List.iter (generate_test_command_call test_name)
5756          [["blockdev_setrw"; "/dev/sda"];
5757           ["umount_all"];
5758           ["lvm_remove_all"]]
5759    | InitPartition ->
5760        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5761        List.iter (generate_test_command_call test_name)
5762          [["blockdev_setrw"; "/dev/sda"];
5763           ["umount_all"];
5764           ["lvm_remove_all"];
5765           ["sfdiskM"; "/dev/sda"; ","]]
5766    | InitBasicFS ->
5767        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5768        List.iter (generate_test_command_call test_name)
5769          [["blockdev_setrw"; "/dev/sda"];
5770           ["umount_all"];
5771           ["lvm_remove_all"];
5772           ["sfdiskM"; "/dev/sda"; ","];
5773           ["mkfs"; "ext2"; "/dev/sda1"];
5774           ["mount"; "/dev/sda1"; "/"]]
5775    | InitBasicFSonLVM ->
5776        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5777          test_name;
5778        List.iter (generate_test_command_call test_name)
5779          [["blockdev_setrw"; "/dev/sda"];
5780           ["umount_all"];
5781           ["lvm_remove_all"];
5782           ["sfdiskM"; "/dev/sda"; ","];
5783           ["pvcreate"; "/dev/sda1"];
5784           ["vgcreate"; "VG"; "/dev/sda1"];
5785           ["lvcreate"; "LV"; "VG"; "8"];
5786           ["mkfs"; "ext2"; "/dev/VG/LV"];
5787           ["mount"; "/dev/VG/LV"; "/"]]
5788    | InitISOFS ->
5789        pr "  /* InitISOFS for %s */\n" test_name;
5790        List.iter (generate_test_command_call test_name)
5791          [["blockdev_setrw"; "/dev/sda"];
5792           ["umount_all"];
5793           ["lvm_remove_all"];
5794           ["mount_ro"; "/dev/sdd"; "/"]]
5795   );
5796
5797   let get_seq_last = function
5798     | [] ->
5799         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5800           test_name
5801     | seq ->
5802         let seq = List.rev seq in
5803         List.rev (List.tl seq), List.hd seq
5804   in
5805
5806   match test with
5807   | TestRun seq ->
5808       pr "  /* TestRun for %s (%d) */\n" name i;
5809       List.iter (generate_test_command_call test_name) seq
5810   | TestOutput (seq, expected) ->
5811       pr "  /* TestOutput for %s (%d) */\n" name i;
5812       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5813       let seq, last = get_seq_last seq in
5814       let test () =
5815         pr "    if (strcmp (r, expected) != 0) {\n";
5816         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5817         pr "      return -1;\n";
5818         pr "    }\n"
5819       in
5820       List.iter (generate_test_command_call test_name) seq;
5821       generate_test_command_call ~test test_name last
5822   | TestOutputList (seq, expected) ->
5823       pr "  /* TestOutputList for %s (%d) */\n" name i;
5824       let seq, last = get_seq_last seq in
5825       let test () =
5826         iteri (
5827           fun i str ->
5828             pr "    if (!r[%d]) {\n" i;
5829             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5830             pr "      print_strings (r);\n";
5831             pr "      return -1;\n";
5832             pr "    }\n";
5833             pr "    {\n";
5834             pr "      const char *expected = \"%s\";\n" (c_quote str);
5835             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5836             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5837             pr "        return -1;\n";
5838             pr "      }\n";
5839             pr "    }\n"
5840         ) expected;
5841         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5842         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5843           test_name;
5844         pr "      print_strings (r);\n";
5845         pr "      return -1;\n";
5846         pr "    }\n"
5847       in
5848       List.iter (generate_test_command_call test_name) seq;
5849       generate_test_command_call ~test test_name last
5850   | TestOutputListOfDevices (seq, expected) ->
5851       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5852       let seq, last = get_seq_last seq in
5853       let test () =
5854         iteri (
5855           fun i str ->
5856             pr "    if (!r[%d]) {\n" i;
5857             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5858             pr "      print_strings (r);\n";
5859             pr "      return -1;\n";
5860             pr "    }\n";
5861             pr "    {\n";
5862             pr "      const char *expected = \"%s\";\n" (c_quote str);
5863             pr "      r[%d][5] = 's';\n" i;
5864             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5865             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5866             pr "        return -1;\n";
5867             pr "      }\n";
5868             pr "    }\n"
5869         ) expected;
5870         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5871         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5872           test_name;
5873         pr "      print_strings (r);\n";
5874         pr "      return -1;\n";
5875         pr "    }\n"
5876       in
5877       List.iter (generate_test_command_call test_name) seq;
5878       generate_test_command_call ~test test_name last
5879   | TestOutputInt (seq, expected) ->
5880       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5881       let seq, last = get_seq_last seq in
5882       let test () =
5883         pr "    if (r != %d) {\n" expected;
5884         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5885           test_name expected;
5886         pr "               (int) r);\n";
5887         pr "      return -1;\n";
5888         pr "    }\n"
5889       in
5890       List.iter (generate_test_command_call test_name) seq;
5891       generate_test_command_call ~test test_name last
5892   | TestOutputIntOp (seq, op, expected) ->
5893       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5894       let seq, last = get_seq_last seq in
5895       let test () =
5896         pr "    if (! (r %s %d)) {\n" op expected;
5897         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5898           test_name op expected;
5899         pr "               (int) r);\n";
5900         pr "      return -1;\n";
5901         pr "    }\n"
5902       in
5903       List.iter (generate_test_command_call test_name) seq;
5904       generate_test_command_call ~test test_name last
5905   | TestOutputTrue seq ->
5906       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5907       let seq, last = get_seq_last seq in
5908       let test () =
5909         pr "    if (!r) {\n";
5910         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5911           test_name;
5912         pr "      return -1;\n";
5913         pr "    }\n"
5914       in
5915       List.iter (generate_test_command_call test_name) seq;
5916       generate_test_command_call ~test test_name last
5917   | TestOutputFalse seq ->
5918       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5919       let seq, last = get_seq_last seq in
5920       let test () =
5921         pr "    if (r) {\n";
5922         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5923           test_name;
5924         pr "      return -1;\n";
5925         pr "    }\n"
5926       in
5927       List.iter (generate_test_command_call test_name) seq;
5928       generate_test_command_call ~test test_name last
5929   | TestOutputLength (seq, expected) ->
5930       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5931       let seq, last = get_seq_last seq in
5932       let test () =
5933         pr "    int j;\n";
5934         pr "    for (j = 0; j < %d; ++j)\n" expected;
5935         pr "      if (r[j] == NULL) {\n";
5936         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5937           test_name;
5938         pr "        print_strings (r);\n";
5939         pr "        return -1;\n";
5940         pr "      }\n";
5941         pr "    if (r[j] != NULL) {\n";
5942         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5943           test_name;
5944         pr "      print_strings (r);\n";
5945         pr "      return -1;\n";
5946         pr "    }\n"
5947       in
5948       List.iter (generate_test_command_call test_name) seq;
5949       generate_test_command_call ~test test_name last
5950   | TestOutputBuffer (seq, expected) ->
5951       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5952       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5953       let seq, last = get_seq_last seq in
5954       let len = String.length expected in
5955       let test () =
5956         pr "    if (size != %d) {\n" len;
5957         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5958         pr "      return -1;\n";
5959         pr "    }\n";
5960         pr "    if (strncmp (r, expected, size) != 0) {\n";
5961         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5962         pr "      return -1;\n";
5963         pr "    }\n"
5964       in
5965       List.iter (generate_test_command_call test_name) seq;
5966       generate_test_command_call ~test test_name last
5967   | TestOutputStruct (seq, checks) ->
5968       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5969       let seq, last = get_seq_last seq in
5970       let test () =
5971         List.iter (
5972           function
5973           | CompareWithInt (field, expected) ->
5974               pr "    if (r->%s != %d) {\n" field expected;
5975               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5976                 test_name field expected;
5977               pr "               (int) r->%s);\n" field;
5978               pr "      return -1;\n";
5979               pr "    }\n"
5980           | CompareWithIntOp (field, op, expected) ->
5981               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5982               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5983                 test_name field op expected;
5984               pr "               (int) r->%s);\n" field;
5985               pr "      return -1;\n";
5986               pr "    }\n"
5987           | CompareWithString (field, expected) ->
5988               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5989               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5990                 test_name field expected;
5991               pr "               r->%s);\n" field;
5992               pr "      return -1;\n";
5993               pr "    }\n"
5994           | CompareFieldsIntEq (field1, field2) ->
5995               pr "    if (r->%s != r->%s) {\n" field1 field2;
5996               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5997                 test_name field1 field2;
5998               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5999               pr "      return -1;\n";
6000               pr "    }\n"
6001           | CompareFieldsStrEq (field1, field2) ->
6002               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
6003               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6004                 test_name field1 field2;
6005               pr "               r->%s, r->%s);\n" field1 field2;
6006               pr "      return -1;\n";
6007               pr "    }\n"
6008         ) checks
6009       in
6010       List.iter (generate_test_command_call test_name) seq;
6011       generate_test_command_call ~test test_name last
6012   | TestLastFail seq ->
6013       pr "  /* TestLastFail for %s (%d) */\n" name i;
6014       let seq, last = get_seq_last seq in
6015       List.iter (generate_test_command_call test_name) seq;
6016       generate_test_command_call test_name ~expect_error:true last
6017
6018 (* Generate the code to run a command, leaving the result in 'r'.
6019  * If you expect to get an error then you should set expect_error:true.
6020  *)
6021 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6022   match cmd with
6023   | [] -> assert false
6024   | name :: args ->
6025       (* Look up the command to find out what args/ret it has. *)
6026       let style =
6027         try
6028           let _, style, _, _, _, _, _ =
6029             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6030           style
6031         with Not_found ->
6032           failwithf "%s: in test, command %s was not found" test_name name in
6033
6034       if List.length (snd style) <> List.length args then
6035         failwithf "%s: in test, wrong number of args given to %s"
6036           test_name name;
6037
6038       pr "  {\n";
6039
6040       List.iter (
6041         function
6042         | OptString n, "NULL" -> ()
6043         | Pathname n, arg
6044         | Device n, arg
6045         | Dev_or_Path n, arg
6046         | String n, arg
6047         | OptString n, arg ->
6048             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6049         | Int _, _
6050         | Bool _, _
6051         | FileIn _, _ | FileOut _, _ -> ()
6052         | StringList n, arg | DeviceList n, arg ->
6053             let strs = string_split " " arg in
6054             iteri (
6055               fun i str ->
6056                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6057             ) strs;
6058             pr "    const char *const %s[] = {\n" n;
6059             iteri (
6060               fun i _ -> pr "      %s_%d,\n" n i
6061             ) strs;
6062             pr "      NULL\n";
6063             pr "    };\n";
6064       ) (List.combine (snd style) args);
6065
6066       let error_code =
6067         match fst style with
6068         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6069         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6070         | RConstString _ | RConstOptString _ ->
6071             pr "    const char *r;\n"; "NULL"
6072         | RString _ -> pr "    char *r;\n"; "NULL"
6073         | RStringList _ | RHashtable _ ->
6074             pr "    char **r;\n";
6075             pr "    int i;\n";
6076             "NULL"
6077         | RStruct (_, typ) ->
6078             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6079         | RStructList (_, typ) ->
6080             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6081         | RBufferOut _ ->
6082             pr "    char *r;\n";
6083             pr "    size_t size;\n";
6084             "NULL" in
6085
6086       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6087       pr "    r = guestfs_%s (g" name;
6088
6089       (* Generate the parameters. *)
6090       List.iter (
6091         function
6092         | OptString _, "NULL" -> pr ", NULL"
6093         | Pathname n, _
6094         | Device n, _ | Dev_or_Path n, _
6095         | String n, _
6096         | OptString n, _ ->
6097             pr ", %s" n
6098         | FileIn _, arg | FileOut _, arg ->
6099             pr ", \"%s\"" (c_quote arg)
6100         | StringList n, _ | DeviceList n, _ ->
6101             pr ", (char **) %s" n
6102         | Int _, arg ->
6103             let i =
6104               try int_of_string arg
6105               with Failure "int_of_string" ->
6106                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6107             pr ", %d" i
6108         | Bool _, arg ->
6109             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6110       ) (List.combine (snd style) args);
6111
6112       (match fst style with
6113        | RBufferOut _ -> pr ", &size"
6114        | _ -> ()
6115       );
6116
6117       pr ");\n";
6118
6119       if not expect_error then
6120         pr "    if (r == %s)\n" error_code
6121       else
6122         pr "    if (r != %s)\n" error_code;
6123       pr "      return -1;\n";
6124
6125       (* Insert the test code. *)
6126       (match test with
6127        | None -> ()
6128        | Some f -> f ()
6129       );
6130
6131       (match fst style with
6132        | RErr | RInt _ | RInt64 _ | RBool _
6133        | RConstString _ | RConstOptString _ -> ()
6134        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6135        | RStringList _ | RHashtable _ ->
6136            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6137            pr "      free (r[i]);\n";
6138            pr "    free (r);\n"
6139        | RStruct (_, typ) ->
6140            pr "    guestfs_free_%s (r);\n" typ
6141        | RStructList (_, typ) ->
6142            pr "    guestfs_free_%s_list (r);\n" typ
6143       );
6144
6145       pr "  }\n"
6146
6147 and c_quote str =
6148   let str = replace_str str "\r" "\\r" in
6149   let str = replace_str str "\n" "\\n" in
6150   let str = replace_str str "\t" "\\t" in
6151   let str = replace_str str "\000" "\\0" in
6152   str
6153
6154 (* Generate a lot of different functions for guestfish. *)
6155 and generate_fish_cmds () =
6156   generate_header CStyle GPLv2;
6157
6158   let all_functions =
6159     List.filter (
6160       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6161     ) all_functions in
6162   let all_functions_sorted =
6163     List.filter (
6164       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6165     ) all_functions_sorted in
6166
6167   pr "#include <stdio.h>\n";
6168   pr "#include <stdlib.h>\n";
6169   pr "#include <string.h>\n";
6170   pr "#include <inttypes.h>\n";
6171   pr "\n";
6172   pr "#include <guestfs.h>\n";
6173   pr "#include \"c-ctype.h\"\n";
6174   pr "#include \"fish.h\"\n";
6175   pr "\n";
6176
6177   (* list_commands function, which implements guestfish -h *)
6178   pr "void list_commands (void)\n";
6179   pr "{\n";
6180   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6181   pr "  list_builtin_commands ();\n";
6182   List.iter (
6183     fun (name, _, _, flags, _, shortdesc, _) ->
6184       let name = replace_char name '_' '-' in
6185       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6186         name shortdesc
6187   ) all_functions_sorted;
6188   pr "  printf (\"    %%s\\n\",";
6189   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6190   pr "}\n";
6191   pr "\n";
6192
6193   (* display_command function, which implements guestfish -h cmd *)
6194   pr "void display_command (const char *cmd)\n";
6195   pr "{\n";
6196   List.iter (
6197     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6198       let name2 = replace_char name '_' '-' in
6199       let alias =
6200         try find_map (function FishAlias n -> Some n | _ -> None) flags
6201         with Not_found -> name in
6202       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6203       let synopsis =
6204         match snd style with
6205         | [] -> name2
6206         | args ->
6207             sprintf "%s <%s>"
6208               name2 (String.concat "> <" (List.map name_of_argt args)) in
6209
6210       let warnings =
6211         if List.mem ProtocolLimitWarning flags then
6212           ("\n\n" ^ protocol_limit_warning)
6213         else "" in
6214
6215       (* For DangerWillRobinson commands, we should probably have
6216        * guestfish prompt before allowing you to use them (especially
6217        * in interactive mode). XXX
6218        *)
6219       let warnings =
6220         warnings ^
6221           if List.mem DangerWillRobinson flags then
6222             ("\n\n" ^ danger_will_robinson)
6223           else "" in
6224
6225       let warnings =
6226         warnings ^
6227           match deprecation_notice flags with
6228           | None -> ""
6229           | Some txt -> "\n\n" ^ txt in
6230
6231       let describe_alias =
6232         if name <> alias then
6233           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6234         else "" in
6235
6236       pr "  if (";
6237       pr "strcasecmp (cmd, \"%s\") == 0" name;
6238       if name <> name2 then
6239         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6240       if name <> alias then
6241         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6242       pr ")\n";
6243       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6244         name2 shortdesc
6245         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6246       pr "  else\n"
6247   ) all_functions;
6248   pr "    display_builtin_command (cmd);\n";
6249   pr "}\n";
6250   pr "\n";
6251
6252   let emit_print_list_function typ =
6253     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6254       typ typ typ;
6255     pr "{\n";
6256     pr "  unsigned int i;\n";
6257     pr "\n";
6258     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6259     pr "    printf (\"[%%d] = {\\n\", i);\n";
6260     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6261     pr "    printf (\"}\\n\");\n";
6262     pr "  }\n";
6263     pr "}\n";
6264     pr "\n";
6265   in
6266
6267   (* print_* functions *)
6268   List.iter (
6269     fun (typ, cols) ->
6270       let needs_i =
6271         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6272
6273       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6274       pr "{\n";
6275       if needs_i then (
6276         pr "  unsigned int i;\n";
6277         pr "\n"
6278       );
6279       List.iter (
6280         function
6281         | name, FString ->
6282             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6283         | name, FUUID ->
6284             pr "  printf (\"%s: \");\n" name;
6285             pr "  for (i = 0; i < 32; ++i)\n";
6286             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6287             pr "  printf (\"\\n\");\n"
6288         | name, FBuffer ->
6289             pr "  printf (\"%%s%s: \", indent);\n" name;
6290             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6291             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6292             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6293             pr "    else\n";
6294             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6295             pr "  printf (\"\\n\");\n"
6296         | name, (FUInt64|FBytes) ->
6297             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6298               name typ name
6299         | name, FInt64 ->
6300             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6301               name typ name
6302         | name, FUInt32 ->
6303             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6304               name typ name
6305         | name, FInt32 ->
6306             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6307               name typ name
6308         | name, FChar ->
6309             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6310               name typ name
6311         | name, FOptPercent ->
6312             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6313               typ name name typ name;
6314             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6315       ) cols;
6316       pr "}\n";
6317       pr "\n";
6318   ) structs;
6319
6320   (* Emit a print_TYPE_list function definition only if that function is used. *)
6321   List.iter (
6322     function
6323     | typ, (RStructListOnly | RStructAndList) ->
6324         (* generate the function for typ *)
6325         emit_print_list_function typ
6326     | typ, _ -> () (* empty *)
6327   ) (rstructs_used_by all_functions);
6328
6329   (* Emit a print_TYPE function definition only if that function is used. *)
6330   List.iter (
6331     function
6332     | typ, (RStructOnly | RStructAndList) ->
6333         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6334         pr "{\n";
6335         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6336         pr "}\n";
6337         pr "\n";
6338     | typ, _ -> () (* empty *)
6339   ) (rstructs_used_by all_functions);
6340
6341   (* run_<action> actions *)
6342   List.iter (
6343     fun (name, style, _, flags, _, _, _) ->
6344       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6345       pr "{\n";
6346       (match fst style with
6347        | RErr
6348        | RInt _
6349        | RBool _ -> pr "  int r;\n"
6350        | RInt64 _ -> pr "  int64_t r;\n"
6351        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6352        | RString _ -> pr "  char *r;\n"
6353        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6354        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6355        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6356        | RBufferOut _ ->
6357            pr "  char *r;\n";
6358            pr "  size_t size;\n";
6359       );
6360       List.iter (
6361         function
6362         | Device n
6363         | String n
6364         | OptString n
6365         | FileIn n
6366         | FileOut n -> pr "  const char *%s;\n" n
6367         | Pathname n
6368         | Dev_or_Path n -> pr "  char *%s;\n" n
6369         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6370         | Bool n -> pr "  int %s;\n" n
6371         | Int n -> pr "  int %s;\n" n
6372       ) (snd style);
6373
6374       (* Check and convert parameters. *)
6375       let argc_expected = List.length (snd style) in
6376       pr "  if (argc != %d) {\n" argc_expected;
6377       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6378         argc_expected;
6379       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6380       pr "    return -1;\n";
6381       pr "  }\n";
6382       iteri (
6383         fun i ->
6384           function
6385           | Device name
6386           | String name ->
6387               pr "  %s = argv[%d];\n" name i
6388           | Pathname name
6389           | Dev_or_Path name ->
6390               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6391               pr "  if (%s == NULL) return -1;\n" name
6392           | OptString name ->
6393               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6394                 name i i
6395           | FileIn name ->
6396               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6397                 name i i
6398           | FileOut name ->
6399               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6400                 name i i
6401           | StringList name | DeviceList name ->
6402               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6403               pr "  if (%s == NULL) return -1;\n" name;
6404           | Bool name ->
6405               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6406           | Int name ->
6407               pr "  %s = atoi (argv[%d]);\n" name i
6408       ) (snd style);
6409
6410       (* Call C API function. *)
6411       let fn =
6412         try find_map (function FishAction n -> Some n | _ -> None) flags
6413         with Not_found -> sprintf "guestfs_%s" name in
6414       pr "  r = %s " fn;
6415       generate_c_call_args ~handle:"g" style;
6416       pr ";\n";
6417
6418       List.iter (
6419         function
6420         | Device name | String name
6421         | OptString name | FileIn name | FileOut name | Bool name
6422         | Int name -> ()
6423         | Pathname name | Dev_or_Path name ->
6424             pr "  free (%s);\n" name
6425         | StringList name | DeviceList name ->
6426             pr "  free_strings (%s);\n" name
6427       ) (snd style);
6428
6429       (* Check return value for errors and display command results. *)
6430       (match fst style with
6431        | RErr -> pr "  return r;\n"
6432        | RInt _ ->
6433            pr "  if (r == -1) return -1;\n";
6434            pr "  printf (\"%%d\\n\", r);\n";
6435            pr "  return 0;\n"
6436        | RInt64 _ ->
6437            pr "  if (r == -1) return -1;\n";
6438            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6439            pr "  return 0;\n"
6440        | RBool _ ->
6441            pr "  if (r == -1) return -1;\n";
6442            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6443            pr "  return 0;\n"
6444        | RConstString _ ->
6445            pr "  if (r == NULL) return -1;\n";
6446            pr "  printf (\"%%s\\n\", r);\n";
6447            pr "  return 0;\n"
6448        | RConstOptString _ ->
6449            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6450            pr "  return 0;\n"
6451        | RString _ ->
6452            pr "  if (r == NULL) return -1;\n";
6453            pr "  printf (\"%%s\\n\", r);\n";
6454            pr "  free (r);\n";
6455            pr "  return 0;\n"
6456        | RStringList _ ->
6457            pr "  if (r == NULL) return -1;\n";
6458            pr "  print_strings (r);\n";
6459            pr "  free_strings (r);\n";
6460            pr "  return 0;\n"
6461        | RStruct (_, typ) ->
6462            pr "  if (r == NULL) return -1;\n";
6463            pr "  print_%s (r);\n" typ;
6464            pr "  guestfs_free_%s (r);\n" typ;
6465            pr "  return 0;\n"
6466        | RStructList (_, typ) ->
6467            pr "  if (r == NULL) return -1;\n";
6468            pr "  print_%s_list (r);\n" typ;
6469            pr "  guestfs_free_%s_list (r);\n" typ;
6470            pr "  return 0;\n"
6471        | RHashtable _ ->
6472            pr "  if (r == NULL) return -1;\n";
6473            pr "  print_table (r);\n";
6474            pr "  free_strings (r);\n";
6475            pr "  return 0;\n"
6476        | RBufferOut _ ->
6477            pr "  if (r == NULL) return -1;\n";
6478            pr "  fwrite (r, size, 1, stdout);\n";
6479            pr "  free (r);\n";
6480            pr "  return 0;\n"
6481       );
6482       pr "}\n";
6483       pr "\n"
6484   ) all_functions;
6485
6486   (* run_action function *)
6487   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6488   pr "{\n";
6489   List.iter (
6490     fun (name, _, _, flags, _, _, _) ->
6491       let name2 = replace_char name '_' '-' in
6492       let alias =
6493         try find_map (function FishAlias n -> Some n | _ -> None) flags
6494         with Not_found -> name in
6495       pr "  if (";
6496       pr "strcasecmp (cmd, \"%s\") == 0" name;
6497       if name <> name2 then
6498         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6499       if name <> alias then
6500         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6501       pr ")\n";
6502       pr "    return run_%s (cmd, argc, argv);\n" name;
6503       pr "  else\n";
6504   ) all_functions;
6505   pr "    {\n";
6506   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6507   pr "      return -1;\n";
6508   pr "    }\n";
6509   pr "  return 0;\n";
6510   pr "}\n";
6511   pr "\n"
6512
6513 (* Readline completion for guestfish. *)
6514 and generate_fish_completion () =
6515   generate_header CStyle GPLv2;
6516
6517   let all_functions =
6518     List.filter (
6519       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6520     ) all_functions in
6521
6522   pr "\
6523 #include <config.h>
6524
6525 #include <stdio.h>
6526 #include <stdlib.h>
6527 #include <string.h>
6528
6529 #ifdef HAVE_LIBREADLINE
6530 #include <readline/readline.h>
6531 #endif
6532
6533 #include \"fish.h\"
6534
6535 #ifdef HAVE_LIBREADLINE
6536
6537 static const char *const commands[] = {
6538   BUILTIN_COMMANDS_FOR_COMPLETION,
6539 ";
6540
6541   (* Get the commands, including the aliases.  They don't need to be
6542    * sorted - the generator() function just does a dumb linear search.
6543    *)
6544   let commands =
6545     List.map (
6546       fun (name, _, _, flags, _, _, _) ->
6547         let name2 = replace_char name '_' '-' in
6548         let alias =
6549           try find_map (function FishAlias n -> Some n | _ -> None) flags
6550           with Not_found -> name in
6551
6552         if name <> alias then [name2; alias] else [name2]
6553     ) all_functions in
6554   let commands = List.flatten commands in
6555
6556   List.iter (pr "  \"%s\",\n") commands;
6557
6558   pr "  NULL
6559 };
6560
6561 static char *
6562 generator (const char *text, int state)
6563 {
6564   static int index, len;
6565   const char *name;
6566
6567   if (!state) {
6568     index = 0;
6569     len = strlen (text);
6570   }
6571
6572   rl_attempted_completion_over = 1;
6573
6574   while ((name = commands[index]) != NULL) {
6575     index++;
6576     if (strncasecmp (name, text, len) == 0)
6577       return strdup (name);
6578   }
6579
6580   return NULL;
6581 }
6582
6583 #endif /* HAVE_LIBREADLINE */
6584
6585 char **do_completion (const char *text, int start, int end)
6586 {
6587   char **matches = NULL;
6588
6589 #ifdef HAVE_LIBREADLINE
6590   rl_completion_append_character = ' ';
6591
6592   if (start == 0)
6593     matches = rl_completion_matches (text, generator);
6594   else if (complete_dest_paths)
6595     matches = rl_completion_matches (text, complete_dest_paths_generator);
6596 #endif
6597
6598   return matches;
6599 }
6600 ";
6601
6602 (* Generate the POD documentation for guestfish. *)
6603 and generate_fish_actions_pod () =
6604   let all_functions_sorted =
6605     List.filter (
6606       fun (_, _, _, flags, _, _, _) ->
6607         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6608     ) all_functions_sorted in
6609
6610   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6611
6612   List.iter (
6613     fun (name, style, _, flags, _, _, longdesc) ->
6614       let longdesc =
6615         Str.global_substitute rex (
6616           fun s ->
6617             let sub =
6618               try Str.matched_group 1 s
6619               with Not_found ->
6620                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6621             "C<" ^ replace_char sub '_' '-' ^ ">"
6622         ) longdesc in
6623       let name = replace_char name '_' '-' in
6624       let alias =
6625         try find_map (function FishAlias n -> Some n | _ -> None) flags
6626         with Not_found -> name in
6627
6628       pr "=head2 %s" name;
6629       if name <> alias then
6630         pr " | %s" alias;
6631       pr "\n";
6632       pr "\n";
6633       pr " %s" name;
6634       List.iter (
6635         function
6636         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6637         | OptString n -> pr " %s" n
6638         | StringList n | DeviceList n -> pr " '%s ...'" n
6639         | Bool _ -> pr " true|false"
6640         | Int n -> pr " %s" n
6641         | FileIn n | FileOut n -> pr " (%s|-)" n
6642       ) (snd style);
6643       pr "\n";
6644       pr "\n";
6645       pr "%s\n\n" longdesc;
6646
6647       if List.exists (function FileIn _ | FileOut _ -> true
6648                       | _ -> false) (snd style) then
6649         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6650
6651       if List.mem ProtocolLimitWarning flags then
6652         pr "%s\n\n" protocol_limit_warning;
6653
6654       if List.mem DangerWillRobinson flags then
6655         pr "%s\n\n" danger_will_robinson;
6656
6657       match deprecation_notice flags with
6658       | None -> ()
6659       | Some txt -> pr "%s\n\n" txt
6660   ) all_functions_sorted
6661
6662 (* Generate a C function prototype. *)
6663 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6664     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6665     ?(prefix = "")
6666     ?handle name style =
6667   if extern then pr "extern ";
6668   if static then pr "static ";
6669   (match fst style with
6670    | RErr -> pr "int "
6671    | RInt _ -> pr "int "
6672    | RInt64 _ -> pr "int64_t "
6673    | RBool _ -> pr "int "
6674    | RConstString _ | RConstOptString _ -> pr "const char *"
6675    | RString _ | RBufferOut _ -> pr "char *"
6676    | RStringList _ | RHashtable _ -> pr "char **"
6677    | RStruct (_, typ) ->
6678        if not in_daemon then pr "struct guestfs_%s *" typ
6679        else pr "guestfs_int_%s *" typ
6680    | RStructList (_, typ) ->
6681        if not in_daemon then pr "struct guestfs_%s_list *" typ
6682        else pr "guestfs_int_%s_list *" typ
6683   );
6684   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6685   pr "%s%s (" prefix name;
6686   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6687     pr "void"
6688   else (
6689     let comma = ref false in
6690     (match handle with
6691      | None -> ()
6692      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6693     );
6694     let next () =
6695       if !comma then (
6696         if single_line then pr ", " else pr ",\n\t\t"
6697       );
6698       comma := true
6699     in
6700     List.iter (
6701       function
6702       | Pathname n
6703       | Device n | Dev_or_Path n
6704       | String n
6705       | OptString n ->
6706           next ();
6707           pr "const char *%s" n
6708       | StringList n | DeviceList n ->
6709           next ();
6710           pr "char *const *%s" n
6711       | Bool n -> next (); pr "int %s" n
6712       | Int n -> next (); pr "int %s" n
6713       | FileIn n
6714       | FileOut n ->
6715           if not in_daemon then (next (); pr "const char *%s" n)
6716     ) (snd style);
6717     if is_RBufferOut then (next (); pr "size_t *size_r");
6718   );
6719   pr ")";
6720   if semicolon then pr ";";
6721   if newline then pr "\n"
6722
6723 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6724 and generate_c_call_args ?handle ?(decl = false) style =
6725   pr "(";
6726   let comma = ref false in
6727   let next () =
6728     if !comma then pr ", ";
6729     comma := true
6730   in
6731   (match handle with
6732    | None -> ()
6733    | Some handle -> pr "%s" handle; comma := true
6734   );
6735   List.iter (
6736     fun arg ->
6737       next ();
6738       pr "%s" (name_of_argt arg)
6739   ) (snd style);
6740   (* For RBufferOut calls, add implicit &size parameter. *)
6741   if not decl then (
6742     match fst style with
6743     | RBufferOut _ ->
6744         next ();
6745         pr "&size"
6746     | _ -> ()
6747   );
6748   pr ")"
6749
6750 (* Generate the OCaml bindings interface. *)
6751 and generate_ocaml_mli () =
6752   generate_header OCamlStyle LGPLv2;
6753
6754   pr "\
6755 (** For API documentation you should refer to the C API
6756     in the guestfs(3) manual page.  The OCaml API uses almost
6757     exactly the same calls. *)
6758
6759 type t
6760 (** A [guestfs_h] handle. *)
6761
6762 exception Error of string
6763 (** This exception is raised when there is an error. *)
6764
6765 val create : unit -> t
6766
6767 val close : t -> unit
6768 (** Handles are closed by the garbage collector when they become
6769     unreferenced, but callers can also call this in order to
6770     provide predictable cleanup. *)
6771
6772 ";
6773   generate_ocaml_structure_decls ();
6774
6775   (* The actions. *)
6776   List.iter (
6777     fun (name, style, _, _, _, shortdesc, _) ->
6778       generate_ocaml_prototype name style;
6779       pr "(** %s *)\n" shortdesc;
6780       pr "\n"
6781   ) all_functions
6782
6783 (* Generate the OCaml bindings implementation. *)
6784 and generate_ocaml_ml () =
6785   generate_header OCamlStyle LGPLv2;
6786
6787   pr "\
6788 type t
6789 exception Error of string
6790 external create : unit -> t = \"ocaml_guestfs_create\"
6791 external close : t -> unit = \"ocaml_guestfs_close\"
6792
6793 let () =
6794   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6795
6796 ";
6797
6798   generate_ocaml_structure_decls ();
6799
6800   (* The actions. *)
6801   List.iter (
6802     fun (name, style, _, _, _, shortdesc, _) ->
6803       generate_ocaml_prototype ~is_external:true name style;
6804   ) all_functions
6805
6806 (* Generate the OCaml bindings C implementation. *)
6807 and generate_ocaml_c () =
6808   generate_header CStyle LGPLv2;
6809
6810   pr "\
6811 #include <stdio.h>
6812 #include <stdlib.h>
6813 #include <string.h>
6814
6815 #include <caml/config.h>
6816 #include <caml/alloc.h>
6817 #include <caml/callback.h>
6818 #include <caml/fail.h>
6819 #include <caml/memory.h>
6820 #include <caml/mlvalues.h>
6821 #include <caml/signals.h>
6822
6823 #include <guestfs.h>
6824
6825 #include \"guestfs_c.h\"
6826
6827 /* Copy a hashtable of string pairs into an assoc-list.  We return
6828  * the list in reverse order, but hashtables aren't supposed to be
6829  * ordered anyway.
6830  */
6831 static CAMLprim value
6832 copy_table (char * const * argv)
6833 {
6834   CAMLparam0 ();
6835   CAMLlocal5 (rv, pairv, kv, vv, cons);
6836   int i;
6837
6838   rv = Val_int (0);
6839   for (i = 0; argv[i] != NULL; i += 2) {
6840     kv = caml_copy_string (argv[i]);
6841     vv = caml_copy_string (argv[i+1]);
6842     pairv = caml_alloc (2, 0);
6843     Store_field (pairv, 0, kv);
6844     Store_field (pairv, 1, vv);
6845     cons = caml_alloc (2, 0);
6846     Store_field (cons, 1, rv);
6847     rv = cons;
6848     Store_field (cons, 0, pairv);
6849   }
6850
6851   CAMLreturn (rv);
6852 }
6853
6854 ";
6855
6856   (* Struct copy functions. *)
6857
6858   let emit_ocaml_copy_list_function typ =
6859     pr "static CAMLprim value\n";
6860     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6861     pr "{\n";
6862     pr "  CAMLparam0 ();\n";
6863     pr "  CAMLlocal2 (rv, v);\n";
6864     pr "  unsigned int i;\n";
6865     pr "\n";
6866     pr "  if (%ss->len == 0)\n" typ;
6867     pr "    CAMLreturn (Atom (0));\n";
6868     pr "  else {\n";
6869     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6870     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6871     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6872     pr "      caml_modify (&Field (rv, i), v);\n";
6873     pr "    }\n";
6874     pr "    CAMLreturn (rv);\n";
6875     pr "  }\n";
6876     pr "}\n";
6877     pr "\n";
6878   in
6879
6880   List.iter (
6881     fun (typ, cols) ->
6882       let has_optpercent_col =
6883         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6884
6885       pr "static CAMLprim value\n";
6886       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6887       pr "{\n";
6888       pr "  CAMLparam0 ();\n";
6889       if has_optpercent_col then
6890         pr "  CAMLlocal3 (rv, v, v2);\n"
6891       else
6892         pr "  CAMLlocal2 (rv, v);\n";
6893       pr "\n";
6894       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6895       iteri (
6896         fun i col ->
6897           (match col with
6898            | name, FString ->
6899                pr "  v = caml_copy_string (%s->%s);\n" typ name
6900            | name, FBuffer ->
6901                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6902                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6903                  typ name typ name
6904            | name, FUUID ->
6905                pr "  v = caml_alloc_string (32);\n";
6906                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6907            | name, (FBytes|FInt64|FUInt64) ->
6908                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6909            | name, (FInt32|FUInt32) ->
6910                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6911            | name, FOptPercent ->
6912                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6913                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6914                pr "    v = caml_alloc (1, 0);\n";
6915                pr "    Store_field (v, 0, v2);\n";
6916                pr "  } else /* None */\n";
6917                pr "    v = Val_int (0);\n";
6918            | name, FChar ->
6919                pr "  v = Val_int (%s->%s);\n" typ name
6920           );
6921           pr "  Store_field (rv, %d, v);\n" i
6922       ) cols;
6923       pr "  CAMLreturn (rv);\n";
6924       pr "}\n";
6925       pr "\n";
6926   ) structs;
6927
6928   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6929   List.iter (
6930     function
6931     | typ, (RStructListOnly | RStructAndList) ->
6932         (* generate the function for typ *)
6933         emit_ocaml_copy_list_function typ
6934     | typ, _ -> () (* empty *)
6935   ) (rstructs_used_by all_functions);
6936
6937   (* The wrappers. *)
6938   List.iter (
6939     fun (name, style, _, _, _, _, _) ->
6940       let params =
6941         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6942
6943       let needs_extra_vs =
6944         match fst style with RConstOptString _ -> true | _ -> false in
6945
6946       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6947       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6948       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6949
6950       pr "CAMLprim value\n";
6951       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6952       List.iter (pr ", value %s") (List.tl params);
6953       pr ")\n";
6954       pr "{\n";
6955
6956       (match params with
6957        | [p1; p2; p3; p4; p5] ->
6958            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6959        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6960            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6961            pr "  CAMLxparam%d (%s);\n"
6962              (List.length rest) (String.concat ", " rest)
6963        | ps ->
6964            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6965       );
6966       if not needs_extra_vs then
6967         pr "  CAMLlocal1 (rv);\n"
6968       else
6969         pr "  CAMLlocal3 (rv, v, v2);\n";
6970       pr "\n";
6971
6972       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6973       pr "  if (g == NULL)\n";
6974       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6975       pr "\n";
6976
6977       List.iter (
6978         function
6979         | Pathname n
6980         | Device n | Dev_or_Path n
6981         | String n
6982         | FileIn n
6983         | FileOut n ->
6984             pr "  const char *%s = String_val (%sv);\n" n n
6985         | OptString n ->
6986             pr "  const char *%s =\n" n;
6987             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6988               n n
6989         | StringList n | DeviceList n ->
6990             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6991         | Bool n ->
6992             pr "  int %s = Bool_val (%sv);\n" n n
6993         | Int n ->
6994             pr "  int %s = Int_val (%sv);\n" n n
6995       ) (snd style);
6996       let error_code =
6997         match fst style with
6998         | RErr -> pr "  int r;\n"; "-1"
6999         | RInt _ -> pr "  int r;\n"; "-1"
7000         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7001         | RBool _ -> pr "  int r;\n"; "-1"
7002         | RConstString _ | RConstOptString _ ->
7003             pr "  const char *r;\n"; "NULL"
7004         | RString _ -> pr "  char *r;\n"; "NULL"
7005         | RStringList _ ->
7006             pr "  int i;\n";
7007             pr "  char **r;\n";
7008             "NULL"
7009         | RStruct (_, typ) ->
7010             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7011         | RStructList (_, typ) ->
7012             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7013         | RHashtable _ ->
7014             pr "  int i;\n";
7015             pr "  char **r;\n";
7016             "NULL"
7017         | RBufferOut _ ->
7018             pr "  char *r;\n";
7019             pr "  size_t size;\n";
7020             "NULL" in
7021       pr "\n";
7022
7023       pr "  caml_enter_blocking_section ();\n";
7024       pr "  r = guestfs_%s " name;
7025       generate_c_call_args ~handle:"g" style;
7026       pr ";\n";
7027       pr "  caml_leave_blocking_section ();\n";
7028
7029       List.iter (
7030         function
7031         | StringList n | DeviceList n ->
7032             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7033         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7034         | FileIn _ | FileOut _ -> ()
7035       ) (snd style);
7036
7037       pr "  if (r == %s)\n" error_code;
7038       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7039       pr "\n";
7040
7041       (match fst style with
7042        | RErr -> pr "  rv = Val_unit;\n"
7043        | RInt _ -> pr "  rv = Val_int (r);\n"
7044        | RInt64 _ ->
7045            pr "  rv = caml_copy_int64 (r);\n"
7046        | RBool _ -> pr "  rv = Val_bool (r);\n"
7047        | RConstString _ ->
7048            pr "  rv = caml_copy_string (r);\n"
7049        | RConstOptString _ ->
7050            pr "  if (r) { /* Some string */\n";
7051            pr "    v = caml_alloc (1, 0);\n";
7052            pr "    v2 = caml_copy_string (r);\n";
7053            pr "    Store_field (v, 0, v2);\n";
7054            pr "  } else /* None */\n";
7055            pr "    v = Val_int (0);\n";
7056        | RString _ ->
7057            pr "  rv = caml_copy_string (r);\n";
7058            pr "  free (r);\n"
7059        | RStringList _ ->
7060            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7061            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7062            pr "  free (r);\n"
7063        | RStruct (_, typ) ->
7064            pr "  rv = copy_%s (r);\n" typ;
7065            pr "  guestfs_free_%s (r);\n" typ;
7066        | RStructList (_, typ) ->
7067            pr "  rv = copy_%s_list (r);\n" typ;
7068            pr "  guestfs_free_%s_list (r);\n" typ;
7069        | RHashtable _ ->
7070            pr "  rv = copy_table (r);\n";
7071            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7072            pr "  free (r);\n";
7073        | RBufferOut _ ->
7074            pr "  rv = caml_alloc_string (size);\n";
7075            pr "  memcpy (String_val (rv), r, size);\n";
7076       );
7077
7078       pr "  CAMLreturn (rv);\n";
7079       pr "}\n";
7080       pr "\n";
7081
7082       if List.length params > 5 then (
7083         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7084         pr "CAMLprim value ";
7085         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7086         pr "CAMLprim value\n";
7087         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7088         pr "{\n";
7089         pr "  return ocaml_guestfs_%s (argv[0]" name;
7090         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7091         pr ");\n";
7092         pr "}\n";
7093         pr "\n"
7094       )
7095   ) all_functions
7096
7097 and generate_ocaml_structure_decls () =
7098   List.iter (
7099     fun (typ, cols) ->
7100       pr "type %s = {\n" typ;
7101       List.iter (
7102         function
7103         | name, FString -> pr "  %s : string;\n" name
7104         | name, FBuffer -> pr "  %s : string;\n" name
7105         | name, FUUID -> pr "  %s : string;\n" name
7106         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7107         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7108         | name, FChar -> pr "  %s : char;\n" name
7109         | name, FOptPercent -> pr "  %s : float option;\n" name
7110       ) cols;
7111       pr "}\n";
7112       pr "\n"
7113   ) structs
7114
7115 and generate_ocaml_prototype ?(is_external = false) name style =
7116   if is_external then pr "external " else pr "val ";
7117   pr "%s : t -> " name;
7118   List.iter (
7119     function
7120     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7121     | OptString _ -> pr "string option -> "
7122     | StringList _ | DeviceList _ -> pr "string array -> "
7123     | Bool _ -> pr "bool -> "
7124     | Int _ -> pr "int -> "
7125   ) (snd style);
7126   (match fst style with
7127    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7128    | RInt _ -> pr "int"
7129    | RInt64 _ -> pr "int64"
7130    | RBool _ -> pr "bool"
7131    | RConstString _ -> pr "string"
7132    | RConstOptString _ -> pr "string option"
7133    | RString _ | RBufferOut _ -> pr "string"
7134    | RStringList _ -> pr "string array"
7135    | RStruct (_, typ) -> pr "%s" typ
7136    | RStructList (_, typ) -> pr "%s array" typ
7137    | RHashtable _ -> pr "(string * string) list"
7138   );
7139   if is_external then (
7140     pr " = ";
7141     if List.length (snd style) + 1 > 5 then
7142       pr "\"ocaml_guestfs_%s_byte\" " name;
7143     pr "\"ocaml_guestfs_%s\"" name
7144   );
7145   pr "\n"
7146
7147 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7148 and generate_perl_xs () =
7149   generate_header CStyle LGPLv2;
7150
7151   pr "\
7152 #include \"EXTERN.h\"
7153 #include \"perl.h\"
7154 #include \"XSUB.h\"
7155
7156 #include <guestfs.h>
7157
7158 #ifndef PRId64
7159 #define PRId64 \"lld\"
7160 #endif
7161
7162 static SV *
7163 my_newSVll(long long val) {
7164 #ifdef USE_64_BIT_ALL
7165   return newSViv(val);
7166 #else
7167   char buf[100];
7168   int len;
7169   len = snprintf(buf, 100, \"%%\" PRId64, val);
7170   return newSVpv(buf, len);
7171 #endif
7172 }
7173
7174 #ifndef PRIu64
7175 #define PRIu64 \"llu\"
7176 #endif
7177
7178 static SV *
7179 my_newSVull(unsigned long long val) {
7180 #ifdef USE_64_BIT_ALL
7181   return newSVuv(val);
7182 #else
7183   char buf[100];
7184   int len;
7185   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7186   return newSVpv(buf, len);
7187 #endif
7188 }
7189
7190 /* http://www.perlmonks.org/?node_id=680842 */
7191 static char **
7192 XS_unpack_charPtrPtr (SV *arg) {
7193   char **ret;
7194   AV *av;
7195   I32 i;
7196
7197   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7198     croak (\"array reference expected\");
7199
7200   av = (AV *)SvRV (arg);
7201   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7202   if (!ret)
7203     croak (\"malloc failed\");
7204
7205   for (i = 0; i <= av_len (av); i++) {
7206     SV **elem = av_fetch (av, i, 0);
7207
7208     if (!elem || !*elem)
7209       croak (\"missing element in list\");
7210
7211     ret[i] = SvPV_nolen (*elem);
7212   }
7213
7214   ret[i] = NULL;
7215
7216   return ret;
7217 }
7218
7219 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7220
7221 PROTOTYPES: ENABLE
7222
7223 guestfs_h *
7224 _create ()
7225    CODE:
7226       RETVAL = guestfs_create ();
7227       if (!RETVAL)
7228         croak (\"could not create guestfs handle\");
7229       guestfs_set_error_handler (RETVAL, NULL, NULL);
7230  OUTPUT:
7231       RETVAL
7232
7233 void
7234 DESTROY (g)
7235       guestfs_h *g;
7236  PPCODE:
7237       guestfs_close (g);
7238
7239 ";
7240
7241   List.iter (
7242     fun (name, style, _, _, _, _, _) ->
7243       (match fst style with
7244        | RErr -> pr "void\n"
7245        | RInt _ -> pr "SV *\n"
7246        | RInt64 _ -> pr "SV *\n"
7247        | RBool _ -> pr "SV *\n"
7248        | RConstString _ -> pr "SV *\n"
7249        | RConstOptString _ -> pr "SV *\n"
7250        | RString _ -> pr "SV *\n"
7251        | RBufferOut _ -> pr "SV *\n"
7252        | RStringList _
7253        | RStruct _ | RStructList _
7254        | RHashtable _ ->
7255            pr "void\n" (* all lists returned implictly on the stack *)
7256       );
7257       (* Call and arguments. *)
7258       pr "%s " name;
7259       generate_c_call_args ~handle:"g" ~decl:true style;
7260       pr "\n";
7261       pr "      guestfs_h *g;\n";
7262       iteri (
7263         fun i ->
7264           function
7265           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7266               pr "      char *%s;\n" n
7267           | OptString n ->
7268               (* http://www.perlmonks.org/?node_id=554277
7269                * Note that the implicit handle argument means we have
7270                * to add 1 to the ST(x) operator.
7271                *)
7272               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7273           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7274           | Bool n -> pr "      int %s;\n" n
7275           | Int n -> pr "      int %s;\n" n
7276       ) (snd style);
7277
7278       let do_cleanups () =
7279         List.iter (
7280           function
7281           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7282           | FileIn _ | FileOut _ -> ()
7283           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7284         ) (snd style)
7285       in
7286
7287       (* Code. *)
7288       (match fst style with
7289        | RErr ->
7290            pr "PREINIT:\n";
7291            pr "      int r;\n";
7292            pr " PPCODE:\n";
7293            pr "      r = guestfs_%s " name;
7294            generate_c_call_args ~handle:"g" style;
7295            pr ";\n";
7296            do_cleanups ();
7297            pr "      if (r == -1)\n";
7298            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7299        | RInt n
7300        | RBool n ->
7301            pr "PREINIT:\n";
7302            pr "      int %s;\n" n;
7303            pr "   CODE:\n";
7304            pr "      %s = guestfs_%s " n name;
7305            generate_c_call_args ~handle:"g" style;
7306            pr ";\n";
7307            do_cleanups ();
7308            pr "      if (%s == -1)\n" n;
7309            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7310            pr "      RETVAL = newSViv (%s);\n" n;
7311            pr " OUTPUT:\n";
7312            pr "      RETVAL\n"
7313        | RInt64 n ->
7314            pr "PREINIT:\n";
7315            pr "      int64_t %s;\n" n;
7316            pr "   CODE:\n";
7317            pr "      %s = guestfs_%s " n name;
7318            generate_c_call_args ~handle:"g" style;
7319            pr ";\n";
7320            do_cleanups ();
7321            pr "      if (%s == -1)\n" n;
7322            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7323            pr "      RETVAL = my_newSVll (%s);\n" n;
7324            pr " OUTPUT:\n";
7325            pr "      RETVAL\n"
7326        | RConstString n ->
7327            pr "PREINIT:\n";
7328            pr "      const char *%s;\n" n;
7329            pr "   CODE:\n";
7330            pr "      %s = guestfs_%s " n name;
7331            generate_c_call_args ~handle:"g" style;
7332            pr ";\n";
7333            do_cleanups ();
7334            pr "      if (%s == NULL)\n" n;
7335            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7336            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7337            pr " OUTPUT:\n";
7338            pr "      RETVAL\n"
7339        | RConstOptString n ->
7340            pr "PREINIT:\n";
7341            pr "      const char *%s;\n" n;
7342            pr "   CODE:\n";
7343            pr "      %s = guestfs_%s " n name;
7344            generate_c_call_args ~handle:"g" style;
7345            pr ";\n";
7346            do_cleanups ();
7347            pr "      if (%s == NULL)\n" n;
7348            pr "        RETVAL = &PL_sv_undef;\n";
7349            pr "      else\n";
7350            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7351            pr " OUTPUT:\n";
7352            pr "      RETVAL\n"
7353        | RString n ->
7354            pr "PREINIT:\n";
7355            pr "      char *%s;\n" n;
7356            pr "   CODE:\n";
7357            pr "      %s = guestfs_%s " n name;
7358            generate_c_call_args ~handle:"g" style;
7359            pr ";\n";
7360            do_cleanups ();
7361            pr "      if (%s == NULL)\n" n;
7362            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7363            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7364            pr "      free (%s);\n" n;
7365            pr " OUTPUT:\n";
7366            pr "      RETVAL\n"
7367        | RStringList n | RHashtable n ->
7368            pr "PREINIT:\n";
7369            pr "      char **%s;\n" n;
7370            pr "      int i, n;\n";
7371            pr " PPCODE:\n";
7372            pr "      %s = guestfs_%s " n name;
7373            generate_c_call_args ~handle:"g" style;
7374            pr ";\n";
7375            do_cleanups ();
7376            pr "      if (%s == NULL)\n" n;
7377            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7378            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7379            pr "      EXTEND (SP, n);\n";
7380            pr "      for (i = 0; i < n; ++i) {\n";
7381            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7382            pr "        free (%s[i]);\n" n;
7383            pr "      }\n";
7384            pr "      free (%s);\n" n;
7385        | RStruct (n, typ) ->
7386            let cols = cols_of_struct typ in
7387            generate_perl_struct_code typ cols name style n do_cleanups
7388        | RStructList (n, typ) ->
7389            let cols = cols_of_struct typ in
7390            generate_perl_struct_list_code typ cols name style n do_cleanups
7391        | RBufferOut n ->
7392            pr "PREINIT:\n";
7393            pr "      char *%s;\n" n;
7394            pr "      size_t size;\n";
7395            pr "   CODE:\n";
7396            pr "      %s = guestfs_%s " n name;
7397            generate_c_call_args ~handle:"g" style;
7398            pr ";\n";
7399            do_cleanups ();
7400            pr "      if (%s == NULL)\n" n;
7401            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7402            pr "      RETVAL = newSVpv (%s, size);\n" n;
7403            pr "      free (%s);\n" n;
7404            pr " OUTPUT:\n";
7405            pr "      RETVAL\n"
7406       );
7407
7408       pr "\n"
7409   ) all_functions
7410
7411 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7412   pr "PREINIT:\n";
7413   pr "      struct guestfs_%s_list *%s;\n" typ n;
7414   pr "      int i;\n";
7415   pr "      HV *hv;\n";
7416   pr " PPCODE:\n";
7417   pr "      %s = guestfs_%s " n name;
7418   generate_c_call_args ~handle:"g" style;
7419   pr ";\n";
7420   do_cleanups ();
7421   pr "      if (%s == NULL)\n" n;
7422   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7423   pr "      EXTEND (SP, %s->len);\n" n;
7424   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7425   pr "        hv = newHV ();\n";
7426   List.iter (
7427     function
7428     | name, FString ->
7429         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7430           name (String.length name) n name
7431     | name, FUUID ->
7432         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7433           name (String.length name) n name
7434     | name, FBuffer ->
7435         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7436           name (String.length name) n name n name
7437     | name, (FBytes|FUInt64) ->
7438         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7439           name (String.length name) n name
7440     | name, FInt64 ->
7441         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7442           name (String.length name) n name
7443     | name, (FInt32|FUInt32) ->
7444         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7445           name (String.length name) n name
7446     | name, FChar ->
7447         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7448           name (String.length name) n name
7449     | name, FOptPercent ->
7450         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7451           name (String.length name) n name
7452   ) cols;
7453   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7454   pr "      }\n";
7455   pr "      guestfs_free_%s_list (%s);\n" typ n
7456
7457 and generate_perl_struct_code typ cols name style n do_cleanups =
7458   pr "PREINIT:\n";
7459   pr "      struct guestfs_%s *%s;\n" typ n;
7460   pr " PPCODE:\n";
7461   pr "      %s = guestfs_%s " n name;
7462   generate_c_call_args ~handle:"g" style;
7463   pr ";\n";
7464   do_cleanups ();
7465   pr "      if (%s == NULL)\n" n;
7466   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7467   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7468   List.iter (
7469     fun ((name, _) as col) ->
7470       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7471
7472       match col with
7473       | name, FString ->
7474           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7475             n name
7476       | name, FBuffer ->
7477           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7478             n name n name
7479       | name, FUUID ->
7480           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7481             n name
7482       | name, (FBytes|FUInt64) ->
7483           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7484             n name
7485       | name, FInt64 ->
7486           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7487             n name
7488       | name, (FInt32|FUInt32) ->
7489           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7490             n name
7491       | name, FChar ->
7492           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7493             n name
7494       | name, FOptPercent ->
7495           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7496             n name
7497   ) cols;
7498   pr "      free (%s);\n" n
7499
7500 (* Generate Sys/Guestfs.pm. *)
7501 and generate_perl_pm () =
7502   generate_header HashStyle LGPLv2;
7503
7504   pr "\
7505 =pod
7506
7507 =head1 NAME
7508
7509 Sys::Guestfs - Perl bindings for libguestfs
7510
7511 =head1 SYNOPSIS
7512
7513  use Sys::Guestfs;
7514
7515  my $h = Sys::Guestfs->new ();
7516  $h->add_drive ('guest.img');
7517  $h->launch ();
7518  $h->mount ('/dev/sda1', '/');
7519  $h->touch ('/hello');
7520  $h->sync ();
7521
7522 =head1 DESCRIPTION
7523
7524 The C<Sys::Guestfs> module provides a Perl XS binding to the
7525 libguestfs API for examining and modifying virtual machine
7526 disk images.
7527
7528 Amongst the things this is good for: making batch configuration
7529 changes to guests, getting disk used/free statistics (see also:
7530 virt-df), migrating between virtualization systems (see also:
7531 virt-p2v), performing partial backups, performing partial guest
7532 clones, cloning guests and changing registry/UUID/hostname info, and
7533 much else besides.
7534
7535 Libguestfs uses Linux kernel and qemu code, and can access any type of
7536 guest filesystem that Linux and qemu can, including but not limited
7537 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7538 schemes, qcow, qcow2, vmdk.
7539
7540 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7541 LVs, what filesystem is in each LV, etc.).  It can also run commands
7542 in the context of the guest.  Also you can access filesystems over FTP.
7543
7544 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7545 functions for using libguestfs from Perl, including integration
7546 with libvirt.
7547
7548 =head1 ERRORS
7549
7550 All errors turn into calls to C<croak> (see L<Carp(3)>).
7551
7552 =head1 METHODS
7553
7554 =over 4
7555
7556 =cut
7557
7558 package Sys::Guestfs;
7559
7560 use strict;
7561 use warnings;
7562
7563 require XSLoader;
7564 XSLoader::load ('Sys::Guestfs');
7565
7566 =item $h = Sys::Guestfs->new ();
7567
7568 Create a new guestfs handle.
7569
7570 =cut
7571
7572 sub new {
7573   my $proto = shift;
7574   my $class = ref ($proto) || $proto;
7575
7576   my $self = Sys::Guestfs::_create ();
7577   bless $self, $class;
7578   return $self;
7579 }
7580
7581 ";
7582
7583   (* Actions.  We only need to print documentation for these as
7584    * they are pulled in from the XS code automatically.
7585    *)
7586   List.iter (
7587     fun (name, style, _, flags, _, _, longdesc) ->
7588       if not (List.mem NotInDocs flags) then (
7589         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7590         pr "=item ";
7591         generate_perl_prototype name style;
7592         pr "\n\n";
7593         pr "%s\n\n" longdesc;
7594         if List.mem ProtocolLimitWarning flags then
7595           pr "%s\n\n" protocol_limit_warning;
7596         if List.mem DangerWillRobinson flags then
7597           pr "%s\n\n" danger_will_robinson;
7598         match deprecation_notice flags with
7599         | None -> ()
7600         | Some txt -> pr "%s\n\n" txt
7601       )
7602   ) all_functions_sorted;
7603
7604   (* End of file. *)
7605   pr "\
7606 =cut
7607
7608 1;
7609
7610 =back
7611
7612 =head1 COPYRIGHT
7613
7614 Copyright (C) 2009 Red Hat Inc.
7615
7616 =head1 LICENSE
7617
7618 Please see the file COPYING.LIB for the full license.
7619
7620 =head1 SEE ALSO
7621
7622 L<guestfs(3)>,
7623 L<guestfish(1)>,
7624 L<http://libguestfs.org>,
7625 L<Sys::Guestfs::Lib(3)>.
7626
7627 =cut
7628 "
7629
7630 and generate_perl_prototype name style =
7631   (match fst style with
7632    | RErr -> ()
7633    | RBool n
7634    | RInt n
7635    | RInt64 n
7636    | RConstString n
7637    | RConstOptString n
7638    | RString n
7639    | RBufferOut n -> pr "$%s = " n
7640    | RStruct (n,_)
7641    | RHashtable n -> pr "%%%s = " n
7642    | RStringList n
7643    | RStructList (n,_) -> pr "@%s = " n
7644   );
7645   pr "$h->%s (" name;
7646   let comma = ref false in
7647   List.iter (
7648     fun arg ->
7649       if !comma then pr ", ";
7650       comma := true;
7651       match arg with
7652       | Pathname n | Device n | Dev_or_Path n | String n
7653       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7654           pr "$%s" n
7655       | StringList n | DeviceList n ->
7656           pr "\\@%s" n
7657   ) (snd style);
7658   pr ");"
7659
7660 (* Generate Python C module. *)
7661 and generate_python_c () =
7662   generate_header CStyle LGPLv2;
7663
7664   pr "\
7665 #include <Python.h>
7666
7667 #include <stdio.h>
7668 #include <stdlib.h>
7669 #include <assert.h>
7670
7671 #include \"guestfs.h\"
7672
7673 typedef struct {
7674   PyObject_HEAD
7675   guestfs_h *g;
7676 } Pyguestfs_Object;
7677
7678 static guestfs_h *
7679 get_handle (PyObject *obj)
7680 {
7681   assert (obj);
7682   assert (obj != Py_None);
7683   return ((Pyguestfs_Object *) obj)->g;
7684 }
7685
7686 static PyObject *
7687 put_handle (guestfs_h *g)
7688 {
7689   assert (g);
7690   return
7691     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7692 }
7693
7694 /* This list should be freed (but not the strings) after use. */
7695 static char **
7696 get_string_list (PyObject *obj)
7697 {
7698   int i, len;
7699   char **r;
7700
7701   assert (obj);
7702
7703   if (!PyList_Check (obj)) {
7704     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7705     return NULL;
7706   }
7707
7708   len = PyList_Size (obj);
7709   r = malloc (sizeof (char *) * (len+1));
7710   if (r == NULL) {
7711     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7712     return NULL;
7713   }
7714
7715   for (i = 0; i < len; ++i)
7716     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7717   r[len] = NULL;
7718
7719   return r;
7720 }
7721
7722 static PyObject *
7723 put_string_list (char * const * const argv)
7724 {
7725   PyObject *list;
7726   int argc, i;
7727
7728   for (argc = 0; argv[argc] != NULL; ++argc)
7729     ;
7730
7731   list = PyList_New (argc);
7732   for (i = 0; i < argc; ++i)
7733     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7734
7735   return list;
7736 }
7737
7738 static PyObject *
7739 put_table (char * const * const argv)
7740 {
7741   PyObject *list, *item;
7742   int argc, i;
7743
7744   for (argc = 0; argv[argc] != NULL; ++argc)
7745     ;
7746
7747   list = PyList_New (argc >> 1);
7748   for (i = 0; i < argc; i += 2) {
7749     item = PyTuple_New (2);
7750     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7751     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7752     PyList_SetItem (list, i >> 1, item);
7753   }
7754
7755   return list;
7756 }
7757
7758 static void
7759 free_strings (char **argv)
7760 {
7761   int argc;
7762
7763   for (argc = 0; argv[argc] != NULL; ++argc)
7764     free (argv[argc]);
7765   free (argv);
7766 }
7767
7768 static PyObject *
7769 py_guestfs_create (PyObject *self, PyObject *args)
7770 {
7771   guestfs_h *g;
7772
7773   g = guestfs_create ();
7774   if (g == NULL) {
7775     PyErr_SetString (PyExc_RuntimeError,
7776                      \"guestfs.create: failed to allocate handle\");
7777     return NULL;
7778   }
7779   guestfs_set_error_handler (g, NULL, NULL);
7780   return put_handle (g);
7781 }
7782
7783 static PyObject *
7784 py_guestfs_close (PyObject *self, PyObject *args)
7785 {
7786   PyObject *py_g;
7787   guestfs_h *g;
7788
7789   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7790     return NULL;
7791   g = get_handle (py_g);
7792
7793   guestfs_close (g);
7794
7795   Py_INCREF (Py_None);
7796   return Py_None;
7797 }
7798
7799 ";
7800
7801   let emit_put_list_function typ =
7802     pr "static PyObject *\n";
7803     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7804     pr "{\n";
7805     pr "  PyObject *list;\n";
7806     pr "  int i;\n";
7807     pr "\n";
7808     pr "  list = PyList_New (%ss->len);\n" typ;
7809     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7810     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7811     pr "  return list;\n";
7812     pr "};\n";
7813     pr "\n"
7814   in
7815
7816   (* Structures, turned into Python dictionaries. *)
7817   List.iter (
7818     fun (typ, cols) ->
7819       pr "static PyObject *\n";
7820       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7821       pr "{\n";
7822       pr "  PyObject *dict;\n";
7823       pr "\n";
7824       pr "  dict = PyDict_New ();\n";
7825       List.iter (
7826         function
7827         | name, FString ->
7828             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7829             pr "                        PyString_FromString (%s->%s));\n"
7830               typ name
7831         | name, FBuffer ->
7832             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7833             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7834               typ name typ name
7835         | name, FUUID ->
7836             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7837             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7838               typ name
7839         | name, (FBytes|FUInt64) ->
7840             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7841             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7842               typ name
7843         | name, FInt64 ->
7844             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7845             pr "                        PyLong_FromLongLong (%s->%s));\n"
7846               typ name
7847         | name, FUInt32 ->
7848             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7849             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7850               typ name
7851         | name, FInt32 ->
7852             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7853             pr "                        PyLong_FromLong (%s->%s));\n"
7854               typ name
7855         | name, FOptPercent ->
7856             pr "  if (%s->%s >= 0)\n" typ name;
7857             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7858             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7859               typ name;
7860             pr "  else {\n";
7861             pr "    Py_INCREF (Py_None);\n";
7862             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7863             pr "  }\n"
7864         | name, FChar ->
7865             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7866             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7867       ) cols;
7868       pr "  return dict;\n";
7869       pr "};\n";
7870       pr "\n";
7871
7872   ) structs;
7873
7874   (* Emit a put_TYPE_list function definition only if that function is used. *)
7875   List.iter (
7876     function
7877     | typ, (RStructListOnly | RStructAndList) ->
7878         (* generate the function for typ *)
7879         emit_put_list_function typ
7880     | typ, _ -> () (* empty *)
7881   ) (rstructs_used_by all_functions);
7882
7883   (* Python wrapper functions. *)
7884   List.iter (
7885     fun (name, style, _, _, _, _, _) ->
7886       pr "static PyObject *\n";
7887       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7888       pr "{\n";
7889
7890       pr "  PyObject *py_g;\n";
7891       pr "  guestfs_h *g;\n";
7892       pr "  PyObject *py_r;\n";
7893
7894       let error_code =
7895         match fst style with
7896         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7897         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7898         | RConstString _ | RConstOptString _ ->
7899             pr "  const char *r;\n"; "NULL"
7900         | RString _ -> pr "  char *r;\n"; "NULL"
7901         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7902         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7903         | RStructList (_, typ) ->
7904             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7905         | RBufferOut _ ->
7906             pr "  char *r;\n";
7907             pr "  size_t size;\n";
7908             "NULL" in
7909
7910       List.iter (
7911         function
7912         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7913             pr "  const char *%s;\n" n
7914         | OptString n -> pr "  const char *%s;\n" n
7915         | StringList n | DeviceList n ->
7916             pr "  PyObject *py_%s;\n" n;
7917             pr "  char **%s;\n" n
7918         | Bool n -> pr "  int %s;\n" n
7919         | Int n -> pr "  int %s;\n" n
7920       ) (snd style);
7921
7922       pr "\n";
7923
7924       (* Convert the parameters. *)
7925       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7926       List.iter (
7927         function
7928         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7929         | OptString _ -> pr "z"
7930         | StringList _ | DeviceList _ -> pr "O"
7931         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7932         | Int _ -> pr "i"
7933       ) (snd style);
7934       pr ":guestfs_%s\",\n" name;
7935       pr "                         &py_g";
7936       List.iter (
7937         function
7938         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7939         | OptString n -> pr ", &%s" n
7940         | StringList n | DeviceList n -> pr ", &py_%s" n
7941         | Bool n -> pr ", &%s" n
7942         | Int n -> pr ", &%s" n
7943       ) (snd style);
7944
7945       pr "))\n";
7946       pr "    return NULL;\n";
7947
7948       pr "  g = get_handle (py_g);\n";
7949       List.iter (
7950         function
7951         | Pathname _ | Device _ | Dev_or_Path _ | String _
7952         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7953         | StringList n | DeviceList n ->
7954             pr "  %s = get_string_list (py_%s);\n" n n;
7955             pr "  if (!%s) return NULL;\n" n
7956       ) (snd style);
7957
7958       pr "\n";
7959
7960       pr "  r = guestfs_%s " name;
7961       generate_c_call_args ~handle:"g" style;
7962       pr ";\n";
7963
7964       List.iter (
7965         function
7966         | Pathname _ | Device _ | Dev_or_Path _ | String _
7967         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7968         | StringList n | DeviceList n ->
7969             pr "  free (%s);\n" n
7970       ) (snd style);
7971
7972       pr "  if (r == %s) {\n" error_code;
7973       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7974       pr "    return NULL;\n";
7975       pr "  }\n";
7976       pr "\n";
7977
7978       (match fst style with
7979        | RErr ->
7980            pr "  Py_INCREF (Py_None);\n";
7981            pr "  py_r = Py_None;\n"
7982        | RInt _
7983        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7984        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7985        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7986        | RConstOptString _ ->
7987            pr "  if (r)\n";
7988            pr "    py_r = PyString_FromString (r);\n";
7989            pr "  else {\n";
7990            pr "    Py_INCREF (Py_None);\n";
7991            pr "    py_r = Py_None;\n";
7992            pr "  }\n"
7993        | RString _ ->
7994            pr "  py_r = PyString_FromString (r);\n";
7995            pr "  free (r);\n"
7996        | RStringList _ ->
7997            pr "  py_r = put_string_list (r);\n";
7998            pr "  free_strings (r);\n"
7999        | RStruct (_, typ) ->
8000            pr "  py_r = put_%s (r);\n" typ;
8001            pr "  guestfs_free_%s (r);\n" typ
8002        | RStructList (_, typ) ->
8003            pr "  py_r = put_%s_list (r);\n" typ;
8004            pr "  guestfs_free_%s_list (r);\n" typ
8005        | RHashtable n ->
8006            pr "  py_r = put_table (r);\n";
8007            pr "  free_strings (r);\n"
8008        | RBufferOut _ ->
8009            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8010            pr "  free (r);\n"
8011       );
8012
8013       pr "  return py_r;\n";
8014       pr "}\n";
8015       pr "\n"
8016   ) all_functions;
8017
8018   (* Table of functions. *)
8019   pr "static PyMethodDef methods[] = {\n";
8020   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8021   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8022   List.iter (
8023     fun (name, _, _, _, _, _, _) ->
8024       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8025         name name
8026   ) all_functions;
8027   pr "  { NULL, NULL, 0, NULL }\n";
8028   pr "};\n";
8029   pr "\n";
8030
8031   (* Init function. *)
8032   pr "\
8033 void
8034 initlibguestfsmod (void)
8035 {
8036   static int initialized = 0;
8037
8038   if (initialized) return;
8039   Py_InitModule ((char *) \"libguestfsmod\", methods);
8040   initialized = 1;
8041 }
8042 "
8043
8044 (* Generate Python module. *)
8045 and generate_python_py () =
8046   generate_header HashStyle LGPLv2;
8047
8048   pr "\
8049 u\"\"\"Python bindings for libguestfs
8050
8051 import guestfs
8052 g = guestfs.GuestFS ()
8053 g.add_drive (\"guest.img\")
8054 g.launch ()
8055 parts = g.list_partitions ()
8056
8057 The guestfs module provides a Python binding to the libguestfs API
8058 for examining and modifying virtual machine disk images.
8059
8060 Amongst the things this is good for: making batch configuration
8061 changes to guests, getting disk used/free statistics (see also:
8062 virt-df), migrating between virtualization systems (see also:
8063 virt-p2v), performing partial backups, performing partial guest
8064 clones, cloning guests and changing registry/UUID/hostname info, and
8065 much else besides.
8066
8067 Libguestfs uses Linux kernel and qemu code, and can access any type of
8068 guest filesystem that Linux and qemu can, including but not limited
8069 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8070 schemes, qcow, qcow2, vmdk.
8071
8072 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8073 LVs, what filesystem is in each LV, etc.).  It can also run commands
8074 in the context of the guest.  Also you can access filesystems over FTP.
8075
8076 Errors which happen while using the API are turned into Python
8077 RuntimeError exceptions.
8078
8079 To create a guestfs handle you usually have to perform the following
8080 sequence of calls:
8081
8082 # Create the handle, call add_drive at least once, and possibly
8083 # several times if the guest has multiple block devices:
8084 g = guestfs.GuestFS ()
8085 g.add_drive (\"guest.img\")
8086
8087 # Launch the qemu subprocess and wait for it to become ready:
8088 g.launch ()
8089
8090 # Now you can issue commands, for example:
8091 logvols = g.lvs ()
8092
8093 \"\"\"
8094
8095 import libguestfsmod
8096
8097 class GuestFS:
8098     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8099
8100     def __init__ (self):
8101         \"\"\"Create a new libguestfs handle.\"\"\"
8102         self._o = libguestfsmod.create ()
8103
8104     def __del__ (self):
8105         libguestfsmod.close (self._o)
8106
8107 ";
8108
8109   List.iter (
8110     fun (name, style, _, flags, _, _, longdesc) ->
8111       pr "    def %s " name;
8112       generate_py_call_args ~handle:"self" (snd style);
8113       pr ":\n";
8114
8115       if not (List.mem NotInDocs flags) then (
8116         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8117         let doc =
8118           match fst style with
8119           | RErr | RInt _ | RInt64 _ | RBool _
8120           | RConstOptString _ | RConstString _
8121           | RString _ | RBufferOut _ -> doc
8122           | RStringList _ ->
8123               doc ^ "\n\nThis function returns a list of strings."
8124           | RStruct (_, typ) ->
8125               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8126           | RStructList (_, typ) ->
8127               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8128           | RHashtable _ ->
8129               doc ^ "\n\nThis function returns a dictionary." in
8130         let doc =
8131           if List.mem ProtocolLimitWarning flags then
8132             doc ^ "\n\n" ^ protocol_limit_warning
8133           else doc in
8134         let doc =
8135           if List.mem DangerWillRobinson flags then
8136             doc ^ "\n\n" ^ danger_will_robinson
8137           else doc in
8138         let doc =
8139           match deprecation_notice flags with
8140           | None -> doc
8141           | Some txt -> doc ^ "\n\n" ^ txt in
8142         let doc = pod2text ~width:60 name doc in
8143         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8144         let doc = String.concat "\n        " doc in
8145         pr "        u\"\"\"%s\"\"\"\n" doc;
8146       );
8147       pr "        return libguestfsmod.%s " name;
8148       generate_py_call_args ~handle:"self._o" (snd style);
8149       pr "\n";
8150       pr "\n";
8151   ) all_functions
8152
8153 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8154 and generate_py_call_args ~handle args =
8155   pr "(%s" handle;
8156   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8157   pr ")"
8158
8159 (* Useful if you need the longdesc POD text as plain text.  Returns a
8160  * list of lines.
8161  *
8162  * Because this is very slow (the slowest part of autogeneration),
8163  * we memoize the results.
8164  *)
8165 and pod2text ~width name longdesc =
8166   let key = width, name, longdesc in
8167   try Hashtbl.find pod2text_memo key
8168   with Not_found ->
8169     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8170     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8171     close_out chan;
8172     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8173     let chan = Unix.open_process_in cmd in
8174     let lines = ref [] in
8175     let rec loop i =
8176       let line = input_line chan in
8177       if i = 1 then             (* discard the first line of output *)
8178         loop (i+1)
8179       else (
8180         let line = triml line in
8181         lines := line :: !lines;
8182         loop (i+1)
8183       ) in
8184     let lines = try loop 1 with End_of_file -> List.rev !lines in
8185     Unix.unlink filename;
8186     (match Unix.close_process_in chan with
8187      | Unix.WEXITED 0 -> ()
8188      | Unix.WEXITED i ->
8189          failwithf "pod2text: process exited with non-zero status (%d)" i
8190      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8191          failwithf "pod2text: process signalled or stopped by signal %d" i
8192     );
8193     Hashtbl.add pod2text_memo key lines;
8194     pod2text_memo_updated ();
8195     lines
8196
8197 (* Generate ruby bindings. *)
8198 and generate_ruby_c () =
8199   generate_header CStyle LGPLv2;
8200
8201   pr "\
8202 #include <stdio.h>
8203 #include <stdlib.h>
8204
8205 #include <ruby.h>
8206
8207 #include \"guestfs.h\"
8208
8209 #include \"extconf.h\"
8210
8211 /* For Ruby < 1.9 */
8212 #ifndef RARRAY_LEN
8213 #define RARRAY_LEN(r) (RARRAY((r))->len)
8214 #endif
8215
8216 static VALUE m_guestfs;                 /* guestfs module */
8217 static VALUE c_guestfs;                 /* guestfs_h handle */
8218 static VALUE e_Error;                   /* used for all errors */
8219
8220 static void ruby_guestfs_free (void *p)
8221 {
8222   if (!p) return;
8223   guestfs_close ((guestfs_h *) p);
8224 }
8225
8226 static VALUE ruby_guestfs_create (VALUE m)
8227 {
8228   guestfs_h *g;
8229
8230   g = guestfs_create ();
8231   if (!g)
8232     rb_raise (e_Error, \"failed to create guestfs handle\");
8233
8234   /* Don't print error messages to stderr by default. */
8235   guestfs_set_error_handler (g, NULL, NULL);
8236
8237   /* Wrap it, and make sure the close function is called when the
8238    * handle goes away.
8239    */
8240   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8241 }
8242
8243 static VALUE ruby_guestfs_close (VALUE gv)
8244 {
8245   guestfs_h *g;
8246   Data_Get_Struct (gv, guestfs_h, g);
8247
8248   ruby_guestfs_free (g);
8249   DATA_PTR (gv) = NULL;
8250
8251   return Qnil;
8252 }
8253
8254 ";
8255
8256   List.iter (
8257     fun (name, style, _, _, _, _, _) ->
8258       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8259       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8260       pr ")\n";
8261       pr "{\n";
8262       pr "  guestfs_h *g;\n";
8263       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8264       pr "  if (!g)\n";
8265       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8266         name;
8267       pr "\n";
8268
8269       List.iter (
8270         function
8271         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8272             pr "  Check_Type (%sv, T_STRING);\n" n;
8273             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8274             pr "  if (!%s)\n" n;
8275             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8276             pr "              \"%s\", \"%s\");\n" n name
8277         | OptString n ->
8278             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8279         | StringList n | DeviceList n ->
8280             pr "  char **%s;\n" n;
8281             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8282             pr "  {\n";
8283             pr "    int i, len;\n";
8284             pr "    len = RARRAY_LEN (%sv);\n" n;
8285             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8286               n;
8287             pr "    for (i = 0; i < len; ++i) {\n";
8288             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8289             pr "      %s[i] = StringValueCStr (v);\n" n;
8290             pr "    }\n";
8291             pr "    %s[len] = NULL;\n" n;
8292             pr "  }\n";
8293         | Bool n ->
8294             pr "  int %s = RTEST (%sv);\n" n n
8295         | Int n ->
8296             pr "  int %s = NUM2INT (%sv);\n" n n
8297       ) (snd style);
8298       pr "\n";
8299
8300       let error_code =
8301         match fst style with
8302         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8303         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8304         | RConstString _ | RConstOptString _ ->
8305             pr "  const char *r;\n"; "NULL"
8306         | RString _ -> pr "  char *r;\n"; "NULL"
8307         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8308         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8309         | RStructList (_, typ) ->
8310             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8311         | RBufferOut _ ->
8312             pr "  char *r;\n";
8313             pr "  size_t size;\n";
8314             "NULL" in
8315       pr "\n";
8316
8317       pr "  r = guestfs_%s " name;
8318       generate_c_call_args ~handle:"g" style;
8319       pr ";\n";
8320
8321       List.iter (
8322         function
8323         | Pathname _ | Device _ | Dev_or_Path _ | String _
8324         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8325         | StringList n | DeviceList n ->
8326             pr "  free (%s);\n" n
8327       ) (snd style);
8328
8329       pr "  if (r == %s)\n" error_code;
8330       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8331       pr "\n";
8332
8333       (match fst style with
8334        | RErr ->
8335            pr "  return Qnil;\n"
8336        | RInt _ | RBool _ ->
8337            pr "  return INT2NUM (r);\n"
8338        | RInt64 _ ->
8339            pr "  return ULL2NUM (r);\n"
8340        | RConstString _ ->
8341            pr "  return rb_str_new2 (r);\n";
8342        | RConstOptString _ ->
8343            pr "  if (r)\n";
8344            pr "    return rb_str_new2 (r);\n";
8345            pr "  else\n";
8346            pr "    return Qnil;\n";
8347        | RString _ ->
8348            pr "  VALUE rv = rb_str_new2 (r);\n";
8349            pr "  free (r);\n";
8350            pr "  return rv;\n";
8351        | RStringList _ ->
8352            pr "  int i, len = 0;\n";
8353            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8354            pr "  VALUE rv = rb_ary_new2 (len);\n";
8355            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8356            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8357            pr "    free (r[i]);\n";
8358            pr "  }\n";
8359            pr "  free (r);\n";
8360            pr "  return rv;\n"
8361        | RStruct (_, typ) ->
8362            let cols = cols_of_struct typ in
8363            generate_ruby_struct_code typ cols
8364        | RStructList (_, typ) ->
8365            let cols = cols_of_struct typ in
8366            generate_ruby_struct_list_code typ cols
8367        | RHashtable _ ->
8368            pr "  VALUE rv = rb_hash_new ();\n";
8369            pr "  int i;\n";
8370            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8371            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8372            pr "    free (r[i]);\n";
8373            pr "    free (r[i+1]);\n";
8374            pr "  }\n";
8375            pr "  free (r);\n";
8376            pr "  return rv;\n"
8377        | RBufferOut _ ->
8378            pr "  VALUE rv = rb_str_new (r, size);\n";
8379            pr "  free (r);\n";
8380            pr "  return rv;\n";
8381       );
8382
8383       pr "}\n";
8384       pr "\n"
8385   ) all_functions;
8386
8387   pr "\
8388 /* Initialize the module. */
8389 void Init__guestfs ()
8390 {
8391   m_guestfs = rb_define_module (\"Guestfs\");
8392   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8393   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8394
8395   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8396   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8397
8398 ";
8399   (* Define the rest of the methods. *)
8400   List.iter (
8401     fun (name, style, _, _, _, _, _) ->
8402       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8403       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8404   ) all_functions;
8405
8406   pr "}\n"
8407
8408 (* Ruby code to return a struct. *)
8409 and generate_ruby_struct_code typ cols =
8410   pr "  VALUE rv = rb_hash_new ();\n";
8411   List.iter (
8412     function
8413     | name, FString ->
8414         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8415     | name, FBuffer ->
8416         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8417     | name, FUUID ->
8418         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8419     | name, (FBytes|FUInt64) ->
8420         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8421     | name, FInt64 ->
8422         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8423     | name, FUInt32 ->
8424         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8425     | name, FInt32 ->
8426         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8427     | name, FOptPercent ->
8428         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8429     | name, FChar -> (* XXX wrong? *)
8430         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8431   ) cols;
8432   pr "  guestfs_free_%s (r);\n" typ;
8433   pr "  return rv;\n"
8434
8435 (* Ruby code to return a struct list. *)
8436 and generate_ruby_struct_list_code typ cols =
8437   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8438   pr "  int i;\n";
8439   pr "  for (i = 0; i < r->len; ++i) {\n";
8440   pr "    VALUE hv = rb_hash_new ();\n";
8441   List.iter (
8442     function
8443     | name, FString ->
8444         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8445     | name, FBuffer ->
8446         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
8447     | name, FUUID ->
8448         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8449     | name, (FBytes|FUInt64) ->
8450         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8451     | name, FInt64 ->
8452         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8453     | name, FUInt32 ->
8454         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8455     | name, FInt32 ->
8456         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8457     | name, FOptPercent ->
8458         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8459     | name, FChar -> (* XXX wrong? *)
8460         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8461   ) cols;
8462   pr "    rb_ary_push (rv, hv);\n";
8463   pr "  }\n";
8464   pr "  guestfs_free_%s_list (r);\n" typ;
8465   pr "  return rv;\n"
8466
8467 (* Generate Java bindings GuestFS.java file. *)
8468 and generate_java_java () =
8469   generate_header CStyle LGPLv2;
8470
8471   pr "\
8472 package com.redhat.et.libguestfs;
8473
8474 import java.util.HashMap;
8475 import com.redhat.et.libguestfs.LibGuestFSException;
8476 import com.redhat.et.libguestfs.PV;
8477 import com.redhat.et.libguestfs.VG;
8478 import com.redhat.et.libguestfs.LV;
8479 import com.redhat.et.libguestfs.Stat;
8480 import com.redhat.et.libguestfs.StatVFS;
8481 import com.redhat.et.libguestfs.IntBool;
8482 import com.redhat.et.libguestfs.Dirent;
8483
8484 /**
8485  * The GuestFS object is a libguestfs handle.
8486  *
8487  * @author rjones
8488  */
8489 public class GuestFS {
8490   // Load the native code.
8491   static {
8492     System.loadLibrary (\"guestfs_jni\");
8493   }
8494
8495   /**
8496    * The native guestfs_h pointer.
8497    */
8498   long g;
8499
8500   /**
8501    * Create a libguestfs handle.
8502    *
8503    * @throws LibGuestFSException
8504    */
8505   public GuestFS () throws LibGuestFSException
8506   {
8507     g = _create ();
8508   }
8509   private native long _create () throws LibGuestFSException;
8510
8511   /**
8512    * Close a libguestfs handle.
8513    *
8514    * You can also leave handles to be collected by the garbage
8515    * collector, but this method ensures that the resources used
8516    * by the handle are freed up immediately.  If you call any
8517    * other methods after closing the handle, you will get an
8518    * exception.
8519    *
8520    * @throws LibGuestFSException
8521    */
8522   public void close () throws LibGuestFSException
8523   {
8524     if (g != 0)
8525       _close (g);
8526     g = 0;
8527   }
8528   private native void _close (long g) throws LibGuestFSException;
8529
8530   public void finalize () throws LibGuestFSException
8531   {
8532     close ();
8533   }
8534
8535 ";
8536
8537   List.iter (
8538     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8539       if not (List.mem NotInDocs flags); then (
8540         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8541         let doc =
8542           if List.mem ProtocolLimitWarning flags then
8543             doc ^ "\n\n" ^ protocol_limit_warning
8544           else doc in
8545         let doc =
8546           if List.mem DangerWillRobinson flags then
8547             doc ^ "\n\n" ^ danger_will_robinson
8548           else doc in
8549         let doc =
8550           match deprecation_notice flags with
8551           | None -> doc
8552           | Some txt -> doc ^ "\n\n" ^ txt in
8553         let doc = pod2text ~width:60 name doc in
8554         let doc = List.map (            (* RHBZ#501883 *)
8555           function
8556           | "" -> "<p>"
8557           | nonempty -> nonempty
8558         ) doc in
8559         let doc = String.concat "\n   * " doc in
8560
8561         pr "  /**\n";
8562         pr "   * %s\n" shortdesc;
8563         pr "   * <p>\n";
8564         pr "   * %s\n" doc;
8565         pr "   * @throws LibGuestFSException\n";
8566         pr "   */\n";
8567         pr "  ";
8568       );
8569       generate_java_prototype ~public:true ~semicolon:false name style;
8570       pr "\n";
8571       pr "  {\n";
8572       pr "    if (g == 0)\n";
8573       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8574         name;
8575       pr "    ";
8576       if fst style <> RErr then pr "return ";
8577       pr "_%s " name;
8578       generate_java_call_args ~handle:"g" (snd style);
8579       pr ";\n";
8580       pr "  }\n";
8581       pr "  ";
8582       generate_java_prototype ~privat:true ~native:true name style;
8583       pr "\n";
8584       pr "\n";
8585   ) all_functions;
8586
8587   pr "}\n"
8588
8589 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8590 and generate_java_call_args ~handle args =
8591   pr "(%s" handle;
8592   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8593   pr ")"
8594
8595 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8596     ?(semicolon=true) name style =
8597   if privat then pr "private ";
8598   if public then pr "public ";
8599   if native then pr "native ";
8600
8601   (* return type *)
8602   (match fst style with
8603    | RErr -> pr "void ";
8604    | RInt _ -> pr "int ";
8605    | RInt64 _ -> pr "long ";
8606    | RBool _ -> pr "boolean ";
8607    | RConstString _ | RConstOptString _ | RString _
8608    | RBufferOut _ -> pr "String ";
8609    | RStringList _ -> pr "String[] ";
8610    | RStruct (_, typ) ->
8611        let name = java_name_of_struct typ in
8612        pr "%s " name;
8613    | RStructList (_, typ) ->
8614        let name = java_name_of_struct typ in
8615        pr "%s[] " name;
8616    | RHashtable _ -> pr "HashMap<String,String> ";
8617   );
8618
8619   if native then pr "_%s " name else pr "%s " name;
8620   pr "(";
8621   let needs_comma = ref false in
8622   if native then (
8623     pr "long g";
8624     needs_comma := true
8625   );
8626
8627   (* args *)
8628   List.iter (
8629     fun arg ->
8630       if !needs_comma then pr ", ";
8631       needs_comma := true;
8632
8633       match arg with
8634       | Pathname n
8635       | Device n | Dev_or_Path n
8636       | String n
8637       | OptString n
8638       | FileIn n
8639       | FileOut n ->
8640           pr "String %s" n
8641       | StringList n | DeviceList n ->
8642           pr "String[] %s" n
8643       | Bool n ->
8644           pr "boolean %s" n
8645       | Int n ->
8646           pr "int %s" n
8647   ) (snd style);
8648
8649   pr ")\n";
8650   pr "    throws LibGuestFSException";
8651   if semicolon then pr ";"
8652
8653 and generate_java_struct jtyp cols =
8654   generate_header CStyle LGPLv2;
8655
8656   pr "\
8657 package com.redhat.et.libguestfs;
8658
8659 /**
8660  * Libguestfs %s structure.
8661  *
8662  * @author rjones
8663  * @see GuestFS
8664  */
8665 public class %s {
8666 " jtyp jtyp;
8667
8668   List.iter (
8669     function
8670     | name, FString
8671     | name, FUUID
8672     | name, FBuffer -> pr "  public String %s;\n" name
8673     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8674     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8675     | name, FChar -> pr "  public char %s;\n" name
8676     | name, FOptPercent ->
8677         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8678         pr "  public float %s;\n" name
8679   ) cols;
8680
8681   pr "}\n"
8682
8683 and generate_java_c () =
8684   generate_header CStyle LGPLv2;
8685
8686   pr "\
8687 #include <stdio.h>
8688 #include <stdlib.h>
8689 #include <string.h>
8690
8691 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8692 #include \"guestfs.h\"
8693
8694 /* Note that this function returns.  The exception is not thrown
8695  * until after the wrapper function returns.
8696  */
8697 static void
8698 throw_exception (JNIEnv *env, const char *msg)
8699 {
8700   jclass cl;
8701   cl = (*env)->FindClass (env,
8702                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8703   (*env)->ThrowNew (env, cl, msg);
8704 }
8705
8706 JNIEXPORT jlong JNICALL
8707 Java_com_redhat_et_libguestfs_GuestFS__1create
8708   (JNIEnv *env, jobject obj)
8709 {
8710   guestfs_h *g;
8711
8712   g = guestfs_create ();
8713   if (g == NULL) {
8714     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8715     return 0;
8716   }
8717   guestfs_set_error_handler (g, NULL, NULL);
8718   return (jlong) (long) g;
8719 }
8720
8721 JNIEXPORT void JNICALL
8722 Java_com_redhat_et_libguestfs_GuestFS__1close
8723   (JNIEnv *env, jobject obj, jlong jg)
8724 {
8725   guestfs_h *g = (guestfs_h *) (long) jg;
8726   guestfs_close (g);
8727 }
8728
8729 ";
8730
8731   List.iter (
8732     fun (name, style, _, _, _, _, _) ->
8733       pr "JNIEXPORT ";
8734       (match fst style with
8735        | RErr -> pr "void ";
8736        | RInt _ -> pr "jint ";
8737        | RInt64 _ -> pr "jlong ";
8738        | RBool _ -> pr "jboolean ";
8739        | RConstString _ | RConstOptString _ | RString _
8740        | RBufferOut _ -> pr "jstring ";
8741        | RStruct _ | RHashtable _ ->
8742            pr "jobject ";
8743        | RStringList _ | RStructList _ ->
8744            pr "jobjectArray ";
8745       );
8746       pr "JNICALL\n";
8747       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8748       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8749       pr "\n";
8750       pr "  (JNIEnv *env, jobject obj, jlong jg";
8751       List.iter (
8752         function
8753         | Pathname n
8754         | Device n | Dev_or_Path n
8755         | String n
8756         | OptString n
8757         | FileIn n
8758         | FileOut n ->
8759             pr ", jstring j%s" n
8760         | StringList n | DeviceList n ->
8761             pr ", jobjectArray j%s" n
8762         | Bool n ->
8763             pr ", jboolean j%s" n
8764         | Int n ->
8765             pr ", jint j%s" n
8766       ) (snd style);
8767       pr ")\n";
8768       pr "{\n";
8769       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8770       let error_code, no_ret =
8771         match fst style with
8772         | RErr -> pr "  int r;\n"; "-1", ""
8773         | RBool _
8774         | RInt _ -> pr "  int r;\n"; "-1", "0"
8775         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8776         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8777         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8778         | RString _ ->
8779             pr "  jstring jr;\n";
8780             pr "  char *r;\n"; "NULL", "NULL"
8781         | RStringList _ ->
8782             pr "  jobjectArray jr;\n";
8783             pr "  int r_len;\n";
8784             pr "  jclass cl;\n";
8785             pr "  jstring jstr;\n";
8786             pr "  char **r;\n"; "NULL", "NULL"
8787         | RStruct (_, typ) ->
8788             pr "  jobject jr;\n";
8789             pr "  jclass cl;\n";
8790             pr "  jfieldID fl;\n";
8791             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8792         | RStructList (_, typ) ->
8793             pr "  jobjectArray jr;\n";
8794             pr "  jclass cl;\n";
8795             pr "  jfieldID fl;\n";
8796             pr "  jobject jfl;\n";
8797             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8798         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8799         | RBufferOut _ ->
8800             pr "  jstring jr;\n";
8801             pr "  char *r;\n";
8802             pr "  size_t size;\n";
8803             "NULL", "NULL" in
8804       List.iter (
8805         function
8806         | Pathname n
8807         | Device n | Dev_or_Path n
8808         | String n
8809         | OptString n
8810         | FileIn n
8811         | FileOut n ->
8812             pr "  const char *%s;\n" n
8813         | StringList n | DeviceList n ->
8814             pr "  int %s_len;\n" n;
8815             pr "  const char **%s;\n" n
8816         | Bool n
8817         | Int n ->
8818             pr "  int %s;\n" n
8819       ) (snd style);
8820
8821       let needs_i =
8822         (match fst style with
8823          | RStringList _ | RStructList _ -> true
8824          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8825          | RConstOptString _
8826          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8827           List.exists (function
8828                        | StringList _ -> true
8829                        | DeviceList _ -> true
8830                        | _ -> false) (snd style) in
8831       if needs_i then
8832         pr "  int i;\n";
8833
8834       pr "\n";
8835
8836       (* Get the parameters. *)
8837       List.iter (
8838         function
8839         | Pathname n
8840         | Device n | Dev_or_Path n
8841         | String n
8842         | FileIn n
8843         | FileOut n ->
8844             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8845         | OptString n ->
8846             (* This is completely undocumented, but Java null becomes
8847              * a NULL parameter.
8848              *)
8849             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8850         | StringList n | DeviceList n ->
8851             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8852             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8853             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8854             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8855               n;
8856             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8857             pr "  }\n";
8858             pr "  %s[%s_len] = NULL;\n" n n;
8859         | Bool n
8860         | Int n ->
8861             pr "  %s = j%s;\n" n n
8862       ) (snd style);
8863
8864       (* Make the call. *)
8865       pr "  r = guestfs_%s " name;
8866       generate_c_call_args ~handle:"g" style;
8867       pr ";\n";
8868
8869       (* Release the parameters. *)
8870       List.iter (
8871         function
8872         | Pathname n
8873         | Device n | Dev_or_Path n
8874         | String n
8875         | FileIn n
8876         | FileOut n ->
8877             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8878         | OptString n ->
8879             pr "  if (j%s)\n" n;
8880             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8881         | StringList n | DeviceList n ->
8882             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8883             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8884               n;
8885             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8886             pr "  }\n";
8887             pr "  free (%s);\n" n
8888         | Bool n
8889         | Int n -> ()
8890       ) (snd style);
8891
8892       (* Check for errors. *)
8893       pr "  if (r == %s) {\n" error_code;
8894       pr "    throw_exception (env, guestfs_last_error (g));\n";
8895       pr "    return %s;\n" no_ret;
8896       pr "  }\n";
8897
8898       (* Return value. *)
8899       (match fst style with
8900        | RErr -> ()
8901        | RInt _ -> pr "  return (jint) r;\n"
8902        | RBool _ -> pr "  return (jboolean) r;\n"
8903        | RInt64 _ -> pr "  return (jlong) r;\n"
8904        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8905        | RConstOptString _ ->
8906            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8907        | RString _ ->
8908            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8909            pr "  free (r);\n";
8910            pr "  return jr;\n"
8911        | RStringList _ ->
8912            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8913            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8914            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8915            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8916            pr "  for (i = 0; i < r_len; ++i) {\n";
8917            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8918            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8919            pr "    free (r[i]);\n";
8920            pr "  }\n";
8921            pr "  free (r);\n";
8922            pr "  return jr;\n"
8923        | RStruct (_, typ) ->
8924            let jtyp = java_name_of_struct typ in
8925            let cols = cols_of_struct typ in
8926            generate_java_struct_return typ jtyp cols
8927        | RStructList (_, typ) ->
8928            let jtyp = java_name_of_struct typ in
8929            let cols = cols_of_struct typ in
8930            generate_java_struct_list_return typ jtyp cols
8931        | RHashtable _ ->
8932            (* XXX *)
8933            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8934            pr "  return NULL;\n"
8935        | RBufferOut _ ->
8936            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8937            pr "  free (r);\n";
8938            pr "  return jr;\n"
8939       );
8940
8941       pr "}\n";
8942       pr "\n"
8943   ) all_functions
8944
8945 and generate_java_struct_return typ jtyp cols =
8946   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8947   pr "  jr = (*env)->AllocObject (env, cl);\n";
8948   List.iter (
8949     function
8950     | name, FString ->
8951         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8952         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8953     | name, FUUID ->
8954         pr "  {\n";
8955         pr "    char s[33];\n";
8956         pr "    memcpy (s, r->%s, 32);\n" name;
8957         pr "    s[32] = 0;\n";
8958         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8959         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8960         pr "  }\n";
8961     | name, FBuffer ->
8962         pr "  {\n";
8963         pr "    int len = r->%s_len;\n" name;
8964         pr "    char s[len+1];\n";
8965         pr "    memcpy (s, r->%s, len);\n" name;
8966         pr "    s[len] = 0;\n";
8967         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8968         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8969         pr "  }\n";
8970     | name, (FBytes|FUInt64|FInt64) ->
8971         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8972         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8973     | name, (FUInt32|FInt32) ->
8974         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8975         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8976     | name, FOptPercent ->
8977         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8978         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8979     | name, FChar ->
8980         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8981         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8982   ) cols;
8983   pr "  free (r);\n";
8984   pr "  return jr;\n"
8985
8986 and generate_java_struct_list_return typ jtyp cols =
8987   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8988   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8989   pr "  for (i = 0; i < r->len; ++i) {\n";
8990   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8991   List.iter (
8992     function
8993     | name, FString ->
8994         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8995         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8996     | name, FUUID ->
8997         pr "    {\n";
8998         pr "      char s[33];\n";
8999         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9000         pr "      s[32] = 0;\n";
9001         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9002         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9003         pr "    }\n";
9004     | name, FBuffer ->
9005         pr "    {\n";
9006         pr "      int len = r->val[i].%s_len;\n" name;
9007         pr "      char s[len+1];\n";
9008         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9009         pr "      s[len] = 0;\n";
9010         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9011         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9012         pr "    }\n";
9013     | name, (FBytes|FUInt64|FInt64) ->
9014         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9015         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9016     | name, (FUInt32|FInt32) ->
9017         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9018         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9019     | name, FOptPercent ->
9020         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9021         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9022     | name, FChar ->
9023         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9024         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9025   ) cols;
9026   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9027   pr "  }\n";
9028   pr "  guestfs_free_%s_list (r);\n" typ;
9029   pr "  return jr;\n"
9030
9031 and generate_java_makefile_inc () =
9032   generate_header HashStyle GPLv2;
9033
9034   pr "java_built_sources = \\\n";
9035   List.iter (
9036     fun (typ, jtyp) ->
9037         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9038   ) java_structs;
9039   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9040
9041 and generate_haskell_hs () =
9042   generate_header HaskellStyle LGPLv2;
9043
9044   (* XXX We only know how to generate partial FFI for Haskell
9045    * at the moment.  Please help out!
9046    *)
9047   let can_generate style =
9048     match style with
9049     | RErr, _
9050     | RInt _, _
9051     | RInt64 _, _ -> true
9052     | RBool _, _
9053     | RConstString _, _
9054     | RConstOptString _, _
9055     | RString _, _
9056     | RStringList _, _
9057     | RStruct _, _
9058     | RStructList _, _
9059     | RHashtable _, _
9060     | RBufferOut _, _ -> false in
9061
9062   pr "\
9063 {-# INCLUDE <guestfs.h> #-}
9064 {-# LANGUAGE ForeignFunctionInterface #-}
9065
9066 module Guestfs (
9067   create";
9068
9069   (* List out the names of the actions we want to export. *)
9070   List.iter (
9071     fun (name, style, _, _, _, _, _) ->
9072       if can_generate style then pr ",\n  %s" name
9073   ) all_functions;
9074
9075   pr "
9076   ) where
9077 import Foreign
9078 import Foreign.C
9079 import Foreign.C.Types
9080 import IO
9081 import Control.Exception
9082 import Data.Typeable
9083
9084 data GuestfsS = GuestfsS            -- represents the opaque C struct
9085 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9086 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9087
9088 -- XXX define properly later XXX
9089 data PV = PV
9090 data VG = VG
9091 data LV = LV
9092 data IntBool = IntBool
9093 data Stat = Stat
9094 data StatVFS = StatVFS
9095 data Hashtable = Hashtable
9096
9097 foreign import ccall unsafe \"guestfs_create\" c_create
9098   :: IO GuestfsP
9099 foreign import ccall unsafe \"&guestfs_close\" c_close
9100   :: FunPtr (GuestfsP -> IO ())
9101 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9102   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9103
9104 create :: IO GuestfsH
9105 create = do
9106   p <- c_create
9107   c_set_error_handler p nullPtr nullPtr
9108   h <- newForeignPtr c_close p
9109   return h
9110
9111 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9112   :: GuestfsP -> IO CString
9113
9114 -- last_error :: GuestfsH -> IO (Maybe String)
9115 -- last_error h = do
9116 --   str <- withForeignPtr h (\\p -> c_last_error p)
9117 --   maybePeek peekCString str
9118
9119 last_error :: GuestfsH -> IO (String)
9120 last_error h = do
9121   str <- withForeignPtr h (\\p -> c_last_error p)
9122   if (str == nullPtr)
9123     then return \"no error\"
9124     else peekCString str
9125
9126 ";
9127
9128   (* Generate wrappers for each foreign function. *)
9129   List.iter (
9130     fun (name, style, _, _, _, _, _) ->
9131       if can_generate style then (
9132         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9133         pr "  :: ";
9134         generate_haskell_prototype ~handle:"GuestfsP" style;
9135         pr "\n";
9136         pr "\n";
9137         pr "%s :: " name;
9138         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9139         pr "\n";
9140         pr "%s %s = do\n" name
9141           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9142         pr "  r <- ";
9143         (* Convert pointer arguments using with* functions. *)
9144         List.iter (
9145           function
9146           | FileIn n
9147           | FileOut n
9148           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9149           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9150           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9151           | Bool _ | Int _ -> ()
9152         ) (snd style);
9153         (* Convert integer arguments. *)
9154         let args =
9155           List.map (
9156             function
9157             | Bool n -> sprintf "(fromBool %s)" n
9158             | Int n -> sprintf "(fromIntegral %s)" n
9159             | FileIn n | FileOut n
9160             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9161           ) (snd style) in
9162         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9163           (String.concat " " ("p" :: args));
9164         (match fst style with
9165          | RErr | RInt _ | RInt64 _ | RBool _ ->
9166              pr "  if (r == -1)\n";
9167              pr "    then do\n";
9168              pr "      err <- last_error h\n";
9169              pr "      fail err\n";
9170          | RConstString _ | RConstOptString _ | RString _
9171          | RStringList _ | RStruct _
9172          | RStructList _ | RHashtable _ | RBufferOut _ ->
9173              pr "  if (r == nullPtr)\n";
9174              pr "    then do\n";
9175              pr "      err <- last_error h\n";
9176              pr "      fail err\n";
9177         );
9178         (match fst style with
9179          | RErr ->
9180              pr "    else return ()\n"
9181          | RInt _ ->
9182              pr "    else return (fromIntegral r)\n"
9183          | RInt64 _ ->
9184              pr "    else return (fromIntegral r)\n"
9185          | RBool _ ->
9186              pr "    else return (toBool r)\n"
9187          | RConstString _
9188          | RConstOptString _
9189          | RString _
9190          | RStringList _
9191          | RStruct _
9192          | RStructList _
9193          | RHashtable _
9194          | RBufferOut _ ->
9195              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9196         );
9197         pr "\n";
9198       )
9199   ) all_functions
9200
9201 and generate_haskell_prototype ~handle ?(hs = false) style =
9202   pr "%s -> " handle;
9203   let string = if hs then "String" else "CString" in
9204   let int = if hs then "Int" else "CInt" in
9205   let bool = if hs then "Bool" else "CInt" in
9206   let int64 = if hs then "Integer" else "Int64" in
9207   List.iter (
9208     fun arg ->
9209       (match arg with
9210        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9211        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9212        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9213        | Bool _ -> pr "%s" bool
9214        | Int _ -> pr "%s" int
9215        | FileIn _ -> pr "%s" string
9216        | FileOut _ -> pr "%s" string
9217       );
9218       pr " -> ";
9219   ) (snd style);
9220   pr "IO (";
9221   (match fst style with
9222    | RErr -> if not hs then pr "CInt"
9223    | RInt _ -> pr "%s" int
9224    | RInt64 _ -> pr "%s" int64
9225    | RBool _ -> pr "%s" bool
9226    | RConstString _ -> pr "%s" string
9227    | RConstOptString _ -> pr "Maybe %s" string
9228    | RString _ -> pr "%s" string
9229    | RStringList _ -> pr "[%s]" string
9230    | RStruct (_, typ) ->
9231        let name = java_name_of_struct typ in
9232        pr "%s" name
9233    | RStructList (_, typ) ->
9234        let name = java_name_of_struct typ in
9235        pr "[%s]" name
9236    | RHashtable _ -> pr "Hashtable"
9237    | RBufferOut _ -> pr "%s" string
9238   );
9239   pr ")"
9240
9241 and generate_bindtests () =
9242   generate_header CStyle LGPLv2;
9243
9244   pr "\
9245 #include <stdio.h>
9246 #include <stdlib.h>
9247 #include <inttypes.h>
9248 #include <string.h>
9249
9250 #include \"guestfs.h\"
9251 #include \"guestfs-internal-actions.h\"
9252 #include \"guestfs_protocol.h\"
9253
9254 #define error guestfs_error
9255 #define safe_calloc guestfs_safe_calloc
9256 #define safe_malloc guestfs_safe_malloc
9257
9258 static void
9259 print_strings (char *const *argv)
9260 {
9261   int argc;
9262
9263   printf (\"[\");
9264   for (argc = 0; argv[argc] != NULL; ++argc) {
9265     if (argc > 0) printf (\", \");
9266     printf (\"\\\"%%s\\\"\", argv[argc]);
9267   }
9268   printf (\"]\\n\");
9269 }
9270
9271 /* The test0 function prints its parameters to stdout. */
9272 ";
9273
9274   let test0, tests =
9275     match test_functions with
9276     | [] -> assert false
9277     | test0 :: tests -> test0, tests in
9278
9279   let () =
9280     let (name, style, _, _, _, _, _) = test0 in
9281     generate_prototype ~extern:false ~semicolon:false ~newline:true
9282       ~handle:"g" ~prefix:"guestfs__" name style;
9283     pr "{\n";
9284     List.iter (
9285       function
9286       | Pathname n
9287       | Device n | Dev_or_Path n
9288       | String n
9289       | FileIn n
9290       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9291       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9292       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9293       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9294       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9295     ) (snd style);
9296     pr "  /* Java changes stdout line buffering so we need this: */\n";
9297     pr "  fflush (stdout);\n";
9298     pr "  return 0;\n";
9299     pr "}\n";
9300     pr "\n" in
9301
9302   List.iter (
9303     fun (name, style, _, _, _, _, _) ->
9304       if String.sub name (String.length name - 3) 3 <> "err" then (
9305         pr "/* Test normal return. */\n";
9306         generate_prototype ~extern:false ~semicolon:false ~newline:true
9307           ~handle:"g" ~prefix:"guestfs__" name style;
9308         pr "{\n";
9309         (match fst style with
9310          | RErr ->
9311              pr "  return 0;\n"
9312          | RInt _ ->
9313              pr "  int r;\n";
9314              pr "  sscanf (val, \"%%d\", &r);\n";
9315              pr "  return r;\n"
9316          | RInt64 _ ->
9317              pr "  int64_t r;\n";
9318              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9319              pr "  return r;\n"
9320          | RBool _ ->
9321              pr "  return strcmp (val, \"true\") == 0;\n"
9322          | RConstString _
9323          | RConstOptString _ ->
9324              (* Can't return the input string here.  Return a static
9325               * string so we ensure we get a segfault if the caller
9326               * tries to free it.
9327               *)
9328              pr "  return \"static string\";\n"
9329          | RString _ ->
9330              pr "  return strdup (val);\n"
9331          | RStringList _ ->
9332              pr "  char **strs;\n";
9333              pr "  int n, i;\n";
9334              pr "  sscanf (val, \"%%d\", &n);\n";
9335              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9336              pr "  for (i = 0; i < n; ++i) {\n";
9337              pr "    strs[i] = safe_malloc (g, 16);\n";
9338              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9339              pr "  }\n";
9340              pr "  strs[n] = NULL;\n";
9341              pr "  return strs;\n"
9342          | RStruct (_, typ) ->
9343              pr "  struct guestfs_%s *r;\n" typ;
9344              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9345              pr "  return r;\n"
9346          | RStructList (_, typ) ->
9347              pr "  struct guestfs_%s_list *r;\n" typ;
9348              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9349              pr "  sscanf (val, \"%%d\", &r->len);\n";
9350              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9351              pr "  return r;\n"
9352          | RHashtable _ ->
9353              pr "  char **strs;\n";
9354              pr "  int n, i;\n";
9355              pr "  sscanf (val, \"%%d\", &n);\n";
9356              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9357              pr "  for (i = 0; i < n; ++i) {\n";
9358              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9359              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9360              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9361              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9362              pr "  }\n";
9363              pr "  strs[n*2] = NULL;\n";
9364              pr "  return strs;\n"
9365          | RBufferOut _ ->
9366              pr "  return strdup (val);\n"
9367         );
9368         pr "}\n";
9369         pr "\n"
9370       ) else (
9371         pr "/* Test error return. */\n";
9372         generate_prototype ~extern:false ~semicolon:false ~newline:true
9373           ~handle:"g" ~prefix:"guestfs__" name style;
9374         pr "{\n";
9375         pr "  error (g, \"error\");\n";
9376         (match fst style with
9377          | RErr | RInt _ | RInt64 _ | RBool _ ->
9378              pr "  return -1;\n"
9379          | RConstString _ | RConstOptString _
9380          | RString _ | RStringList _ | RStruct _
9381          | RStructList _
9382          | RHashtable _
9383          | RBufferOut _ ->
9384              pr "  return NULL;\n"
9385         );
9386         pr "}\n";
9387         pr "\n"
9388       )
9389   ) tests
9390
9391 and generate_ocaml_bindtests () =
9392   generate_header OCamlStyle GPLv2;
9393
9394   pr "\
9395 let () =
9396   let g = Guestfs.create () in
9397 ";
9398
9399   let mkargs args =
9400     String.concat " " (
9401       List.map (
9402         function
9403         | CallString s -> "\"" ^ s ^ "\""
9404         | CallOptString None -> "None"
9405         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9406         | CallStringList xs ->
9407             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9408         | CallInt i when i >= 0 -> string_of_int i
9409         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9410         | CallBool b -> string_of_bool b
9411       ) args
9412     )
9413   in
9414
9415   generate_lang_bindtests (
9416     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9417   );
9418
9419   pr "print_endline \"EOF\"\n"
9420
9421 and generate_perl_bindtests () =
9422   pr "#!/usr/bin/perl -w\n";
9423   generate_header HashStyle GPLv2;
9424
9425   pr "\
9426 use strict;
9427
9428 use Sys::Guestfs;
9429
9430 my $g = Sys::Guestfs->new ();
9431 ";
9432
9433   let mkargs args =
9434     String.concat ", " (
9435       List.map (
9436         function
9437         | CallString s -> "\"" ^ s ^ "\""
9438         | CallOptString None -> "undef"
9439         | CallOptString (Some s) -> sprintf "\"%s\"" s
9440         | CallStringList xs ->
9441             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9442         | CallInt i -> string_of_int i
9443         | CallBool b -> if b then "1" else "0"
9444       ) args
9445     )
9446   in
9447
9448   generate_lang_bindtests (
9449     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9450   );
9451
9452   pr "print \"EOF\\n\"\n"
9453
9454 and generate_python_bindtests () =
9455   generate_header HashStyle GPLv2;
9456
9457   pr "\
9458 import guestfs
9459
9460 g = guestfs.GuestFS ()
9461 ";
9462
9463   let mkargs args =
9464     String.concat ", " (
9465       List.map (
9466         function
9467         | CallString s -> "\"" ^ s ^ "\""
9468         | CallOptString None -> "None"
9469         | CallOptString (Some s) -> sprintf "\"%s\"" s
9470         | CallStringList xs ->
9471             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9472         | CallInt i -> string_of_int i
9473         | CallBool b -> if b then "1" else "0"
9474       ) args
9475     )
9476   in
9477
9478   generate_lang_bindtests (
9479     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9480   );
9481
9482   pr "print \"EOF\"\n"
9483
9484 and generate_ruby_bindtests () =
9485   generate_header HashStyle GPLv2;
9486
9487   pr "\
9488 require 'guestfs'
9489
9490 g = Guestfs::create()
9491 ";
9492
9493   let mkargs args =
9494     String.concat ", " (
9495       List.map (
9496         function
9497         | CallString s -> "\"" ^ s ^ "\""
9498         | CallOptString None -> "nil"
9499         | CallOptString (Some s) -> sprintf "\"%s\"" s
9500         | CallStringList xs ->
9501             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9502         | CallInt i -> string_of_int i
9503         | CallBool b -> string_of_bool b
9504       ) args
9505     )
9506   in
9507
9508   generate_lang_bindtests (
9509     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9510   );
9511
9512   pr "print \"EOF\\n\"\n"
9513
9514 and generate_java_bindtests () =
9515   generate_header CStyle GPLv2;
9516
9517   pr "\
9518 import com.redhat.et.libguestfs.*;
9519
9520 public class Bindtests {
9521     public static void main (String[] argv)
9522     {
9523         try {
9524             GuestFS g = new GuestFS ();
9525 ";
9526
9527   let mkargs args =
9528     String.concat ", " (
9529       List.map (
9530         function
9531         | CallString s -> "\"" ^ s ^ "\""
9532         | CallOptString None -> "null"
9533         | CallOptString (Some s) -> sprintf "\"%s\"" s
9534         | CallStringList xs ->
9535             "new String[]{" ^
9536               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9537         | CallInt i -> string_of_int i
9538         | CallBool b -> string_of_bool b
9539       ) args
9540     )
9541   in
9542
9543   generate_lang_bindtests (
9544     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9545   );
9546
9547   pr "
9548             System.out.println (\"EOF\");
9549         }
9550         catch (Exception exn) {
9551             System.err.println (exn);
9552             System.exit (1);
9553         }
9554     }
9555 }
9556 "
9557
9558 and generate_haskell_bindtests () =
9559   generate_header HaskellStyle GPLv2;
9560
9561   pr "\
9562 module Bindtests where
9563 import qualified Guestfs
9564
9565 main = do
9566   g <- Guestfs.create
9567 ";
9568
9569   let mkargs args =
9570     String.concat " " (
9571       List.map (
9572         function
9573         | CallString s -> "\"" ^ s ^ "\""
9574         | CallOptString None -> "Nothing"
9575         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9576         | CallStringList xs ->
9577             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9578         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9579         | CallInt i -> string_of_int i
9580         | CallBool true -> "True"
9581         | CallBool false -> "False"
9582       ) args
9583     )
9584   in
9585
9586   generate_lang_bindtests (
9587     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9588   );
9589
9590   pr "  putStrLn \"EOF\"\n"
9591
9592 (* Language-independent bindings tests - we do it this way to
9593  * ensure there is parity in testing bindings across all languages.
9594  *)
9595 and generate_lang_bindtests call =
9596   call "test0" [CallString "abc"; CallOptString (Some "def");
9597                 CallStringList []; CallBool false;
9598                 CallInt 0; CallString "123"; CallString "456"];
9599   call "test0" [CallString "abc"; CallOptString None;
9600                 CallStringList []; CallBool false;
9601                 CallInt 0; CallString "123"; CallString "456"];
9602   call "test0" [CallString ""; CallOptString (Some "def");
9603                 CallStringList []; CallBool false;
9604                 CallInt 0; CallString "123"; CallString "456"];
9605   call "test0" [CallString ""; CallOptString (Some "");
9606                 CallStringList []; CallBool false;
9607                 CallInt 0; CallString "123"; CallString "456"];
9608   call "test0" [CallString "abc"; CallOptString (Some "def");
9609                 CallStringList ["1"]; CallBool false;
9610                 CallInt 0; CallString "123"; CallString "456"];
9611   call "test0" [CallString "abc"; CallOptString (Some "def");
9612                 CallStringList ["1"; "2"]; CallBool false;
9613                 CallInt 0; CallString "123"; CallString "456"];
9614   call "test0" [CallString "abc"; CallOptString (Some "def");
9615                 CallStringList ["1"]; CallBool true;
9616                 CallInt 0; CallString "123"; CallString "456"];
9617   call "test0" [CallString "abc"; CallOptString (Some "def");
9618                 CallStringList ["1"]; CallBool false;
9619                 CallInt (-1); CallString "123"; CallString "456"];
9620   call "test0" [CallString "abc"; CallOptString (Some "def");
9621                 CallStringList ["1"]; CallBool false;
9622                 CallInt (-2); CallString "123"; CallString "456"];
9623   call "test0" [CallString "abc"; CallOptString (Some "def");
9624                 CallStringList ["1"]; CallBool false;
9625                 CallInt 1; CallString "123"; CallString "456"];
9626   call "test0" [CallString "abc"; CallOptString (Some "def");
9627                 CallStringList ["1"]; CallBool false;
9628                 CallInt 2; CallString "123"; CallString "456"];
9629   call "test0" [CallString "abc"; CallOptString (Some "def");
9630                 CallStringList ["1"]; CallBool false;
9631                 CallInt 4095; CallString "123"; CallString "456"];
9632   call "test0" [CallString "abc"; CallOptString (Some "def");
9633                 CallStringList ["1"]; CallBool false;
9634                 CallInt 0; CallString ""; CallString ""]
9635
9636 (* XXX Add here tests of the return and error functions. *)
9637
9638 (* This is used to generate the src/MAX_PROC_NR file which
9639  * contains the maximum procedure number, a surrogate for the
9640  * ABI version number.  See src/Makefile.am for the details.
9641  *)
9642 and generate_max_proc_nr () =
9643   let proc_nrs = List.map (
9644     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9645   ) daemon_functions in
9646
9647   let max_proc_nr = List.fold_left max 0 proc_nrs in
9648
9649   pr "%d\n" max_proc_nr
9650
9651 let output_to filename =
9652   let filename_new = filename ^ ".new" in
9653   chan := open_out filename_new;
9654   let close () =
9655     close_out !chan;
9656     chan := stdout;
9657
9658     (* Is the new file different from the current file? *)
9659     if Sys.file_exists filename && files_equal filename filename_new then
9660       Unix.unlink filename_new          (* same, so skip it *)
9661     else (
9662       (* different, overwrite old one *)
9663       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9664       Unix.rename filename_new filename;
9665       Unix.chmod filename 0o444;
9666       printf "written %s\n%!" filename;
9667     )
9668   in
9669   close
9670
9671 (* Main program. *)
9672 let () =
9673   check_functions ();
9674
9675   if not (Sys.file_exists "HACKING") then (
9676     eprintf "\
9677 You are probably running this from the wrong directory.
9678 Run it from the top source directory using the command
9679   src/generator.ml
9680 ";
9681     exit 1
9682   );
9683
9684   let close = output_to "src/guestfs_protocol.x" in
9685   generate_xdr ();
9686   close ();
9687
9688   let close = output_to "src/guestfs-structs.h" in
9689   generate_structs_h ();
9690   close ();
9691
9692   let close = output_to "src/guestfs-actions.h" in
9693   generate_actions_h ();
9694   close ();
9695
9696   let close = output_to "src/guestfs-internal-actions.h" in
9697   generate_internal_actions_h ();
9698   close ();
9699
9700   let close = output_to "src/guestfs-actions.c" in
9701   generate_client_actions ();
9702   close ();
9703
9704   let close = output_to "daemon/actions.h" in
9705   generate_daemon_actions_h ();
9706   close ();
9707
9708   let close = output_to "daemon/stubs.c" in
9709   generate_daemon_actions ();
9710   close ();
9711
9712   let close = output_to "daemon/names.c" in
9713   generate_daemon_names ();
9714   close ();
9715
9716   let close = output_to "capitests/tests.c" in
9717   generate_tests ();
9718   close ();
9719
9720   let close = output_to "src/guestfs-bindtests.c" in
9721   generate_bindtests ();
9722   close ();
9723
9724   let close = output_to "fish/cmds.c" in
9725   generate_fish_cmds ();
9726   close ();
9727
9728   let close = output_to "fish/completion.c" in
9729   generate_fish_completion ();
9730   close ();
9731
9732   let close = output_to "guestfs-structs.pod" in
9733   generate_structs_pod ();
9734   close ();
9735
9736   let close = output_to "guestfs-actions.pod" in
9737   generate_actions_pod ();
9738   close ();
9739
9740   let close = output_to "guestfish-actions.pod" in
9741   generate_fish_actions_pod ();
9742   close ();
9743
9744   let close = output_to "ocaml/guestfs.mli" in
9745   generate_ocaml_mli ();
9746   close ();
9747
9748   let close = output_to "ocaml/guestfs.ml" in
9749   generate_ocaml_ml ();
9750   close ();
9751
9752   let close = output_to "ocaml/guestfs_c_actions.c" in
9753   generate_ocaml_c ();
9754   close ();
9755
9756   let close = output_to "ocaml/bindtests.ml" in
9757   generate_ocaml_bindtests ();
9758   close ();
9759
9760   let close = output_to "perl/Guestfs.xs" in
9761   generate_perl_xs ();
9762   close ();
9763
9764   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9765   generate_perl_pm ();
9766   close ();
9767
9768   let close = output_to "perl/bindtests.pl" in
9769   generate_perl_bindtests ();
9770   close ();
9771
9772   let close = output_to "python/guestfs-py.c" in
9773   generate_python_c ();
9774   close ();
9775
9776   let close = output_to "python/guestfs.py" in
9777   generate_python_py ();
9778   close ();
9779
9780   let close = output_to "python/bindtests.py" in
9781   generate_python_bindtests ();
9782   close ();
9783
9784   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9785   generate_ruby_c ();
9786   close ();
9787
9788   let close = output_to "ruby/bindtests.rb" in
9789   generate_ruby_bindtests ();
9790   close ();
9791
9792   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9793   generate_java_java ();
9794   close ();
9795
9796   List.iter (
9797     fun (typ, jtyp) ->
9798       let cols = cols_of_struct typ in
9799       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9800       let close = output_to filename in
9801       generate_java_struct jtyp cols;
9802       close ();
9803   ) java_structs;
9804
9805   let close = output_to "java/Makefile.inc" in
9806   generate_java_makefile_inc ();
9807   close ();
9808
9809   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9810   generate_java_c ();
9811   close ();
9812
9813   let close = output_to "java/Bindtests.java" in
9814   generate_java_bindtests ();
9815   close ();
9816
9817   let close = output_to "haskell/Guestfs.hs" in
9818   generate_haskell_hs ();
9819   close ();
9820
9821   let close = output_to "haskell/Bindtests.hs" in
9822   generate_haskell_bindtests ();
9823   close ();
9824
9825   let close = output_to "src/MAX_PROC_NR" in
9826   generate_max_proc_nr ();
9827   close ();
9828
9829   (* Always generate this file last, and unconditionally.  It's used
9830    * by the Makefile to know when we must re-run the generator.
9831    *)
9832   let chan = open_out "src/stamp-generator" in
9833   fprintf chan "1\n";
9834   close_out chan