Add a build test for the 'umask' command.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 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 of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -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 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM logical volume",
1477    "\
1478 This creates an LVM logical volume called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2029
2030   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031    [],
2032    "pack directory into tarfile",
2033    "\
2034 This command packs the contents of C<directory> and downloads
2035 it to local file C<tarfile>.
2036
2037 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038
2039   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2040    [InitBasicFS, Always, TestOutput (
2041       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2042        ["cat"; "/hello"]], "hello\n")],
2043    "unpack compressed tarball to directory",
2044    "\
2045 This command uploads and unpacks local file C<tarball> (a
2046 I<gzip compressed> tar file) into C<directory>.
2047
2048 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049
2050   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051    [],
2052    "pack directory into compressed tarball",
2053    "\
2054 This command packs the contents of C<directory> and downloads
2055 it to local file C<tarball>.
2056
2057 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058
2059   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2060    [InitBasicFS, Always, TestLastFail (
2061       [["umount"; "/"];
2062        ["mount_ro"; "/dev/sda1"; "/"];
2063        ["touch"; "/new"]]);
2064     InitBasicFS, Always, TestOutput (
2065       [["write_file"; "/new"; "data"; "0"];
2066        ["umount"; "/"];
2067        ["mount_ro"; "/dev/sda1"; "/"];
2068        ["cat"; "/new"]], "data")],
2069    "mount a guest disk, read-only",
2070    "\
2071 This is the same as the C<guestfs_mount> command, but it
2072 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073
2074   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075    [],
2076    "mount a guest disk with mount options",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 allows you to set the mount options as for the
2080 L<mount(8)> I<-o> flag.");
2081
2082   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083    [],
2084    "mount a guest disk with mount options and vfstype",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set both the mount options and the vfstype
2088 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089
2090   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091    [],
2092    "debugging and internals",
2093    "\
2094 The C<guestfs_debug> command exposes some internals of
2095 C<guestfsd> (the guestfs daemon) that runs inside the
2096 qemu subprocess.
2097
2098 There is no comprehensive help for this command.  You have
2099 to look at the file C<daemon/debug.c> in the libguestfs source
2100 to find out what you can do.");
2101
2102   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2103    [InitEmpty, Always, TestOutputList (
2104       [["part_disk"; "/dev/sda"; "mbr"];
2105        ["pvcreate"; "/dev/sda1"];
2106        ["vgcreate"; "VG"; "/dev/sda1"];
2107        ["lvcreate"; "LV1"; "VG"; "50"];
2108        ["lvcreate"; "LV2"; "VG"; "50"];
2109        ["lvremove"; "/dev/VG/LV1"];
2110        ["lvs"]], ["/dev/VG/LV2"]);
2111     InitEmpty, Always, TestOutputList (
2112       [["part_disk"; "/dev/sda"; "mbr"];
2113        ["pvcreate"; "/dev/sda1"];
2114        ["vgcreate"; "VG"; "/dev/sda1"];
2115        ["lvcreate"; "LV1"; "VG"; "50"];
2116        ["lvcreate"; "LV2"; "VG"; "50"];
2117        ["lvremove"; "/dev/VG"];
2118        ["lvs"]], []);
2119     InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG"];
2126        ["vgs"]], ["VG"])],
2127    "remove an LVM logical volume",
2128    "\
2129 Remove an LVM logical volume C<device>, where C<device> is
2130 the path to the LV, such as C</dev/VG/LV>.
2131
2132 You can also remove all LVs in a volume group by specifying
2133 the VG name, C</dev/VG>.");
2134
2135   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2136    [InitEmpty, Always, TestOutputList (
2137       [["part_disk"; "/dev/sda"; "mbr"];
2138        ["pvcreate"; "/dev/sda1"];
2139        ["vgcreate"; "VG"; "/dev/sda1"];
2140        ["lvcreate"; "LV1"; "VG"; "50"];
2141        ["lvcreate"; "LV2"; "VG"; "50"];
2142        ["vgremove"; "VG"];
2143        ["lvs"]], []);
2144     InitEmpty, Always, TestOutputList (
2145       [["part_disk"; "/dev/sda"; "mbr"];
2146        ["pvcreate"; "/dev/sda1"];
2147        ["vgcreate"; "VG"; "/dev/sda1"];
2148        ["lvcreate"; "LV1"; "VG"; "50"];
2149        ["lvcreate"; "LV2"; "VG"; "50"];
2150        ["vgremove"; "VG"];
2151        ["vgs"]], [])],
2152    "remove an LVM volume group",
2153    "\
2154 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155
2156 This also forcibly removes all logical volumes in the volume
2157 group (if any).");
2158
2159   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2160    [InitEmpty, Always, TestOutputListOfDevices (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["pvremove"; "/dev/sda1"];
2168        ["lvs"]], []);
2169     InitEmpty, Always, TestOutputListOfDevices (
2170       [["part_disk"; "/dev/sda"; "mbr"];
2171        ["pvcreate"; "/dev/sda1"];
2172        ["vgcreate"; "VG"; "/dev/sda1"];
2173        ["lvcreate"; "LV1"; "VG"; "50"];
2174        ["lvcreate"; "LV2"; "VG"; "50"];
2175        ["vgremove"; "VG"];
2176        ["pvremove"; "/dev/sda1"];
2177        ["vgs"]], []);
2178     InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["pvs"]], [])],
2187    "remove an LVM physical volume",
2188    "\
2189 This wipes a physical volume C<device> so that LVM will no longer
2190 recognise it.
2191
2192 The implementation uses the C<pvremove> command which refuses to
2193 wipe physical volumes that contain any volume groups, so you have
2194 to remove those first.");
2195
2196   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2197    [InitBasicFS, Always, TestOutput (
2198       [["set_e2label"; "/dev/sda1"; "testlabel"];
2199        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2200    "set the ext2/3/4 filesystem label",
2201    "\
2202 This sets the ext2/3/4 filesystem label of the filesystem on
2203 C<device> to C<label>.  Filesystem labels are limited to
2204 16 characters.
2205
2206 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2207 to return the existing label on a filesystem.");
2208
2209   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210    [],
2211    "get the ext2/3/4 filesystem label",
2212    "\
2213 This returns the ext2/3/4 filesystem label of the filesystem on
2214 C<device>.");
2215
2216   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2217    (let uuid = uuidgen () in
2218     [InitBasicFS, Always, TestOutput (
2219        [["set_e2uuid"; "/dev/sda1"; uuid];
2220         ["get_e2uuid"; "/dev/sda1"]], uuid);
2221      InitBasicFS, Always, TestOutput (
2222        [["set_e2uuid"; "/dev/sda1"; "clear"];
2223         ["get_e2uuid"; "/dev/sda1"]], "");
2224      (* We can't predict what UUIDs will be, so just check the commands run. *)
2225      InitBasicFS, Always, TestRun (
2226        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2229    "set the ext2/3/4 filesystem UUID",
2230    "\
2231 This sets the ext2/3/4 filesystem UUID of the filesystem on
2232 C<device> to C<uuid>.  The format of the UUID and alternatives
2233 such as C<clear>, C<random> and C<time> are described in the
2234 L<tune2fs(8)> manpage.
2235
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2237 to return the existing UUID of a filesystem.");
2238
2239   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240    [],
2241    "get the ext2/3/4 filesystem UUID",
2242    "\
2243 This returns the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device>.");
2245
2246   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2247    [InitBasicFS, Always, TestOutputInt (
2248       [["umount"; "/dev/sda1"];
2249        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2250     InitBasicFS, Always, TestOutputInt (
2251       [["umount"; "/dev/sda1"];
2252        ["zero"; "/dev/sda1"];
2253        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2254    "run the filesystem checker",
2255    "\
2256 This runs the filesystem checker (fsck) on C<device> which
2257 should have filesystem type C<fstype>.
2258
2259 The returned integer is the status.  See L<fsck(8)> for the
2260 list of status codes from C<fsck>.
2261
2262 Notes:
2263
2264 =over 4
2265
2266 =item *
2267
2268 Multiple status codes can be summed together.
2269
2270 =item *
2271
2272 A non-zero return code can mean \"success\", for example if
2273 errors have been corrected on the filesystem.
2274
2275 =item *
2276
2277 Checking or repairing NTFS volumes is not supported
2278 (by linux-ntfs).
2279
2280 =back
2281
2282 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283
2284   ("zero", (RErr, [Device "device"]), 85, [],
2285    [InitBasicFS, Always, TestOutput (
2286       [["umount"; "/dev/sda1"];
2287        ["zero"; "/dev/sda1"];
2288        ["file"; "/dev/sda1"]], "data")],
2289    "write zeroes to the device",
2290    "\
2291 This command writes zeroes over the first few blocks of C<device>.
2292
2293 How many blocks are zeroed isn't specified (but it's I<not> enough
2294 to securely wipe the device).  It should be sufficient to remove
2295 any partition tables, filesystem superblocks and so on.
2296
2297 See also: C<guestfs_scrub_device>.");
2298
2299   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2300    (* Test disabled because grub-install incompatible with virtio-blk driver.
2301     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302     *)
2303    [InitBasicFS, Disabled, TestOutputTrue (
2304       [["grub_install"; "/"; "/dev/sda1"];
2305        ["is_dir"; "/boot"]])],
2306    "install GRUB",
2307    "\
2308 This command installs GRUB (the Grand Unified Bootloader) on
2309 C<device>, with the root directory being C<root>.");
2310
2311   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2312    [InitBasicFS, Always, TestOutput (
2313       [["write_file"; "/old"; "file content"; "0"];
2314        ["cp"; "/old"; "/new"];
2315        ["cat"; "/new"]], "file content");
2316     InitBasicFS, Always, TestOutputTrue (
2317       [["write_file"; "/old"; "file content"; "0"];
2318        ["cp"; "/old"; "/new"];
2319        ["is_file"; "/old"]]);
2320     InitBasicFS, Always, TestOutput (
2321       [["write_file"; "/old"; "file content"; "0"];
2322        ["mkdir"; "/dir"];
2323        ["cp"; "/old"; "/dir/new"];
2324        ["cat"; "/dir/new"]], "file content")],
2325    "copy a file",
2326    "\
2327 This copies a file from C<src> to C<dest> where C<dest> is
2328 either a destination filename or destination directory.");
2329
2330   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2331    [InitBasicFS, Always, TestOutput (
2332       [["mkdir"; "/olddir"];
2333        ["mkdir"; "/newdir"];
2334        ["write_file"; "/olddir/file"; "file content"; "0"];
2335        ["cp_a"; "/olddir"; "/newdir"];
2336        ["cat"; "/newdir/olddir/file"]], "file content")],
2337    "copy a file or directory recursively",
2338    "\
2339 This copies a file or directory from C<src> to C<dest>
2340 recursively using the C<cp -a> command.");
2341
2342   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["mv"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputFalse (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["mv"; "/old"; "/new"];
2350        ["is_file"; "/old"]])],
2351    "move a file",
2352    "\
2353 This moves a file from C<src> to C<dest> where C<dest> is
2354 either a destination filename or destination directory.");
2355
2356   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2357    [InitEmpty, Always, TestRun (
2358       [["drop_caches"; "3"]])],
2359    "drop kernel page cache, dentries and inodes",
2360    "\
2361 This instructs the guest kernel to drop its page cache,
2362 and/or dentries and inode caches.  The parameter C<whattodrop>
2363 tells the kernel what precisely to drop, see
2364 L<http://linux-mm.org/Drop_Caches>
2365
2366 Setting C<whattodrop> to 3 should drop everything.
2367
2368 This automatically calls L<sync(2)> before the operation,
2369 so that the maximum guest memory is freed.");
2370
2371   ("dmesg", (RString "kmsgs", []), 91, [],
2372    [InitEmpty, Always, TestRun (
2373       [["dmesg"]])],
2374    "return kernel messages",
2375    "\
2376 This returns the kernel messages (C<dmesg> output) from
2377 the guest kernel.  This is sometimes useful for extended
2378 debugging of problems.
2379
2380 Another way to get the same information is to enable
2381 verbose messages with C<guestfs_set_verbose> or by setting
2382 the environment variable C<LIBGUESTFS_DEBUG=1> before
2383 running the program.");
2384
2385   ("ping_daemon", (RErr, []), 92, [],
2386    [InitEmpty, Always, TestRun (
2387       [["ping_daemon"]])],
2388    "ping the guest daemon",
2389    "\
2390 This is a test probe into the guestfs daemon running inside
2391 the qemu subprocess.  Calling this function checks that the
2392 daemon responds to the ping message, without affecting the daemon
2393 or attached block device(s) in any other way.");
2394
2395   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2396    [InitBasicFS, Always, TestOutputTrue (
2397       [["write_file"; "/file1"; "contents of a file"; "0"];
2398        ["cp"; "/file1"; "/file2"];
2399        ["equal"; "/file1"; "/file2"]]);
2400     InitBasicFS, Always, TestOutputFalse (
2401       [["write_file"; "/file1"; "contents of a file"; "0"];
2402        ["write_file"; "/file2"; "contents of another file"; "0"];
2403        ["equal"; "/file1"; "/file2"]]);
2404     InitBasicFS, Always, TestLastFail (
2405       [["equal"; "/file1"; "/file2"]])],
2406    "test if two files have equal contents",
2407    "\
2408 This compares the two files C<file1> and C<file2> and returns
2409 true if their content is exactly equal, or false otherwise.
2410
2411 The external L<cmp(1)> program is used for the comparison.");
2412
2413   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2414    [InitISOFS, Always, TestOutputList (
2415       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2416     InitISOFS, Always, TestOutputList (
2417       [["strings"; "/empty"]], [])],
2418    "print the printable strings in a file",
2419    "\
2420 This runs the L<strings(1)> command on a file and returns
2421 the list of printable strings found.");
2422
2423   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2424    [InitISOFS, Always, TestOutputList (
2425       [["strings_e"; "b"; "/known-5"]], []);
2426     InitBasicFS, Disabled, TestOutputList (
2427       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2428        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2429    "print the printable strings in a file",
2430    "\
2431 This is like the C<guestfs_strings> command, but allows you to
2432 specify the encoding.
2433
2434 See the L<strings(1)> manpage for the full list of encodings.
2435
2436 Commonly useful encodings are C<l> (lower case L) which will
2437 show strings inside Windows/x86 files.
2438
2439 The returned strings are transcoded to UTF-8.");
2440
2441   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutput (
2443       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2444     (* Test for RHBZ#501888c2 regression which caused large hexdump
2445      * commands to segfault.
2446      *)
2447     InitISOFS, Always, TestRun (
2448       [["hexdump"; "/100krandom"]])],
2449    "dump a file in hexadecimal",
2450    "\
2451 This runs C<hexdump -C> on the given C<path>.  The result is
2452 the human-readable, canonical hex dump of the file.");
2453
2454   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2455    [InitNone, Always, TestOutput (
2456       [["part_disk"; "/dev/sda"; "mbr"];
2457        ["mkfs"; "ext3"; "/dev/sda1"];
2458        ["mount_options"; ""; "/dev/sda1"; "/"];
2459        ["write_file"; "/new"; "test file"; "0"];
2460        ["umount"; "/dev/sda1"];
2461        ["zerofree"; "/dev/sda1"];
2462        ["mount_options"; ""; "/dev/sda1"; "/"];
2463        ["cat"; "/new"]], "test file")],
2464    "zero unused inodes and disk blocks on ext2/3 filesystem",
2465    "\
2466 This runs the I<zerofree> program on C<device>.  This program
2467 claims to zero unused inodes and disk blocks on an ext2/3
2468 filesystem, thus making it possible to compress the filesystem
2469 more effectively.
2470
2471 You should B<not> run this program if the filesystem is
2472 mounted.
2473
2474 It is possible that using this program can damage the filesystem
2475 or data on the filesystem.");
2476
2477   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478    [],
2479    "resize an LVM physical volume",
2480    "\
2481 This resizes (expands or shrinks) an existing LVM physical
2482 volume to match the new size of the underlying device.");
2483
2484   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2485                        Int "cyls"; Int "heads"; Int "sectors";
2486                        String "line"]), 99, [DangerWillRobinson],
2487    [],
2488    "modify a single partition on a block device",
2489    "\
2490 This runs L<sfdisk(8)> option to modify just the single
2491 partition C<n> (note: C<n> counts from 1).
2492
2493 For other parameters, see C<guestfs_sfdisk>.  You should usually
2494 pass C<0> for the cyls/heads/sectors parameters.
2495
2496 See also: C<guestfs_part_add>");
2497
2498   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499    [],
2500    "display the partition table",
2501    "\
2502 This displays the partition table on C<device>, in the
2503 human-readable output of the L<sfdisk(8)> command.  It is
2504 not intended to be parsed.
2505
2506 See also: C<guestfs_part_list>");
2507
2508   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509    [],
2510    "display the kernel geometry",
2511    "\
2512 This displays the kernel's idea of the geometry of C<device>.
2513
2514 The result is in human-readable format, and not designed to
2515 be parsed.");
2516
2517   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518    [],
2519    "display the disk geometry from the partition table",
2520    "\
2521 This displays the disk geometry of C<device> read from the
2522 partition table.  Especially in the case where the underlying
2523 block device has been resized, this can be different from the
2524 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530    [],
2531    "activate or deactivate all volume groups",
2532    "\
2533 This command activates or (if C<activate> is false) deactivates
2534 all logical volumes in all volume groups.
2535 If activated, then they are made known to the
2536 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2537 then those devices disappear.
2538
2539 This command is the same as running C<vgchange -a y|n>");
2540
2541   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate some volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in the listed volume groups C<volgroups>.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n volgroups...>
2552
2553 Note that if C<volgroups> is an empty list then B<all> volume groups
2554 are activated or deactivated.");
2555
2556   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2557    [InitNone, Always, TestOutput (
2558       [["part_disk"; "/dev/sda"; "mbr"];
2559        ["pvcreate"; "/dev/sda1"];
2560        ["vgcreate"; "VG"; "/dev/sda1"];
2561        ["lvcreate"; "LV"; "VG"; "10"];
2562        ["mkfs"; "ext2"; "/dev/VG/LV"];
2563        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2564        ["write_file"; "/new"; "test content"; "0"];
2565        ["umount"; "/"];
2566        ["lvresize"; "/dev/VG/LV"; "20"];
2567        ["e2fsck_f"; "/dev/VG/LV"];
2568        ["resize2fs"; "/dev/VG/LV"];
2569        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2570        ["cat"; "/new"]], "test content")],
2571    "resize an LVM logical volume",
2572    "\
2573 This resizes (expands or shrinks) an existing LVM logical
2574 volume to C<mbytes>.  When reducing, data in the reduced part
2575 is lost.");
2576
2577   ("resize2fs", (RErr, [Device "device"]), 106, [],
2578    [], (* lvresize tests this *)
2579    "resize an ext2/ext3 filesystem",
2580    "\
2581 This resizes an ext2 or ext3 filesystem to match the size of
2582 the underlying device.
2583
2584 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2585 on the C<device> before calling this command.  For unknown reasons
2586 C<resize2fs> sometimes gives an error about this and sometimes not.
2587 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2588 calling this function.");
2589
2590   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2591    [InitBasicFS, Always, TestOutputList (
2592       [["find"; "/"]], ["lost+found"]);
2593     InitBasicFS, Always, TestOutputList (
2594       [["touch"; "/a"];
2595        ["mkdir"; "/b"];
2596        ["touch"; "/b/c"];
2597        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2598     InitBasicFS, Always, TestOutputList (
2599       [["mkdir_p"; "/a/b/c"];
2600        ["touch"; "/a/b/c/d"];
2601        ["find"; "/a/b/"]], ["c"; "c/d"])],
2602    "find all files and directories",
2603    "\
2604 This command lists out all files and directories, recursively,
2605 starting at C<directory>.  It is essentially equivalent to
2606 running the shell command C<find directory -print> but some
2607 post-processing happens on the output, described below.
2608
2609 This returns a list of strings I<without any prefix>.  Thus
2610 if the directory structure was:
2611
2612  /tmp/a
2613  /tmp/b
2614  /tmp/c/d
2615
2616 then the returned list from C<guestfs_find> C</tmp> would be
2617 4 elements:
2618
2619  a
2620  b
2621  c
2622  c/d
2623
2624 If C<directory> is not a directory, then this command returns
2625 an error.
2626
2627 The returned list is sorted.
2628
2629 See also C<guestfs_find0>.");
2630
2631   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2632    [], (* lvresize tests this *)
2633    "check an ext2/ext3 filesystem",
2634    "\
2635 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2636 filesystem checker on C<device>, noninteractively (C<-p>),
2637 even if the filesystem appears to be clean (C<-f>).
2638
2639 This command is only needed because of C<guestfs_resize2fs>
2640 (q.v.).  Normally you should use C<guestfs_fsck>.");
2641
2642   ("sleep", (RErr, [Int "secs"]), 109, [],
2643    [InitNone, Always, TestRun (
2644       [["sleep"; "1"]])],
2645    "sleep for some seconds",
2646    "\
2647 Sleep for C<secs> seconds.");
2648
2649   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2650    [InitNone, Always, TestOutputInt (
2651       [["part_disk"; "/dev/sda"; "mbr"];
2652        ["mkfs"; "ntfs"; "/dev/sda1"];
2653        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2654     InitNone, Always, TestOutputInt (
2655       [["part_disk"; "/dev/sda"; "mbr"];
2656        ["mkfs"; "ext2"; "/dev/sda1"];
2657        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2658    "probe NTFS volume",
2659    "\
2660 This command runs the L<ntfs-3g.probe(8)> command which probes
2661 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2662 be mounted read-write, and some cannot be mounted at all).
2663
2664 C<rw> is a boolean flag.  Set it to true if you want to test
2665 if the volume can be mounted read-write.  Set it to false if
2666 you want to test if the volume can be mounted read-only.
2667
2668 The return value is an integer which C<0> if the operation
2669 would succeed, or some non-zero value documented in the
2670 L<ntfs-3g.probe(8)> manual page.");
2671
2672   ("sh", (RString "output", [String "command"]), 111, [],
2673    [], (* XXX needs tests *)
2674    "run a command via the shell",
2675    "\
2676 This call runs a command from the guest filesystem via the
2677 guest's C</bin/sh>.
2678
2679 This is like C<guestfs_command>, but passes the command to:
2680
2681  /bin/sh -c \"command\"
2682
2683 Depending on the guest's shell, this usually results in
2684 wildcards being expanded, shell expressions being interpolated
2685 and so on.
2686
2687 All the provisos about C<guestfs_command> apply to this call.");
2688
2689   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2690    [], (* XXX needs tests *)
2691    "run a command via the shell returning lines",
2692    "\
2693 This is the same as C<guestfs_sh>, but splits the result
2694 into a list of lines.
2695
2696 See also: C<guestfs_command_lines>");
2697
2698   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2699    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2700     * code in stubs.c, since all valid glob patterns must start with "/".
2701     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702     *)
2703    [InitBasicFS, Always, TestOutputList (
2704       [["mkdir_p"; "/a/b/c"];
2705        ["touch"; "/a/b/c/d"];
2706        ["touch"; "/a/b/c/e"];
2707        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2708     InitBasicFS, Always, TestOutputList (
2709       [["mkdir_p"; "/a/b/c"];
2710        ["touch"; "/a/b/c/d"];
2711        ["touch"; "/a/b/c/e"];
2712        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2713     InitBasicFS, Always, TestOutputList (
2714       [["mkdir_p"; "/a/b/c"];
2715        ["touch"; "/a/b/c/d"];
2716        ["touch"; "/a/b/c/e"];
2717        ["glob_expand"; "/a/*/x/*"]], [])],
2718    "expand a wildcard path",
2719    "\
2720 This command searches for all the pathnames matching
2721 C<pattern> according to the wildcard expansion rules
2722 used by the shell.
2723
2724 If no paths match, then this returns an empty list
2725 (note: not an error).
2726
2727 It is just a wrapper around the C L<glob(3)> function
2728 with flags C<GLOB_MARK|GLOB_BRACE>.
2729 See that manual page for more details.");
2730
2731   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2732    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2733       [["scrub_device"; "/dev/sdc"]])],
2734    "scrub (securely wipe) a device",
2735    "\
2736 This command writes patterns over C<device> to make data retrieval
2737 more difficult.
2738
2739 It is an interface to the L<scrub(1)> program.  See that
2740 manual page for more details.");
2741
2742   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2743    [InitBasicFS, Always, TestRun (
2744       [["write_file"; "/file"; "content"; "0"];
2745        ["scrub_file"; "/file"]])],
2746    "scrub (securely wipe) a file",
2747    "\
2748 This command writes patterns over a file to make data retrieval
2749 more difficult.
2750
2751 The file is I<removed> after scrubbing.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2757    [], (* XXX needs testing *)
2758    "scrub (securely wipe) free space",
2759    "\
2760 This command creates the directory C<dir> and then fills it
2761 with files until the filesystem is full, and scrubs the files
2762 as for C<guestfs_scrub_file>, and deletes them.
2763 The intention is to scrub any free space on the partition
2764 containing C<dir>.
2765
2766 It is an interface to the L<scrub(1)> program.  See that
2767 manual page for more details.");
2768
2769   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2770    [InitBasicFS, Always, TestRun (
2771       [["mkdir"; "/tmp"];
2772        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2773    "create a temporary directory",
2774    "\
2775 This command creates a temporary directory.  The
2776 C<template> parameter should be a full pathname for the
2777 temporary directory name with the final six characters being
2778 \"XXXXXX\".
2779
2780 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2781 the second one being suitable for Windows filesystems.
2782
2783 The name of the temporary directory that was created
2784 is returned.
2785
2786 The temporary directory is created with mode 0700
2787 and is owned by root.
2788
2789 The caller is responsible for deleting the temporary
2790 directory and its contents after use.
2791
2792 See also: L<mkdtemp(3)>");
2793
2794   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["wc_l"; "/10klines"]], 10000)],
2797    "count lines in a file",
2798    "\
2799 This command counts the lines in a file, using the
2800 C<wc -l> external command.");
2801
2802   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2803    [InitISOFS, Always, TestOutputInt (
2804       [["wc_w"; "/10klines"]], 10000)],
2805    "count words in a file",
2806    "\
2807 This command counts the words in a file, using the
2808 C<wc -w> external command.");
2809
2810   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2811    [InitISOFS, Always, TestOutputInt (
2812       [["wc_c"; "/100kallspaces"]], 102400)],
2813    "count characters in a file",
2814    "\
2815 This command counts the characters in a file, using the
2816 C<wc -c> external command.");
2817
2818   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2819    [InitISOFS, Always, TestOutputList (
2820       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2821    "return first 10 lines of a file",
2822    "\
2823 This command returns up to the first 10 lines of a file as
2824 a list of strings.");
2825
2826   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2827    [InitISOFS, Always, TestOutputList (
2828       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2829     InitISOFS, Always, TestOutputList (
2830       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "0"; "/10klines"]], [])],
2833    "return first N lines of a file",
2834    "\
2835 If the parameter C<nrlines> is a positive number, this returns the first
2836 C<nrlines> lines of the file C<path>.
2837
2838 If the parameter C<nrlines> is a negative number, this returns lines
2839 from the file C<path>, excluding the last C<nrlines> lines.
2840
2841 If the parameter C<nrlines> is zero, this returns an empty list.");
2842
2843   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2844    [InitISOFS, Always, TestOutputList (
2845       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2846    "return last 10 lines of a file",
2847    "\
2848 This command returns up to the last 10 lines of a file as
2849 a list of strings.");
2850
2851   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2852    [InitISOFS, Always, TestOutputList (
2853       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2854     InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "0"; "/10klines"]], [])],
2858    "return last N lines of a file",
2859    "\
2860 If the parameter C<nrlines> is a positive number, this returns the last
2861 C<nrlines> lines of the file C<path>.
2862
2863 If the parameter C<nrlines> is a negative number, this returns lines
2864 from the file C<path>, starting with the C<-nrlines>th line.
2865
2866 If the parameter C<nrlines> is zero, this returns an empty list.");
2867
2868   ("df", (RString "output", []), 125, [],
2869    [], (* XXX Tricky to test because it depends on the exact format
2870         * of the 'df' command and other imponderables.
2871         *)
2872    "report file system disk space usage",
2873    "\
2874 This command runs the C<df> command to report disk space used.
2875
2876 This command is mostly useful for interactive sessions.  It
2877 is I<not> intended that you try to parse the output string.
2878 Use C<statvfs> from programs.");
2879
2880   ("df_h", (RString "output", []), 126, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage (human readable)",
2885    "\
2886 This command runs the C<df -h> command to report disk space used
2887 in human-readable format.
2888
2889 This command is mostly useful for interactive sessions.  It
2890 is I<not> intended that you try to parse the output string.
2891 Use C<statvfs> from programs.");
2892
2893   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2894    [InitISOFS, Always, TestOutputInt (
2895       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2896    "estimate file space usage",
2897    "\
2898 This command runs the C<du -s> command to estimate file space
2899 usage for C<path>.
2900
2901 C<path> can be a file or a directory.  If C<path> is a directory
2902 then the estimate includes the contents of the directory and all
2903 subdirectories (recursively).
2904
2905 The result is the estimated size in I<kilobytes>
2906 (ie. units of 1024 bytes).");
2907
2908   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2909    [InitISOFS, Always, TestOutputList (
2910       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2911    "list files in an initrd",
2912    "\
2913 This command lists out files contained in an initrd.
2914
2915 The files are listed without any initial C</> character.  The
2916 files are listed in the order they appear (not necessarily
2917 alphabetical).  Directory names are listed as separate items.
2918
2919 Old Linux kernels (2.4 and earlier) used a compressed ext2
2920 filesystem as initrd.  We I<only> support the newer initramfs
2921 format (compressed cpio files).");
2922
2923   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924    [],
2925    "mount a file using the loop device",
2926    "\
2927 This command lets you mount C<file> (a filesystem image
2928 in a file) on a mount point.  It is entirely equivalent to
2929 the command C<mount -o loop file mountpoint>.");
2930
2931   ("mkswap", (RErr, [Device "device"]), 130, [],
2932    [InitEmpty, Always, TestRun (
2933       [["part_disk"; "/dev/sda"; "mbr"];
2934        ["mkswap"; "/dev/sda1"]])],
2935    "create a swap partition",
2936    "\
2937 Create a swap partition on C<device>.");
2938
2939   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2940    [InitEmpty, Always, TestRun (
2941       [["part_disk"; "/dev/sda"; "mbr"];
2942        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2943    "create a swap partition with a label",
2944    "\
2945 Create a swap partition on C<device> with label C<label>.
2946
2947 Note that you cannot attach a swap label to a block device
2948 (eg. C</dev/sda>), just to a partition.  This appears to be
2949 a limitation of the kernel or swap tools.");
2950
2951   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2952    (let uuid = uuidgen () in
2953     [InitEmpty, Always, TestRun (
2954        [["part_disk"; "/dev/sda"; "mbr"];
2955         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2956    "create a swap partition with an explicit UUID",
2957    "\
2958 Create a swap partition on C<device> with UUID C<uuid>.");
2959
2960   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2961    [InitBasicFS, Always, TestOutputStruct (
2962       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2963        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2964        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2965     InitBasicFS, Always, TestOutputStruct (
2966       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2967        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2968    "make block, character or FIFO devices",
2969    "\
2970 This call creates block or character special devices, or
2971 named pipes (FIFOs).
2972
2973 The C<mode> parameter should be the mode, using the standard
2974 constants.  C<devmajor> and C<devminor> are the
2975 device major and minor numbers, only used when creating block
2976 and character special devices.");
2977
2978   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2979    [InitBasicFS, Always, TestOutputStruct (
2980       [["mkfifo"; "0o777"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2982    "make FIFO (named pipe)",
2983    "\
2984 This call creates a FIFO (named pipe) called C<path> with
2985 mode C<mode>.  It is just a convenient wrapper around
2986 C<guestfs_mknod>.");
2987
2988   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2989    [InitBasicFS, Always, TestOutputStruct (
2990       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2991        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2992    "make block device node",
2993    "\
2994 This call creates a block device node called C<path> with
2995 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2996 It is just a convenient wrapper around C<guestfs_mknod>.");
2997
2998   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2999    [InitBasicFS, Always, TestOutputStruct (
3000       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3001        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3002    "make char device node",
3003    "\
3004 This call creates a char device node called C<path> with
3005 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3006 It is just a convenient wrapper around C<guestfs_mknod>.");
3007
3008   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3009    [InitEmpty, Always, TestOutputInt (
3010       [["umask"; "0o22"]], 0o22)],
3011    "set file mode creation mask (umask)",
3012    "\
3013 This function sets the mask used for creating new files and
3014 device nodes to C<mask & 0777>.
3015
3016 Typical umask values would be C<022> which creates new files
3017 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3018 C<002> which creates new files with permissions like
3019 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3020
3021 The default umask is C<022>.  This is important because it
3022 means that directories and device nodes will be created with
3023 C<0644> or C<0755> mode even if you specify C<0777>.
3024
3025 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3026
3027 This call returns the previous umask.");
3028
3029   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3030    [],
3031    "read directories entries",
3032    "\
3033 This returns the list of directory entries in directory C<dir>.
3034
3035 All entries in the directory are returned, including C<.> and
3036 C<..>.  The entries are I<not> sorted, but returned in the same
3037 order as the underlying filesystem.
3038
3039 Also this call returns basic file type information about each
3040 file.  The C<ftyp> field will contain one of the following characters:
3041
3042 =over 4
3043
3044 =item 'b'
3045
3046 Block special
3047
3048 =item 'c'
3049
3050 Char special
3051
3052 =item 'd'
3053
3054 Directory
3055
3056 =item 'f'
3057
3058 FIFO (named pipe)
3059
3060 =item 'l'
3061
3062 Symbolic link
3063
3064 =item 'r'
3065
3066 Regular file
3067
3068 =item 's'
3069
3070 Socket
3071
3072 =item 'u'
3073
3074 Unknown file type
3075
3076 =item '?'
3077
3078 The L<readdir(3)> returned a C<d_type> field with an
3079 unexpected value
3080
3081 =back
3082
3083 This function is primarily intended for use by programs.  To
3084 get a simple list of names, use C<guestfs_ls>.  To get a printable
3085 directory for human consumption, use C<guestfs_ll>.");
3086
3087   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3088    [],
3089    "create partitions on a block device",
3090    "\
3091 This is a simplified interface to the C<guestfs_sfdisk>
3092 command, where partition sizes are specified in megabytes
3093 only (rounded to the nearest cylinder) and you don't need
3094 to specify the cyls, heads and sectors parameters which
3095 were rarely if ever used anyway.
3096
3097 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3098 and C<guestfs_part_disk>");
3099
3100   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3101    [],
3102    "determine file type inside a compressed file",
3103    "\
3104 This command runs C<file> after first decompressing C<path>
3105 using C<method>.
3106
3107 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3108
3109 Since 1.0.63, use C<guestfs_file> instead which can now
3110 process compressed files.");
3111
3112   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3113    [],
3114    "list extended attributes of a file or directory",
3115    "\
3116 This call lists the extended attributes of the file or directory
3117 C<path>.
3118
3119 At the system call level, this is a combination of the
3120 L<listxattr(2)> and L<getxattr(2)> calls.
3121
3122 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3123
3124   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3125    [],
3126    "list extended attributes of a file or directory",
3127    "\
3128 This is the same as C<guestfs_getxattrs>, but if C<path>
3129 is a symbolic link, then it returns the extended attributes
3130 of the link itself.");
3131
3132   ("setxattr", (RErr, [String "xattr";
3133                        String "val"; Int "vallen"; (* will be BufferIn *)
3134                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3135    [],
3136    "set extended attribute of a file or directory",
3137    "\
3138 This call sets the extended attribute named C<xattr>
3139 of the file C<path> to the value C<val> (of length C<vallen>).
3140 The value is arbitrary 8 bit data.
3141
3142 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3143
3144   ("lsetxattr", (RErr, [String "xattr";
3145                         String "val"; Int "vallen"; (* will be BufferIn *)
3146                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3147    [],
3148    "set extended attribute of a file or directory",
3149    "\
3150 This is the same as C<guestfs_setxattr>, but if C<path>
3151 is a symbolic link, then it sets an extended attribute
3152 of the link itself.");
3153
3154   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3155    [],
3156    "remove extended attribute of a file or directory",
3157    "\
3158 This call removes the extended attribute named C<xattr>
3159 of the file C<path>.
3160
3161 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3162
3163   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3164    [],
3165    "remove extended attribute of a file or directory",
3166    "\
3167 This is the same as C<guestfs_removexattr>, but if C<path>
3168 is a symbolic link, then it removes an extended attribute
3169 of the link itself.");
3170
3171   ("mountpoints", (RHashtable "mps", []), 147, [],
3172    [],
3173    "show mountpoints",
3174    "\
3175 This call is similar to C<guestfs_mounts>.  That call returns
3176 a list of devices.  This one returns a hash table (map) of
3177 device name to directory where the device is mounted.");
3178
3179   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3180    (* This is a special case: while you would expect a parameter
3181     * of type "Pathname", that doesn't work, because it implies
3182     * NEED_ROOT in the generated calling code in stubs.c, and
3183     * this function cannot use NEED_ROOT.
3184     *)
3185    [],
3186    "create a mountpoint",
3187    "\
3188 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3189 specialized calls that can be used to create extra mountpoints
3190 before mounting the first filesystem.
3191
3192 These calls are I<only> necessary in some very limited circumstances,
3193 mainly the case where you want to mount a mix of unrelated and/or
3194 read-only filesystems together.
3195
3196 For example, live CDs often contain a \"Russian doll\" nest of
3197 filesystems, an ISO outer layer, with a squashfs image inside, with
3198 an ext2/3 image inside that.  You can unpack this as follows
3199 in guestfish:
3200
3201  add-ro Fedora-11-i686-Live.iso
3202  run
3203  mkmountpoint /cd
3204  mkmountpoint /squash
3205  mkmountpoint /ext3
3206  mount /dev/sda /cd
3207  mount-loop /cd/LiveOS/squashfs.img /squash
3208  mount-loop /squash/LiveOS/ext3fs.img /ext3
3209
3210 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3211
3212   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3213    [],
3214    "remove a mountpoint",
3215    "\
3216 This calls removes a mountpoint that was previously created
3217 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3218 for full details.");
3219
3220   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputBuffer (
3222       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3223    "read a file",
3224    "\
3225 This calls returns the contents of the file C<path> as a
3226 buffer.
3227
3228 Unlike C<guestfs_cat>, this function can correctly
3229 handle files that contain embedded ASCII NUL characters.
3230 However unlike C<guestfs_download>, this function is limited
3231 in the total size of file that can be handled.");
3232
3233   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3234    [InitISOFS, Always, TestOutputList (
3235       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3236     InitISOFS, Always, TestOutputList (
3237       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3238    "return lines matching a pattern",
3239    "\
3240 This calls the external C<grep> program and returns the
3241 matching lines.");
3242
3243   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3244    [InitISOFS, Always, TestOutputList (
3245       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3246    "return lines matching a pattern",
3247    "\
3248 This calls the external C<egrep> program and returns the
3249 matching lines.");
3250
3251   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputList (
3253       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254    "return lines matching a pattern",
3255    "\
3256 This calls the external C<fgrep> program and returns the
3257 matching lines.");
3258
3259   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3260    [InitISOFS, Always, TestOutputList (
3261       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3262    "return lines matching a pattern",
3263    "\
3264 This calls the external C<grep -i> program and returns the
3265 matching lines.");
3266
3267   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3268    [InitISOFS, Always, TestOutputList (
3269       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270    "return lines matching a pattern",
3271    "\
3272 This calls the external C<egrep -i> program and returns the
3273 matching lines.");
3274
3275   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3276    [InitISOFS, Always, TestOutputList (
3277       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278    "return lines matching a pattern",
3279    "\
3280 This calls the external C<fgrep -i> program and returns the
3281 matching lines.");
3282
3283   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3284    [InitISOFS, Always, TestOutputList (
3285       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3286    "return lines matching a pattern",
3287    "\
3288 This calls the external C<zgrep> program and returns the
3289 matching lines.");
3290
3291   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3292    [InitISOFS, Always, TestOutputList (
3293       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294    "return lines matching a pattern",
3295    "\
3296 This calls the external C<zegrep> program and returns the
3297 matching lines.");
3298
3299   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3300    [InitISOFS, Always, TestOutputList (
3301       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302    "return lines matching a pattern",
3303    "\
3304 This calls the external C<zfgrep> program and returns the
3305 matching lines.");
3306
3307   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3308    [InitISOFS, Always, TestOutputList (
3309       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3310    "return lines matching a pattern",
3311    "\
3312 This calls the external C<zgrep -i> program and returns the
3313 matching lines.");
3314
3315   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3316    [InitISOFS, Always, TestOutputList (
3317       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318    "return lines matching a pattern",
3319    "\
3320 This calls the external C<zegrep -i> program and returns the
3321 matching lines.");
3322
3323   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326    "return lines matching a pattern",
3327    "\
3328 This calls the external C<zfgrep -i> program and returns the
3329 matching lines.");
3330
3331   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3332    [InitISOFS, Always, TestOutput (
3333       [["realpath"; "/../directory"]], "/directory")],
3334    "canonicalized absolute pathname",
3335    "\
3336 Return the canonicalized absolute pathname of C<path>.  The
3337 returned path has no C<.>, C<..> or symbolic link path elements.");
3338
3339   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3340    [InitBasicFS, Always, TestOutputStruct (
3341       [["touch"; "/a"];
3342        ["ln"; "/a"; "/b"];
3343        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3344    "create a hard link",
3345    "\
3346 This command creates a hard link using the C<ln> command.");
3347
3348   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3349    [InitBasicFS, Always, TestOutputStruct (
3350       [["touch"; "/a"];
3351        ["touch"; "/b"];
3352        ["ln_f"; "/a"; "/b"];
3353        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3354    "create a hard link",
3355    "\
3356 This command creates a hard link using the C<ln -f> command.
3357 The C<-f> option removes the link (C<linkname>) if it exists already.");
3358
3359   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3360    [InitBasicFS, Always, TestOutputStruct (
3361       [["touch"; "/a"];
3362        ["ln_s"; "a"; "/b"];
3363        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3364    "create a symbolic link",
3365    "\
3366 This command creates a symbolic link using the C<ln -s> command.");
3367
3368   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3369    [InitBasicFS, Always, TestOutput (
3370       [["mkdir_p"; "/a/b"];
3371        ["touch"; "/a/b/c"];
3372        ["ln_sf"; "../d"; "/a/b/c"];
3373        ["readlink"; "/a/b/c"]], "../d")],
3374    "create a symbolic link",
3375    "\
3376 This command creates a symbolic link using the C<ln -sf> command,
3377 The C<-f> option removes the link (C<linkname>) if it exists already.");
3378
3379   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3380    [] (* XXX tested above *),
3381    "read the target of a symbolic link",
3382    "\
3383 This command reads the target of a symbolic link.");
3384
3385   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3386    [InitBasicFS, Always, TestOutputStruct (
3387       [["fallocate"; "/a"; "1000000"];
3388        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3389    "preallocate a file in the guest filesystem",
3390    "\
3391 This command preallocates a file (containing zero bytes) named
3392 C<path> of size C<len> bytes.  If the file exists already, it
3393 is overwritten.
3394
3395 Do not confuse this with the guestfish-specific
3396 C<alloc> command which allocates a file in the host and
3397 attaches it as a device.");
3398
3399   ("swapon_device", (RErr, [Device "device"]), 170, [],
3400    [InitPartition, Always, TestRun (
3401       [["mkswap"; "/dev/sda1"];
3402        ["swapon_device"; "/dev/sda1"];
3403        ["swapoff_device"; "/dev/sda1"]])],
3404    "enable swap on device",
3405    "\
3406 This command enables the libguestfs appliance to use the
3407 swap device or partition named C<device>.  The increased
3408 memory is made available for all commands, for example
3409 those run using C<guestfs_command> or C<guestfs_sh>.
3410
3411 Note that you should not swap to existing guest swap
3412 partitions unless you know what you are doing.  They may
3413 contain hibernation information, or other information that
3414 the guest doesn't want you to trash.  You also risk leaking
3415 information about the host to the guest this way.  Instead,
3416 attach a new host device to the guest and swap on that.");
3417
3418   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3419    [], (* XXX tested by swapon_device *)
3420    "disable swap on device",
3421    "\
3422 This command disables the libguestfs appliance swap
3423 device or partition named C<device>.
3424 See C<guestfs_swapon_device>.");
3425
3426   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3427    [InitBasicFS, Always, TestRun (
3428       [["fallocate"; "/swap"; "8388608"];
3429        ["mkswap_file"; "/swap"];
3430        ["swapon_file"; "/swap"];
3431        ["swapoff_file"; "/swap"]])],
3432    "enable swap on file",
3433    "\
3434 This command enables swap to a file.
3435 See C<guestfs_swapon_device> for other notes.");
3436
3437   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3438    [], (* XXX tested by swapon_file *)
3439    "disable swap on file",
3440    "\
3441 This command disables the libguestfs appliance swap on file.");
3442
3443   ("swapon_label", (RErr, [String "label"]), 174, [],
3444    [InitEmpty, Always, TestRun (
3445       [["part_disk"; "/dev/sdb"; "mbr"];
3446        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3447        ["swapon_label"; "swapit"];
3448        ["swapoff_label"; "swapit"];
3449        ["zero"; "/dev/sdb"];
3450        ["blockdev_rereadpt"; "/dev/sdb"]])],
3451    "enable swap on labeled swap partition",
3452    "\
3453 This command enables swap to a labeled swap partition.
3454 See C<guestfs_swapon_device> for other notes.");
3455
3456   ("swapoff_label", (RErr, [String "label"]), 175, [],
3457    [], (* XXX tested by swapon_label *)
3458    "disable swap on labeled swap partition",
3459    "\
3460 This command disables the libguestfs appliance swap on
3461 labeled swap partition.");
3462
3463   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3464    (let uuid = uuidgen () in
3465     [InitEmpty, Always, TestRun (
3466        [["mkswap_U"; uuid; "/dev/sdb"];
3467         ["swapon_uuid"; uuid];
3468         ["swapoff_uuid"; uuid]])]),
3469    "enable swap on swap partition by UUID",
3470    "\
3471 This command enables swap to a swap partition with the given UUID.
3472 See C<guestfs_swapon_device> for other notes.");
3473
3474   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3475    [], (* XXX tested by swapon_uuid *)
3476    "disable swap on swap partition by UUID",
3477    "\
3478 This command disables the libguestfs appliance swap partition
3479 with the given UUID.");
3480
3481   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3482    [InitBasicFS, Always, TestRun (
3483       [["fallocate"; "/swap"; "8388608"];
3484        ["mkswap_file"; "/swap"]])],
3485    "create a swap file",
3486    "\
3487 Create a swap file.
3488
3489 This command just writes a swap file signature to an existing
3490 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3491
3492   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3493    [InitISOFS, Always, TestRun (
3494       [["inotify_init"; "0"]])],
3495    "create an inotify handle",
3496    "\
3497 This command creates a new inotify handle.
3498 The inotify subsystem can be used to notify events which happen to
3499 objects in the guest filesystem.
3500
3501 C<maxevents> is the maximum number of events which will be
3502 queued up between calls to C<guestfs_inotify_read> or
3503 C<guestfs_inotify_files>.
3504 If this is passed as C<0>, then the kernel (or previously set)
3505 default is used.  For Linux 2.6.29 the default was 16384 events.
3506 Beyond this limit, the kernel throws away events, but records
3507 the fact that it threw them away by setting a flag
3508 C<IN_Q_OVERFLOW> in the returned structure list (see
3509 C<guestfs_inotify_read>).
3510
3511 Before any events are generated, you have to add some
3512 watches to the internal watch list.  See:
3513 C<guestfs_inotify_add_watch>,
3514 C<guestfs_inotify_rm_watch> and
3515 C<guestfs_inotify_watch_all>.
3516
3517 Queued up events should be read periodically by calling
3518 C<guestfs_inotify_read>
3519 (or C<guestfs_inotify_files> which is just a helpful
3520 wrapper around C<guestfs_inotify_read>).  If you don't
3521 read the events out often enough then you risk the internal
3522 queue overflowing.
3523
3524 The handle should be closed after use by calling
3525 C<guestfs_inotify_close>.  This also removes any
3526 watches automatically.
3527
3528 See also L<inotify(7)> for an overview of the inotify interface
3529 as exposed by the Linux kernel, which is roughly what we expose
3530 via libguestfs.  Note that there is one global inotify handle
3531 per libguestfs instance.");
3532
3533   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3534    [InitBasicFS, Always, TestOutputList (
3535       [["inotify_init"; "0"];
3536        ["inotify_add_watch"; "/"; "1073741823"];
3537        ["touch"; "/a"];
3538        ["touch"; "/b"];
3539        ["inotify_files"]], ["a"; "b"])],
3540    "add an inotify watch",
3541    "\
3542 Watch C<path> for the events listed in C<mask>.
3543
3544 Note that if C<path> is a directory then events within that
3545 directory are watched, but this does I<not> happen recursively
3546 (in subdirectories).
3547
3548 Note for non-C or non-Linux callers: the inotify events are
3549 defined by the Linux kernel ABI and are listed in
3550 C</usr/include/sys/inotify.h>.");
3551
3552   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3553    [],
3554    "remove an inotify watch",
3555    "\
3556 Remove a previously defined inotify watch.
3557 See C<guestfs_inotify_add_watch>.");
3558
3559   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3560    [],
3561    "return list of inotify events",
3562    "\
3563 Return the complete queue of events that have happened
3564 since the previous read call.
3565
3566 If no events have happened, this returns an empty list.
3567
3568 I<Note>: In order to make sure that all events have been
3569 read, you must call this function repeatedly until it
3570 returns an empty list.  The reason is that the call will
3571 read events up to the maximum appliance-to-host message
3572 size and leave remaining events in the queue.");
3573
3574   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3575    [],
3576    "return list of watched files that had events",
3577    "\
3578 This function is a helpful wrapper around C<guestfs_inotify_read>
3579 which just returns a list of pathnames of objects that were
3580 touched.  The returned pathnames are sorted and deduplicated.");
3581
3582   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3583    [],
3584    "close the inotify handle",
3585    "\
3586 This closes the inotify handle which was previously
3587 opened by inotify_init.  It removes all watches, throws
3588 away any pending events, and deallocates all resources.");
3589
3590   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3591    [],
3592    "set SELinux security context",
3593    "\
3594 This sets the SELinux security context of the daemon
3595 to the string C<context>.
3596
3597 See the documentation about SELINUX in L<guestfs(3)>.");
3598
3599   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3600    [],
3601    "get SELinux security context",
3602    "\
3603 This gets the SELinux security context of the daemon.
3604
3605 See the documentation about SELINUX in L<guestfs(3)>,
3606 and C<guestfs_setcon>");
3607
3608   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3609    [InitEmpty, Always, TestOutput (
3610       [["part_disk"; "/dev/sda"; "mbr"];
3611        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3612        ["mount_options"; ""; "/dev/sda1"; "/"];
3613        ["write_file"; "/new"; "new file contents"; "0"];
3614        ["cat"; "/new"]], "new file contents")],
3615    "make a filesystem with block size",
3616    "\
3617 This call is similar to C<guestfs_mkfs>, but it allows you to
3618 control the block size of the resulting filesystem.  Supported
3619 block sizes depend on the filesystem type, but typically they
3620 are C<1024>, C<2048> or C<4096> only.");
3621
3622   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3623    [InitEmpty, Always, TestOutput (
3624       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3625        ["mke2journal"; "4096"; "/dev/sda1"];
3626        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3627        ["mount_options"; ""; "/dev/sda2"; "/"];
3628        ["write_file"; "/new"; "new file contents"; "0"];
3629        ["cat"; "/new"]], "new file contents")],
3630    "make ext2/3/4 external journal",
3631    "\
3632 This creates an ext2 external journal on C<device>.  It is equivalent
3633 to the command:
3634
3635  mke2fs -O journal_dev -b blocksize device");
3636
3637   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3638    [InitEmpty, Always, TestOutput (
3639       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3640        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3641        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3642        ["mount_options"; ""; "/dev/sda2"; "/"];
3643        ["write_file"; "/new"; "new file contents"; "0"];
3644        ["cat"; "/new"]], "new file contents")],
3645    "make ext2/3/4 external journal with label",
3646    "\
3647 This creates an ext2 external journal on C<device> with label C<label>.");
3648
3649   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3650    (let uuid = uuidgen () in
3651     [InitEmpty, Always, TestOutput (
3652        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3654         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3655         ["mount_options"; ""; "/dev/sda2"; "/"];
3656         ["write_file"; "/new"; "new file contents"; "0"];
3657         ["cat"; "/new"]], "new file contents")]),
3658    "make ext2/3/4 external journal with UUID",
3659    "\
3660 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3661
3662   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3663    [],
3664    "make ext2/3/4 filesystem with external journal",
3665    "\
3666 This creates an ext2/3/4 filesystem on C<device> with
3667 an external journal on C<journal>.  It is equivalent
3668 to the command:
3669
3670  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3671
3672 See also C<guestfs_mke2journal>.");
3673
3674   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3675    [],
3676    "make ext2/3/4 filesystem with external journal",
3677    "\
3678 This creates an ext2/3/4 filesystem on C<device> with
3679 an external journal on the journal labeled C<label>.
3680
3681 See also C<guestfs_mke2journal_L>.");
3682
3683   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3684    [],
3685    "make ext2/3/4 filesystem with external journal",
3686    "\
3687 This creates an ext2/3/4 filesystem on C<device> with
3688 an external journal on the journal with UUID C<uuid>.
3689
3690 See also C<guestfs_mke2journal_U>.");
3691
3692   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3693    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3694    "load a kernel module",
3695    "\
3696 This loads a kernel module in the appliance.
3697
3698 The kernel module must have been whitelisted when libguestfs
3699 was built (see C<appliance/kmod.whitelist.in> in the source).");
3700
3701   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3702    [InitNone, Always, TestOutput (
3703       [["echo_daemon"; "This is a test"]], "This is a test"
3704     )],
3705    "echo arguments back to the client",
3706    "\
3707 This command concatenate the list of C<words> passed with single spaces between
3708 them and returns the resulting string.
3709
3710 You can use this command to test the connection through to the daemon.
3711
3712 See also C<guestfs_ping_daemon>.");
3713
3714   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3715    [], (* There is a regression test for this. *)
3716    "find all files and directories, returning NUL-separated list",
3717    "\
3718 This command lists out all files and directories, recursively,
3719 starting at C<directory>, placing the resulting list in the
3720 external file called C<files>.
3721
3722 This command works the same way as C<guestfs_find> with the
3723 following exceptions:
3724
3725 =over 4
3726
3727 =item *
3728
3729 The resulting list is written to an external file.
3730
3731 =item *
3732
3733 Items (filenames) in the result are separated
3734 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3735
3736 =item *
3737
3738 This command is not limited in the number of names that it
3739 can return.
3740
3741 =item *
3742
3743 The result list is not sorted.
3744
3745 =back");
3746
3747   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3748    [InitISOFS, Always, TestOutput (
3749       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3750     InitISOFS, Always, TestOutput (
3751       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3752     InitISOFS, Always, TestOutput (
3753       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3754     InitISOFS, Always, TestLastFail (
3755       [["case_sensitive_path"; "/Known-1/"]]);
3756     InitBasicFS, Always, TestOutput (
3757       [["mkdir"; "/a"];
3758        ["mkdir"; "/a/bbb"];
3759        ["touch"; "/a/bbb/c"];
3760        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3761     InitBasicFS, Always, TestOutput (
3762       [["mkdir"; "/a"];
3763        ["mkdir"; "/a/bbb"];
3764        ["touch"; "/a/bbb/c"];
3765        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3766     InitBasicFS, Always, TestLastFail (
3767       [["mkdir"; "/a"];
3768        ["mkdir"; "/a/bbb"];
3769        ["touch"; "/a/bbb/c"];
3770        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3771    "return true path on case-insensitive filesystem",
3772    "\
3773 This can be used to resolve case insensitive paths on
3774 a filesystem which is case sensitive.  The use case is
3775 to resolve paths which you have read from Windows configuration
3776 files or the Windows Registry, to the true path.
3777
3778 The command handles a peculiarity of the Linux ntfs-3g
3779 filesystem driver (and probably others), which is that although
3780 the underlying filesystem is case-insensitive, the driver
3781 exports the filesystem to Linux as case-sensitive.
3782
3783 One consequence of this is that special directories such
3784 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3785 (or other things) depending on the precise details of how
3786 they were created.  In Windows itself this would not be
3787 a problem.
3788
3789 Bug or feature?  You decide:
3790 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3791
3792 This function resolves the true case of each element in the
3793 path and returns the case-sensitive path.
3794
3795 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3796 might return C<\"/WINDOWS/system32\"> (the exact return value
3797 would depend on details of how the directories were originally
3798 created under Windows).
3799
3800 I<Note>:
3801 This function does not handle drive names, backslashes etc.
3802
3803 See also C<guestfs_realpath>.");
3804
3805   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3806    [InitBasicFS, Always, TestOutput (
3807       [["vfs_type"; "/dev/sda1"]], "ext2")],
3808    "get the Linux VFS type corresponding to a mounted device",
3809    "\
3810 This command gets the block device type corresponding to
3811 a mounted device called C<device>.
3812
3813 Usually the result is the name of the Linux VFS module that
3814 is used to mount this device (probably determined automatically
3815 if you used the C<guestfs_mount> call).");
3816
3817   ("truncate", (RErr, [Pathname "path"]), 199, [],
3818    [InitBasicFS, Always, TestOutputStruct (
3819       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3820        ["truncate"; "/test"];
3821        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3822    "truncate a file to zero size",
3823    "\
3824 This command truncates C<path> to a zero-length file.  The
3825 file must exist already.");
3826
3827   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3828    [InitBasicFS, Always, TestOutputStruct (
3829       [["touch"; "/test"];
3830        ["truncate_size"; "/test"; "1000"];
3831        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3832    "truncate a file to a particular size",
3833    "\
3834 This command truncates C<path> to size C<size> bytes.  The file
3835 must exist already.  If the file is smaller than C<size> then
3836 the file is extended to the required size with null bytes.");
3837
3838   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3839    [InitBasicFS, Always, TestOutputStruct (
3840       [["touch"; "/test"];
3841        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3842        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3843    "set timestamp of a file with nanosecond precision",
3844    "\
3845 This command sets the timestamps of a file with nanosecond
3846 precision.
3847
3848 C<atsecs, atnsecs> are the last access time (atime) in secs and
3849 nanoseconds from the epoch.
3850
3851 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3852 secs and nanoseconds from the epoch.
3853
3854 If the C<*nsecs> field contains the special value C<-1> then
3855 the corresponding timestamp is set to the current time.  (The
3856 C<*secs> field is ignored in this case).
3857
3858 If the C<*nsecs> field contains the special value C<-2> then
3859 the corresponding timestamp is left unchanged.  (The
3860 C<*secs> field is ignored in this case).");
3861
3862   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3863    [InitBasicFS, Always, TestOutputStruct (
3864       [["mkdir_mode"; "/test"; "0o111"];
3865        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3866    "create a directory with a particular mode",
3867    "\
3868 This command creates a directory, setting the initial permissions
3869 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3870
3871   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3872    [], (* XXX *)
3873    "change file owner and group",
3874    "\
3875 Change the file owner to C<owner> and group to C<group>.
3876 This is like C<guestfs_chown> but if C<path> is a symlink then
3877 the link itself is changed, not the target.
3878
3879 Only numeric uid and gid are supported.  If you want to use
3880 names, you will need to locate and parse the password file
3881 yourself (Augeas support makes this relatively easy).");
3882
3883   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3884    [], (* XXX *)
3885    "lstat on multiple files",
3886    "\
3887 This call allows you to perform the C<guestfs_lstat> operation
3888 on multiple files, where all files are in the directory C<path>.
3889 C<names> is the list of files from this directory.
3890
3891 On return you get a list of stat structs, with a one-to-one
3892 correspondence to the C<names> list.  If any name did not exist
3893 or could not be lstat'd, then the C<ino> field of that structure
3894 is set to C<-1>.
3895
3896 This call is intended for programs that want to efficiently
3897 list a directory contents without making many round-trips.
3898 See also C<guestfs_lxattrlist> for a similarly efficient call
3899 for getting extended attributes.  Very long directory listings
3900 might cause the protocol message size to be exceeded, causing
3901 this call to fail.  The caller must split up such requests
3902 into smaller groups of names.");
3903
3904   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3905    [], (* XXX *)
3906    "lgetxattr on multiple files",
3907    "\
3908 This call allows you to get the extended attributes
3909 of multiple files, where all files are in the directory C<path>.
3910 C<names> is the list of files from this directory.
3911
3912 On return you get a flat list of xattr structs which must be
3913 interpreted sequentially.  The first xattr struct always has a zero-length
3914 C<attrname>.  C<attrval> in this struct is zero-length
3915 to indicate there was an error doing C<lgetxattr> for this
3916 file, I<or> is a C string which is a decimal number
3917 (the number of following attributes for this file, which could
3918 be C<\"0\">).  Then after the first xattr struct are the
3919 zero or more attributes for the first named file.
3920 This repeats for the second and subsequent files.
3921
3922 This call is intended for programs that want to efficiently
3923 list a directory contents without making many round-trips.
3924 See also C<guestfs_lstatlist> for a similarly efficient call
3925 for getting standard stats.  Very long directory listings
3926 might cause the protocol message size to be exceeded, causing
3927 this call to fail.  The caller must split up such requests
3928 into smaller groups of names.");
3929
3930   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3931    [], (* XXX *)
3932    "readlink on multiple files",
3933    "\
3934 This call allows you to do a C<readlink> operation
3935 on multiple files, where all files are in the directory C<path>.
3936 C<names> is the list of files from this directory.
3937
3938 On return you get a list of strings, with a one-to-one
3939 correspondence to the C<names> list.  Each string is the
3940 value of the symbol link.
3941
3942 If the C<readlink(2)> operation fails on any name, then
3943 the corresponding result string is the empty string C<\"\">.
3944 However the whole operation is completed even if there
3945 were C<readlink(2)> errors, and so you can call this
3946 function with names where you don't know if they are
3947 symbolic links already (albeit slightly less efficient).
3948
3949 This call is intended for programs that want to efficiently
3950 list a directory contents without making many round-trips.
3951 Very long directory listings might cause the protocol
3952 message size to be exceeded, causing
3953 this call to fail.  The caller must split up such requests
3954 into smaller groups of names.");
3955
3956   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3957    [InitISOFS, Always, TestOutputBuffer (
3958       [["pread"; "/known-4"; "1"; "3"]], "\n");
3959     InitISOFS, Always, TestOutputBuffer (
3960       [["pread"; "/empty"; "0"; "100"]], "")],
3961    "read part of a file",
3962    "\
3963 This command lets you read part of a file.  It reads C<count>
3964 bytes of the file, starting at C<offset>, from file C<path>.
3965
3966 This may read fewer bytes than requested.  For further details
3967 see the L<pread(2)> system call.");
3968
3969   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3970    [InitEmpty, Always, TestRun (
3971       [["part_init"; "/dev/sda"; "gpt"]])],
3972    "create an empty partition table",
3973    "\
3974 This creates an empty partition table on C<device> of one of the
3975 partition types listed below.  Usually C<parttype> should be
3976 either C<msdos> or C<gpt> (for large disks).
3977
3978 Initially there are no partitions.  Following this, you should
3979 call C<guestfs_part_add> for each partition required.
3980
3981 Possible values for C<parttype> are:
3982
3983 =over 4
3984
3985 =item B<efi> | B<gpt>
3986
3987 Intel EFI / GPT partition table.
3988
3989 This is recommended for >= 2 TB partitions that will be accessed
3990 from Linux and Intel-based Mac OS X.  It also has limited backwards
3991 compatibility with the C<mbr> format.
3992
3993 =item B<mbr> | B<msdos>
3994
3995 The standard PC \"Master Boot Record\" (MBR) format used
3996 by MS-DOS and Windows.  This partition type will B<only> work
3997 for device sizes up to 2 TB.  For large disks we recommend
3998 using C<gpt>.
3999
4000 =back
4001
4002 Other partition table types that may work but are not
4003 supported include:
4004
4005 =over 4
4006
4007 =item B<aix>
4008
4009 AIX disk labels.
4010
4011 =item B<amiga> | B<rdb>
4012
4013 Amiga \"Rigid Disk Block\" format.
4014
4015 =item B<bsd>
4016
4017 BSD disk labels.
4018
4019 =item B<dasd>
4020
4021 DASD, used on IBM mainframes.
4022
4023 =item B<dvh>
4024
4025 MIPS/SGI volumes.
4026
4027 =item B<mac>
4028
4029 Old Mac partition format.  Modern Macs use C<gpt>.
4030
4031 =item B<pc98>
4032
4033 NEC PC-98 format, common in Japan apparently.
4034
4035 =item B<sun>
4036
4037 Sun disk labels.
4038
4039 =back");
4040
4041   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4042    [InitEmpty, Always, TestRun (
4043       [["part_init"; "/dev/sda"; "mbr"];
4044        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4045     InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "gpt"];
4047        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4048        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4049     InitEmpty, Always, TestRun (
4050       [["part_init"; "/dev/sda"; "mbr"];
4051        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4052        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4053        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4054        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4055    "add a partition to the device",
4056    "\
4057 This command adds a partition to C<device>.  If there is no partition
4058 table on the device, call C<guestfs_part_init> first.
4059
4060 The C<prlogex> parameter is the type of partition.  Normally you
4061 should pass C<p> or C<primary> here, but MBR partition tables also
4062 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4063 types.
4064
4065 C<startsect> and C<endsect> are the start and end of the partition
4066 in I<sectors>.  C<endsect> may be negative, which means it counts
4067 backwards from the end of the disk (C<-1> is the last sector).
4068
4069 Creating a partition which covers the whole disk is not so easy.
4070 Use C<guestfs_part_disk> to do that.");
4071
4072   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4073    [InitEmpty, Always, TestRun (
4074       [["part_disk"; "/dev/sda"; "mbr"]]);
4075     InitEmpty, Always, TestRun (
4076       [["part_disk"; "/dev/sda"; "gpt"]])],
4077    "partition whole disk with a single primary partition",
4078    "\
4079 This command is simply a combination of C<guestfs_part_init>
4080 followed by C<guestfs_part_add> to create a single primary partition
4081 covering the whole disk.
4082
4083 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4084 but other possible values are described in C<guestfs_part_init>.");
4085
4086   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4087    [InitEmpty, Always, TestRun (
4088       [["part_disk"; "/dev/sda"; "mbr"];
4089        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4090    "make a partition bootable",
4091    "\
4092 This sets the bootable flag on partition numbered C<partnum> on
4093 device C<device>.  Note that partitions are numbered from 1.
4094
4095 The bootable flag is used by some operating systems (notably
4096 Windows) to determine which partition to boot from.  It is by
4097 no means universally recognized.");
4098
4099   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4100    [InitEmpty, Always, TestRun (
4101       [["part_disk"; "/dev/sda"; "gpt"];
4102        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4103    "set partition name",
4104    "\
4105 This sets the partition name on partition numbered C<partnum> on
4106 device C<device>.  Note that partitions are numbered from 1.
4107
4108 The partition name can only be set on certain types of partition
4109 table.  This works on C<gpt> but not on C<mbr> partitions.");
4110
4111   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4112    [], (* XXX Add a regression test for this. *)
4113    "list partitions on a device",
4114    "\
4115 This command parses the partition table on C<device> and
4116 returns the list of partitions found.
4117
4118 The fields in the returned structure are:
4119
4120 =over 4
4121
4122 =item B<part_num>
4123
4124 Partition number, counting from 1.
4125
4126 =item B<part_start>
4127
4128 Start of the partition I<in bytes>.  To get sectors you have to
4129 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4130
4131 =item B<part_end>
4132
4133 End of the partition in bytes.
4134
4135 =item B<part_size>
4136
4137 Size of the partition in bytes.
4138
4139 =back");
4140
4141   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4142    [InitEmpty, Always, TestOutput (
4143       [["part_disk"; "/dev/sda"; "gpt"];
4144        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4145    "get the partition table type",
4146    "\
4147 This command examines the partition table on C<device> and
4148 returns the partition table type (format) being used.
4149
4150 Common return values include: C<msdos> (a DOS/Windows style MBR
4151 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4152 values are possible, although unusual.  See C<guestfs_part_init>
4153 for a full list.");
4154
4155   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4156    [InitBasicFS, Always, TestOutputBuffer (
4157       [["fill"; "0x63"; "10"; "/test"];
4158        ["read_file"; "/test"]], "cccccccccc")],
4159    "fill a file with octets",
4160    "\
4161 This command creates a new file called C<path>.  The initial
4162 content of the file is C<len> octets of C<c>, where C<c>
4163 must be a number in the range C<[0..255]>.
4164
4165 To fill a file with zero bytes (sparsely), it is
4166 much more efficient to use C<guestfs_truncate_size>.");
4167
4168   ("available", (RErr, [StringList "groups"]), 216, [],
4169    [InitNone, Always, TestRun [["available"; ""]]],
4170    "test availability of some parts of the API",
4171    "\
4172 This command is used to check the availability of some
4173 groups of functionality in the appliance, which not all builds of
4174 the libguestfs appliance will be able to provide.
4175
4176 The libguestfs groups, and the functions that those
4177 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4178
4179 The argument C<groups> is a list of group names, eg:
4180 C<[\"inotify\", \"augeas\"]> would check for the availability of
4181 the Linux inotify functions and Augeas (configuration file
4182 editing) functions.
4183
4184 The command returns no error if I<all> requested groups are available.
4185
4186 It fails with an error if one or more of the requested
4187 groups is unavailable in the appliance.
4188
4189 If an unknown group name is included in the
4190 list of groups then an error is always returned.
4191
4192 I<Notes:>
4193
4194 =over 4
4195
4196 =item *
4197
4198 You must call C<guestfs_launch> before calling this function.
4199
4200 The reason is because we don't know what groups are
4201 supported by the appliance/daemon until it is running and can
4202 be queried.
4203
4204 =item *
4205
4206 If a group of functions is available, this does not necessarily
4207 mean that they will work.  You still have to check for errors
4208 when calling individual API functions even if they are
4209 available.
4210
4211 =item *
4212
4213 It is usually the job of distro packagers to build
4214 complete functionality into the libguestfs appliance.
4215 Upstream libguestfs, if built from source with all
4216 requirements satisfied, will support everything.
4217
4218 =item *
4219
4220 This call was added in version C<1.0.80>.  In previous
4221 versions of libguestfs all you could do would be to speculatively
4222 execute a command to find out if the daemon implemented it.
4223 See also C<guestfs_version>.
4224
4225 =back");
4226
4227   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4228    [InitBasicFS, Always, TestOutputBuffer (
4229       [["write_file"; "/src"; "hello, world"; "0"];
4230        ["dd"; "/src"; "/dest"];
4231        ["read_file"; "/dest"]], "hello, world")],
4232    "copy from source to destination using dd",
4233    "\
4234 This command copies from one source device or file C<src>
4235 to another destination device or file C<dest>.  Normally you
4236 would use this to copy to or from a device or partition, for
4237 example to duplicate a filesystem.
4238
4239 If the destination is a device, it must be as large or larger
4240 than the source file or device, otherwise the copy will fail.
4241 This command cannot do partial copies (see C<guestfs_copy_size>).");
4242
4243   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4244    [InitBasicFS, Always, TestOutputInt (
4245       [["write_file"; "/file"; "hello, world"; "0"];
4246        ["filesize"; "/file"]], 12)],
4247    "return the size of the file in bytes",
4248    "\
4249 This command returns the size of C<file> in bytes.
4250
4251 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4252 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4253 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4254
4255   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4256    [InitBasicFSonLVM, Always, TestOutputList (
4257       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4258        ["lvs"]], ["/dev/VG/LV2"])],
4259    "rename an LVM logical volume",
4260    "\
4261 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4262
4263   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4264    [InitBasicFSonLVM, Always, TestOutputList (
4265       [["umount"; "/"];
4266        ["vg_activate"; "false"; "VG"];
4267        ["vgrename"; "VG"; "VG2"];
4268        ["vg_activate"; "true"; "VG2"];
4269        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4270        ["vgs"]], ["VG2"])],
4271    "rename an LVM volume group",
4272    "\
4273 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4274
4275   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4276    [InitISOFS, Always, TestOutputBuffer (
4277       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4278    "list the contents of a single file in an initrd",
4279    "\
4280 This command unpacks the file C<filename> from the initrd file
4281 called C<initrdpath>.  The filename must be given I<without> the
4282 initial C</> character.
4283
4284 For example, in guestfish you could use the following command
4285 to examine the boot script (usually called C</init>)
4286 contained in a Linux initrd or initramfs image:
4287
4288  initrd-cat /boot/initrd-<version>.img init
4289
4290 See also C<guestfs_initrd_list>.");
4291
4292   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4293    [],
4294    "get the UUID of a physical volume",
4295    "\
4296 This command returns the UUID of the LVM PV C<device>.");
4297
4298   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4299    [],
4300    "get the UUID of a volume group",
4301    "\
4302 This command returns the UUID of the LVM VG named C<vgname>.");
4303
4304   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4305    [],
4306    "get the UUID of a logical volume",
4307    "\
4308 This command returns the UUID of the LVM LV C<device>.");
4309
4310   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4311    [],
4312    "get the PV UUIDs containing the volume group",
4313    "\
4314 Given a VG called C<vgname>, this returns the UUIDs of all
4315 the physical volumes that this volume group resides on.
4316
4317 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4318 calls to associate physical volumes and volume groups.
4319
4320 See also C<guestfs_vglvuuids>.");
4321
4322   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4323    [],
4324    "get the LV UUIDs of all LVs in the volume group",
4325    "\
4326 Given a VG called C<vgname>, this returns the UUIDs of all
4327 the logical volumes created in this volume group.
4328
4329 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4330 calls to associate logical volumes and volume groups.
4331
4332 See also C<guestfs_vgpvuuids>.");
4333
4334   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4335    [InitBasicFS, Always, TestOutputBuffer (
4336       [["write_file"; "/src"; "hello, world"; "0"];
4337        ["copy_size"; "/src"; "/dest"; "5"];
4338        ["read_file"; "/dest"]], "hello")],
4339    "copy size bytes from source to destination using dd",
4340    "\
4341 This command copies exactly C<size> bytes from one source device
4342 or file C<src> to another destination device or file C<dest>.
4343
4344 Note this will fail if the source is too short or if the destination
4345 is not large enough.");
4346
4347   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4348    [InitEmpty, Always, TestRun (
4349       [["part_init"; "/dev/sda"; "mbr"];
4350        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4351        ["part_del"; "/dev/sda"; "1"]])],
4352    "delete a partition",
4353    "\
4354 This command deletes the partition numbered C<partnum> on C<device>.
4355
4356 Note that in the case of MBR partitioning, deleting an
4357 extended partition also deletes any logical partitions
4358 it contains.");
4359
4360   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4361    [InitEmpty, Always, TestOutputTrue (
4362       [["part_init"; "/dev/sda"; "mbr"];
4363        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4364        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4365        ["part_get_bootable"; "/dev/sda"; "1"]])],
4366    "return true if a partition is bootable",
4367    "\
4368 This command returns true if the partition C<partnum> on
4369 C<device> has the bootable flag set.
4370
4371 See also C<guestfs_part_set_bootable>.");
4372
4373   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4374    [InitEmpty, Always, TestOutputInt (
4375       [["part_init"; "/dev/sda"; "mbr"];
4376        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4377        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4378        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4379    "get the MBR type byte (ID byte) from a partition",
4380    "\
4381 Returns the MBR type byte (also known as the ID byte) from
4382 the numbered partition C<partnum>.
4383
4384 Note that only MBR (old DOS-style) partitions have type bytes.
4385 You will get undefined results for other partition table
4386 types (see C<guestfs_part_get_parttype>).");
4387
4388   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4389    [], (* tested by part_get_mbr_id *)
4390    "set the MBR type byte (ID byte) of a partition",
4391    "\
4392 Sets the MBR type byte (also known as the ID byte) of
4393 the numbered partition C<partnum> to C<idbyte>.  Note
4394 that the type bytes quoted in most documentation are
4395 in fact hexadecimal numbers, but usually documented
4396 without any leading \"0x\" which might be confusing.
4397
4398 Note that only MBR (old DOS-style) partitions have type bytes.
4399 You will get undefined results for other partition table
4400 types (see C<guestfs_part_get_parttype>).");
4401
4402 ]
4403
4404 let all_functions = non_daemon_functions @ daemon_functions
4405
4406 (* In some places we want the functions to be displayed sorted
4407  * alphabetically, so this is useful:
4408  *)
4409 let all_functions_sorted =
4410   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4411                compare n1 n2) all_functions
4412
4413 (* Field types for structures. *)
4414 type field =
4415   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4416   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4417   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4418   | FUInt32
4419   | FInt32
4420   | FUInt64
4421   | FInt64
4422   | FBytes                      (* Any int measure that counts bytes. *)
4423   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4424   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4425
4426 (* Because we generate extra parsing code for LVM command line tools,
4427  * we have to pull out the LVM columns separately here.
4428  *)
4429 let lvm_pv_cols = [
4430   "pv_name", FString;
4431   "pv_uuid", FUUID;
4432   "pv_fmt", FString;
4433   "pv_size", FBytes;
4434   "dev_size", FBytes;
4435   "pv_free", FBytes;
4436   "pv_used", FBytes;
4437   "pv_attr", FString (* XXX *);
4438   "pv_pe_count", FInt64;
4439   "pv_pe_alloc_count", FInt64;
4440   "pv_tags", FString;
4441   "pe_start", FBytes;
4442   "pv_mda_count", FInt64;
4443   "pv_mda_free", FBytes;
4444   (* Not in Fedora 10:
4445      "pv_mda_size", FBytes;
4446   *)
4447 ]
4448 let lvm_vg_cols = [
4449   "vg_name", FString;
4450   "vg_uuid", FUUID;
4451   "vg_fmt", FString;
4452   "vg_attr", FString (* XXX *);
4453   "vg_size", FBytes;
4454   "vg_free", FBytes;
4455   "vg_sysid", FString;
4456   "vg_extent_size", FBytes;
4457   "vg_extent_count", FInt64;
4458   "vg_free_count", FInt64;
4459   "max_lv", FInt64;
4460   "max_pv", FInt64;
4461   "pv_count", FInt64;
4462   "lv_count", FInt64;
4463   "snap_count", FInt64;
4464   "vg_seqno", FInt64;
4465   "vg_tags", FString;
4466   "vg_mda_count", FInt64;
4467   "vg_mda_free", FBytes;
4468   (* Not in Fedora 10:
4469      "vg_mda_size", FBytes;
4470   *)
4471 ]
4472 let lvm_lv_cols = [
4473   "lv_name", FString;
4474   "lv_uuid", FUUID;
4475   "lv_attr", FString (* XXX *);
4476   "lv_major", FInt64;
4477   "lv_minor", FInt64;
4478   "lv_kernel_major", FInt64;
4479   "lv_kernel_minor", FInt64;
4480   "lv_size", FBytes;
4481   "seg_count", FInt64;
4482   "origin", FString;
4483   "snap_percent", FOptPercent;
4484   "copy_percent", FOptPercent;
4485   "move_pv", FString;
4486   "lv_tags", FString;
4487   "mirror_log", FString;
4488   "modules", FString;
4489 ]
4490
4491 (* Names and fields in all structures (in RStruct and RStructList)
4492  * that we support.
4493  *)
4494 let structs = [
4495   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4496    * not use this struct in any new code.
4497    *)
4498   "int_bool", [
4499     "i", FInt32;                (* for historical compatibility *)
4500     "b", FInt32;                (* for historical compatibility *)
4501   ];
4502
4503   (* LVM PVs, VGs, LVs. *)
4504   "lvm_pv", lvm_pv_cols;
4505   "lvm_vg", lvm_vg_cols;
4506   "lvm_lv", lvm_lv_cols;
4507
4508   (* Column names and types from stat structures.
4509    * NB. Can't use things like 'st_atime' because glibc header files
4510    * define some of these as macros.  Ugh.
4511    *)
4512   "stat", [
4513     "dev", FInt64;
4514     "ino", FInt64;
4515     "mode", FInt64;
4516     "nlink", FInt64;
4517     "uid", FInt64;
4518     "gid", FInt64;
4519     "rdev", FInt64;
4520     "size", FInt64;
4521     "blksize", FInt64;
4522     "blocks", FInt64;
4523     "atime", FInt64;
4524     "mtime", FInt64;
4525     "ctime", FInt64;
4526   ];
4527   "statvfs", [
4528     "bsize", FInt64;
4529     "frsize", FInt64;
4530     "blocks", FInt64;
4531     "bfree", FInt64;
4532     "bavail", FInt64;
4533     "files", FInt64;
4534     "ffree", FInt64;
4535     "favail", FInt64;
4536     "fsid", FInt64;
4537     "flag", FInt64;
4538     "namemax", FInt64;
4539   ];
4540
4541   (* Column names in dirent structure. *)
4542   "dirent", [
4543     "ino", FInt64;
4544     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4545     "ftyp", FChar;
4546     "name", FString;
4547   ];
4548
4549   (* Version numbers. *)
4550   "version", [
4551     "major", FInt64;
4552     "minor", FInt64;
4553     "release", FInt64;
4554     "extra", FString;
4555   ];
4556
4557   (* Extended attribute. *)
4558   "xattr", [
4559     "attrname", FString;
4560     "attrval", FBuffer;
4561   ];
4562
4563   (* Inotify events. *)
4564   "inotify_event", [
4565     "in_wd", FInt64;
4566     "in_mask", FUInt32;
4567     "in_cookie", FUInt32;
4568     "in_name", FString;
4569   ];
4570
4571   (* Partition table entry. *)
4572   "partition", [
4573     "part_num", FInt32;
4574     "part_start", FBytes;
4575     "part_end", FBytes;
4576     "part_size", FBytes;
4577   ];
4578 ] (* end of structs *)
4579
4580 (* Ugh, Java has to be different ..
4581  * These names are also used by the Haskell bindings.
4582  *)
4583 let java_structs = [
4584   "int_bool", "IntBool";
4585   "lvm_pv", "PV";
4586   "lvm_vg", "VG";
4587   "lvm_lv", "LV";
4588   "stat", "Stat";
4589   "statvfs", "StatVFS";
4590   "dirent", "Dirent";
4591   "version", "Version";
4592   "xattr", "XAttr";
4593   "inotify_event", "INotifyEvent";
4594   "partition", "Partition";
4595 ]
4596
4597 (* What structs are actually returned. *)
4598 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4599
4600 (* Returns a list of RStruct/RStructList structs that are returned
4601  * by any function.  Each element of returned list is a pair:
4602  *
4603  * (structname, RStructOnly)
4604  *    == there exists function which returns RStruct (_, structname)
4605  * (structname, RStructListOnly)
4606  *    == there exists function which returns RStructList (_, structname)
4607  * (structname, RStructAndList)
4608  *    == there are functions returning both RStruct (_, structname)
4609  *                                      and RStructList (_, structname)
4610  *)
4611 let rstructs_used_by functions =
4612   (* ||| is a "logical OR" for rstructs_used_t *)
4613   let (|||) a b =
4614     match a, b with
4615     | RStructAndList, _
4616     | _, RStructAndList -> RStructAndList
4617     | RStructOnly, RStructListOnly
4618     | RStructListOnly, RStructOnly -> RStructAndList
4619     | RStructOnly, RStructOnly -> RStructOnly
4620     | RStructListOnly, RStructListOnly -> RStructListOnly
4621   in
4622
4623   let h = Hashtbl.create 13 in
4624
4625   (* if elem->oldv exists, update entry using ||| operator,
4626    * else just add elem->newv to the hash
4627    *)
4628   let update elem newv =
4629     try  let oldv = Hashtbl.find h elem in
4630          Hashtbl.replace h elem (newv ||| oldv)
4631     with Not_found -> Hashtbl.add h elem newv
4632   in
4633
4634   List.iter (
4635     fun (_, style, _, _, _, _, _) ->
4636       match fst style with
4637       | RStruct (_, structname) -> update structname RStructOnly
4638       | RStructList (_, structname) -> update structname RStructListOnly
4639       | _ -> ()
4640   ) functions;
4641
4642   (* return key->values as a list of (key,value) *)
4643   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4644
4645 (* Used for testing language bindings. *)
4646 type callt =
4647   | CallString of string
4648   | CallOptString of string option
4649   | CallStringList of string list
4650   | CallInt of int
4651   | CallInt64 of int64
4652   | CallBool of bool
4653
4654 (* Used to memoize the result of pod2text. *)
4655 let pod2text_memo_filename = "src/.pod2text.data"
4656 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4657   try
4658     let chan = open_in pod2text_memo_filename in
4659     let v = input_value chan in
4660     close_in chan;
4661     v
4662   with
4663     _ -> Hashtbl.create 13
4664 let pod2text_memo_updated () =
4665   let chan = open_out pod2text_memo_filename in
4666   output_value chan pod2text_memo;
4667   close_out chan
4668
4669 (* Useful functions.
4670  * Note we don't want to use any external OCaml libraries which
4671  * makes this a bit harder than it should be.
4672  *)
4673 module StringMap = Map.Make (String)
4674
4675 let failwithf fs = ksprintf failwith fs
4676
4677 let unique = let i = ref 0 in fun () -> incr i; !i
4678
4679 let replace_char s c1 c2 =
4680   let s2 = String.copy s in
4681   let r = ref false in
4682   for i = 0 to String.length s2 - 1 do
4683     if String.unsafe_get s2 i = c1 then (
4684       String.unsafe_set s2 i c2;
4685       r := true
4686     )
4687   done;
4688   if not !r then s else s2
4689
4690 let isspace c =
4691   c = ' '
4692   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4693
4694 let triml ?(test = isspace) str =
4695   let i = ref 0 in
4696   let n = ref (String.length str) in
4697   while !n > 0 && test str.[!i]; do
4698     decr n;
4699     incr i
4700   done;
4701   if !i = 0 then str
4702   else String.sub str !i !n
4703
4704 let trimr ?(test = isspace) str =
4705   let n = ref (String.length str) in
4706   while !n > 0 && test str.[!n-1]; do
4707     decr n
4708   done;
4709   if !n = String.length str then str
4710   else String.sub str 0 !n
4711
4712 let trim ?(test = isspace) str =
4713   trimr ~test (triml ~test str)
4714
4715 let rec find s sub =
4716   let len = String.length s in
4717   let sublen = String.length sub in
4718   let rec loop i =
4719     if i <= len-sublen then (
4720       let rec loop2 j =
4721         if j < sublen then (
4722           if s.[i+j] = sub.[j] then loop2 (j+1)
4723           else -1
4724         ) else
4725           i (* found *)
4726       in
4727       let r = loop2 0 in
4728       if r = -1 then loop (i+1) else r
4729     ) else
4730       -1 (* not found *)
4731   in
4732   loop 0
4733
4734 let rec replace_str s s1 s2 =
4735   let len = String.length s in
4736   let sublen = String.length s1 in
4737   let i = find s s1 in
4738   if i = -1 then s
4739   else (
4740     let s' = String.sub s 0 i in
4741     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4742     s' ^ s2 ^ replace_str s'' s1 s2
4743   )
4744
4745 let rec string_split sep str =
4746   let len = String.length str in
4747   let seplen = String.length sep in
4748   let i = find str sep in
4749   if i = -1 then [str]
4750   else (
4751     let s' = String.sub str 0 i in
4752     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4753     s' :: string_split sep s''
4754   )
4755
4756 let files_equal n1 n2 =
4757   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4758   match Sys.command cmd with
4759   | 0 -> true
4760   | 1 -> false
4761   | i -> failwithf "%s: failed with error code %d" cmd i
4762
4763 let rec filter_map f = function
4764   | [] -> []
4765   | x :: xs ->
4766       match f x with
4767       | Some y -> y :: filter_map f xs
4768       | None -> filter_map f xs
4769
4770 let rec find_map f = function
4771   | [] -> raise Not_found
4772   | x :: xs ->
4773       match f x with
4774       | Some y -> y
4775       | None -> find_map f xs
4776
4777 let iteri f xs =
4778   let rec loop i = function
4779     | [] -> ()
4780     | x :: xs -> f i x; loop (i+1) xs
4781   in
4782   loop 0 xs
4783
4784 let mapi f xs =
4785   let rec loop i = function
4786     | [] -> []
4787     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4788   in
4789   loop 0 xs
4790
4791 let count_chars c str =
4792   let count = ref 0 in
4793   for i = 0 to String.length str - 1 do
4794     if c = String.unsafe_get str i then incr count
4795   done;
4796   !count
4797
4798 let name_of_argt = function
4799   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4800   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4801   | FileIn n | FileOut n -> n
4802
4803 let java_name_of_struct typ =
4804   try List.assoc typ java_structs
4805   with Not_found ->
4806     failwithf
4807       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4808
4809 let cols_of_struct typ =
4810   try List.assoc typ structs
4811   with Not_found ->
4812     failwithf "cols_of_struct: unknown struct %s" typ
4813
4814 let seq_of_test = function
4815   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4816   | TestOutputListOfDevices (s, _)
4817   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4818   | TestOutputTrue s | TestOutputFalse s
4819   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4820   | TestOutputStruct (s, _)
4821   | TestLastFail s -> s
4822
4823 (* Handling for function flags. *)
4824 let protocol_limit_warning =
4825   "Because of the message protocol, there is a transfer limit
4826 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4827
4828 let danger_will_robinson =
4829   "B<This command is dangerous.  Without careful use you
4830 can easily destroy all your data>."
4831
4832 let deprecation_notice flags =
4833   try
4834     let alt =
4835       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4836     let txt =
4837       sprintf "This function is deprecated.
4838 In new code, use the C<%s> call instead.
4839
4840 Deprecated functions will not be removed from the API, but the
4841 fact that they are deprecated indicates that there are problems
4842 with correct use of these functions." alt in
4843     Some txt
4844   with
4845     Not_found -> None
4846
4847 (* Create list of optional groups. *)
4848 let optgroups =
4849   let h = Hashtbl.create 13 in
4850   List.iter (
4851     fun (name, _, _, flags, _, _, _) ->
4852       List.iter (
4853         function
4854         | Optional group ->
4855             let names = try Hashtbl.find h group with Not_found -> [] in
4856             Hashtbl.replace h group (name :: names)
4857         | _ -> ()
4858       ) flags
4859   ) daemon_functions;
4860   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4861   let groups =
4862     List.map (
4863       fun group -> group, List.sort compare (Hashtbl.find h group)
4864     ) groups in
4865   List.sort (fun x y -> compare (fst x) (fst y)) groups
4866
4867 (* Check function names etc. for consistency. *)
4868 let check_functions () =
4869   let contains_uppercase str =
4870     let len = String.length str in
4871     let rec loop i =
4872       if i >= len then false
4873       else (
4874         let c = str.[i] in
4875         if c >= 'A' && c <= 'Z' then true
4876         else loop (i+1)
4877       )
4878     in
4879     loop 0
4880   in
4881
4882   (* Check function names. *)
4883   List.iter (
4884     fun (name, _, _, _, _, _, _) ->
4885       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4886         failwithf "function name %s does not need 'guestfs' prefix" name;
4887       if name = "" then
4888         failwithf "function name is empty";
4889       if name.[0] < 'a' || name.[0] > 'z' then
4890         failwithf "function name %s must start with lowercase a-z" name;
4891       if String.contains name '-' then
4892         failwithf "function name %s should not contain '-', use '_' instead."
4893           name
4894   ) all_functions;
4895
4896   (* Check function parameter/return names. *)
4897   List.iter (
4898     fun (name, style, _, _, _, _, _) ->
4899       let check_arg_ret_name n =
4900         if contains_uppercase n then
4901           failwithf "%s param/ret %s should not contain uppercase chars"
4902             name n;
4903         if String.contains n '-' || String.contains n '_' then
4904           failwithf "%s param/ret %s should not contain '-' or '_'"
4905             name n;
4906         if n = "value" then
4907           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;
4908         if n = "int" || n = "char" || n = "short" || n = "long" then
4909           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4910         if n = "i" || n = "n" then
4911           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4912         if n = "argv" || n = "args" then
4913           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4914
4915         (* List Haskell, OCaml and C keywords here.
4916          * http://www.haskell.org/haskellwiki/Keywords
4917          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4918          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4919          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4920          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4921          * Omitting _-containing words, since they're handled above.
4922          * Omitting the OCaml reserved word, "val", is ok,
4923          * and saves us from renaming several parameters.
4924          *)
4925         let reserved = [
4926           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4927           "char"; "class"; "const"; "constraint"; "continue"; "data";
4928           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4929           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4930           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4931           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4932           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4933           "interface";
4934           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4935           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4936           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4937           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4938           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4939           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4940           "volatile"; "when"; "where"; "while";
4941           ] in
4942         if List.mem n reserved then
4943           failwithf "%s has param/ret using reserved word %s" name n;
4944       in
4945
4946       (match fst style with
4947        | RErr -> ()
4948        | RInt n | RInt64 n | RBool n
4949        | RConstString n | RConstOptString n | RString n
4950        | RStringList n | RStruct (n, _) | RStructList (n, _)
4951        | RHashtable n | RBufferOut n ->
4952            check_arg_ret_name n
4953       );
4954       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4955   ) all_functions;
4956
4957   (* Check short descriptions. *)
4958   List.iter (
4959     fun (name, _, _, _, _, shortdesc, _) ->
4960       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4961         failwithf "short description of %s should begin with lowercase." name;
4962       let c = shortdesc.[String.length shortdesc-1] in
4963       if c = '\n' || c = '.' then
4964         failwithf "short description of %s should not end with . or \\n." name
4965   ) all_functions;
4966
4967   (* Check long dscriptions. *)
4968   List.iter (
4969     fun (name, _, _, _, _, _, longdesc) ->
4970       if longdesc.[String.length longdesc-1] = '\n' then
4971         failwithf "long description of %s should not end with \\n." name
4972   ) all_functions;
4973
4974   (* Check proc_nrs. *)
4975   List.iter (
4976     fun (name, _, proc_nr, _, _, _, _) ->
4977       if proc_nr <= 0 then
4978         failwithf "daemon function %s should have proc_nr > 0" name
4979   ) daemon_functions;
4980
4981   List.iter (
4982     fun (name, _, proc_nr, _, _, _, _) ->
4983       if proc_nr <> -1 then
4984         failwithf "non-daemon function %s should have proc_nr -1" name
4985   ) non_daemon_functions;
4986
4987   let proc_nrs =
4988     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4989       daemon_functions in
4990   let proc_nrs =
4991     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4992   let rec loop = function
4993     | [] -> ()
4994     | [_] -> ()
4995     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4996         loop rest
4997     | (name1,nr1) :: (name2,nr2) :: _ ->
4998         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4999           name1 name2 nr1 nr2
5000   in
5001   loop proc_nrs;
5002
5003   (* Check tests. *)
5004   List.iter (
5005     function
5006       (* Ignore functions that have no tests.  We generate a
5007        * warning when the user does 'make check' instead.
5008        *)
5009     | name, _, _, _, [], _, _ -> ()
5010     | name, _, _, _, tests, _, _ ->
5011         let funcs =
5012           List.map (
5013             fun (_, _, test) ->
5014               match seq_of_test test with
5015               | [] ->
5016                   failwithf "%s has a test containing an empty sequence" name
5017               | cmds -> List.map List.hd cmds
5018           ) tests in
5019         let funcs = List.flatten funcs in
5020
5021         let tested = List.mem name funcs in
5022
5023         if not tested then
5024           failwithf "function %s has tests but does not test itself" name
5025   ) all_functions
5026
5027 (* 'pr' prints to the current output file. *)
5028 let chan = ref Pervasives.stdout
5029 let lines = ref 0
5030 let pr fs =
5031   ksprintf
5032     (fun str ->
5033        let i = count_chars '\n' str in
5034        lines := !lines + i;
5035        output_string !chan str
5036     ) fs
5037
5038 let copyright_years =
5039   let this_year = 1900 + (localtime (time ())).tm_year in
5040   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5041
5042 (* Generate a header block in a number of standard styles. *)
5043 type comment_style =
5044     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5045 type license = GPLv2plus | LGPLv2plus
5046
5047 let generate_header ?(extra_inputs = []) comment license =
5048   let inputs = "src/generator.ml" :: extra_inputs in
5049   let c = match comment with
5050     | CStyle ->         pr "/* "; " *"
5051     | CPlusPlusStyle -> pr "// "; "//"
5052     | HashStyle ->      pr "# ";  "#"
5053     | OCamlStyle ->     pr "(* "; " *"
5054     | HaskellStyle ->   pr "{- "; "  " in
5055   pr "libguestfs generated file\n";
5056   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5057   List.iter (pr "%s   %s\n" c) inputs;
5058   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5059   pr "%s\n" c;
5060   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5061   pr "%s\n" c;
5062   (match license with
5063    | GPLv2plus ->
5064        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5065        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5066        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5067        pr "%s (at your option) any later version.\n" c;
5068        pr "%s\n" c;
5069        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5070        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5071        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5072        pr "%s GNU General Public License for more details.\n" c;
5073        pr "%s\n" c;
5074        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5075        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5076        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5077
5078    | LGPLv2plus ->
5079        pr "%s This library is free software; you can redistribute it and/or\n" c;
5080        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5081        pr "%s License as published by the Free Software Foundation; either\n" c;
5082        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5083        pr "%s\n" c;
5084        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5085        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5086        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5087        pr "%s Lesser General Public License for more details.\n" c;
5088        pr "%s\n" c;
5089        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5090        pr "%s License along with this library; if not, write to the Free Software\n" c;
5091        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5092   );
5093   (match comment with
5094    | CStyle -> pr " */\n"
5095    | CPlusPlusStyle
5096    | HashStyle -> ()
5097    | OCamlStyle -> pr " *)\n"
5098    | HaskellStyle -> pr "-}\n"
5099   );
5100   pr "\n"
5101
5102 (* Start of main code generation functions below this line. *)
5103
5104 (* Generate the pod documentation for the C API. *)
5105 let rec generate_actions_pod () =
5106   List.iter (
5107     fun (shortname, style, _, flags, _, _, longdesc) ->
5108       if not (List.mem NotInDocs flags) then (
5109         let name = "guestfs_" ^ shortname in
5110         pr "=head2 %s\n\n" name;
5111         pr " ";
5112         generate_prototype ~extern:false ~handle:"handle" name style;
5113         pr "\n\n";
5114         pr "%s\n\n" longdesc;
5115         (match fst style with
5116          | RErr ->
5117              pr "This function returns 0 on success or -1 on error.\n\n"
5118          | RInt _ ->
5119              pr "On error this function returns -1.\n\n"
5120          | RInt64 _ ->
5121              pr "On error this function returns -1.\n\n"
5122          | RBool _ ->
5123              pr "This function returns a C truth value on success or -1 on error.\n\n"
5124          | RConstString _ ->
5125              pr "This function returns a string, or NULL on error.
5126 The string is owned by the guest handle and must I<not> be freed.\n\n"
5127          | RConstOptString _ ->
5128              pr "This function returns a string which may be NULL.
5129 There is way to return an error from this function.
5130 The string is owned by the guest handle and must I<not> be freed.\n\n"
5131          | RString _ ->
5132              pr "This function returns a string, or NULL on error.
5133 I<The caller must free the returned string after use>.\n\n"
5134          | RStringList _ ->
5135              pr "This function returns a NULL-terminated array of strings
5136 (like L<environ(3)>), or NULL if there was an error.
5137 I<The caller must free the strings and the array after use>.\n\n"
5138          | RStruct (_, typ) ->
5139              pr "This function returns a C<struct guestfs_%s *>,
5140 or NULL if there was an error.
5141 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5142          | RStructList (_, typ) ->
5143              pr "This function returns a C<struct guestfs_%s_list *>
5144 (see E<lt>guestfs-structs.hE<gt>),
5145 or NULL if there was an error.
5146 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5147          | RHashtable _ ->
5148              pr "This function returns a NULL-terminated array of
5149 strings, or NULL if there was an error.
5150 The array of strings will always have length C<2n+1>, where
5151 C<n> keys and values alternate, followed by the trailing NULL entry.
5152 I<The caller must free the strings and the array after use>.\n\n"
5153          | RBufferOut _ ->
5154              pr "This function returns a buffer, or NULL on error.
5155 The size of the returned buffer is written to C<*size_r>.
5156 I<The caller must free the returned buffer after use>.\n\n"
5157         );
5158         if List.mem ProtocolLimitWarning flags then
5159           pr "%s\n\n" protocol_limit_warning;
5160         if List.mem DangerWillRobinson flags then
5161           pr "%s\n\n" danger_will_robinson;
5162         match deprecation_notice flags with
5163         | None -> ()
5164         | Some txt -> pr "%s\n\n" txt
5165       )
5166   ) all_functions_sorted
5167
5168 and generate_structs_pod () =
5169   (* Structs documentation. *)
5170   List.iter (
5171     fun (typ, cols) ->
5172       pr "=head2 guestfs_%s\n" typ;
5173       pr "\n";
5174       pr " struct guestfs_%s {\n" typ;
5175       List.iter (
5176         function
5177         | name, FChar -> pr "   char %s;\n" name
5178         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5179         | name, FInt32 -> pr "   int32_t %s;\n" name
5180         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5181         | name, FInt64 -> pr "   int64_t %s;\n" name
5182         | name, FString -> pr "   char *%s;\n" name
5183         | name, FBuffer ->
5184             pr "   /* The next two fields describe a byte array. */\n";
5185             pr "   uint32_t %s_len;\n" name;
5186             pr "   char *%s;\n" name
5187         | name, FUUID ->
5188             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5189             pr "   char %s[32];\n" name
5190         | name, FOptPercent ->
5191             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5192             pr "   float %s;\n" name
5193       ) cols;
5194       pr " };\n";
5195       pr " \n";
5196       pr " struct guestfs_%s_list {\n" typ;
5197       pr "   uint32_t len; /* Number of elements in list. */\n";
5198       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5199       pr " };\n";
5200       pr " \n";
5201       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5202       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5203         typ typ;
5204       pr "\n"
5205   ) structs
5206
5207 and generate_availability_pod () =
5208   (* Availability documentation. *)
5209   pr "=over 4\n";
5210   pr "\n";
5211   List.iter (
5212     fun (group, functions) ->
5213       pr "=item B<%s>\n" group;
5214       pr "\n";
5215       pr "The following functions:\n";
5216       List.iter (pr "L</guestfs_%s>\n") functions;
5217       pr "\n"
5218   ) optgroups;
5219   pr "=back\n";
5220   pr "\n"
5221
5222 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5223  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5224  *
5225  * We have to use an underscore instead of a dash because otherwise
5226  * rpcgen generates incorrect code.
5227  *
5228  * This header is NOT exported to clients, but see also generate_structs_h.
5229  *)
5230 and generate_xdr () =
5231   generate_header CStyle LGPLv2plus;
5232
5233   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5234   pr "typedef string str<>;\n";
5235   pr "\n";
5236
5237   (* Internal structures. *)
5238   List.iter (
5239     function
5240     | typ, cols ->
5241         pr "struct guestfs_int_%s {\n" typ;
5242         List.iter (function
5243                    | name, FChar -> pr "  char %s;\n" name
5244                    | name, FString -> pr "  string %s<>;\n" name
5245                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5246                    | name, FUUID -> pr "  opaque %s[32];\n" name
5247                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5248                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5249                    | name, FOptPercent -> pr "  float %s;\n" name
5250                   ) cols;
5251         pr "};\n";
5252         pr "\n";
5253         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5254         pr "\n";
5255   ) structs;
5256
5257   List.iter (
5258     fun (shortname, style, _, _, _, _, _) ->
5259       let name = "guestfs_" ^ shortname in
5260
5261       (match snd style with
5262        | [] -> ()
5263        | args ->
5264            pr "struct %s_args {\n" name;
5265            List.iter (
5266              function
5267              | Pathname n | Device n | Dev_or_Path n | String n ->
5268                  pr "  string %s<>;\n" n
5269              | OptString n -> pr "  str *%s;\n" n
5270              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5271              | Bool n -> pr "  bool %s;\n" n
5272              | Int n -> pr "  int %s;\n" n
5273              | Int64 n -> pr "  hyper %s;\n" n
5274              | FileIn _ | FileOut _ -> ()
5275            ) args;
5276            pr "};\n\n"
5277       );
5278       (match fst style with
5279        | RErr -> ()
5280        | RInt n ->
5281            pr "struct %s_ret {\n" name;
5282            pr "  int %s;\n" n;
5283            pr "};\n\n"
5284        | RInt64 n ->
5285            pr "struct %s_ret {\n" name;
5286            pr "  hyper %s;\n" n;
5287            pr "};\n\n"
5288        | RBool n ->
5289            pr "struct %s_ret {\n" name;
5290            pr "  bool %s;\n" n;
5291            pr "};\n\n"
5292        | RConstString _ | RConstOptString _ ->
5293            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5294        | RString n ->
5295            pr "struct %s_ret {\n" name;
5296            pr "  string %s<>;\n" n;
5297            pr "};\n\n"
5298        | RStringList n ->
5299            pr "struct %s_ret {\n" name;
5300            pr "  str %s<>;\n" n;
5301            pr "};\n\n"
5302        | RStruct (n, typ) ->
5303            pr "struct %s_ret {\n" name;
5304            pr "  guestfs_int_%s %s;\n" typ n;
5305            pr "};\n\n"
5306        | RStructList (n, typ) ->
5307            pr "struct %s_ret {\n" name;
5308            pr "  guestfs_int_%s_list %s;\n" typ n;
5309            pr "};\n\n"
5310        | RHashtable n ->
5311            pr "struct %s_ret {\n" name;
5312            pr "  str %s<>;\n" n;
5313            pr "};\n\n"
5314        | RBufferOut n ->
5315            pr "struct %s_ret {\n" name;
5316            pr "  opaque %s<>;\n" n;
5317            pr "};\n\n"
5318       );
5319   ) daemon_functions;
5320
5321   (* Table of procedure numbers. *)
5322   pr "enum guestfs_procedure {\n";
5323   List.iter (
5324     fun (shortname, _, proc_nr, _, _, _, _) ->
5325       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5326   ) daemon_functions;
5327   pr "  GUESTFS_PROC_NR_PROCS\n";
5328   pr "};\n";
5329   pr "\n";
5330
5331   (* Having to choose a maximum message size is annoying for several
5332    * reasons (it limits what we can do in the API), but it (a) makes
5333    * the protocol a lot simpler, and (b) provides a bound on the size
5334    * of the daemon which operates in limited memory space.
5335    *)
5336   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5337   pr "\n";
5338
5339   (* Message header, etc. *)
5340   pr "\
5341 /* The communication protocol is now documented in the guestfs(3)
5342  * manpage.
5343  */
5344
5345 const GUESTFS_PROGRAM = 0x2000F5F5;
5346 const GUESTFS_PROTOCOL_VERSION = 1;
5347
5348 /* These constants must be larger than any possible message length. */
5349 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5350 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5351
5352 enum guestfs_message_direction {
5353   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5354   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5355 };
5356
5357 enum guestfs_message_status {
5358   GUESTFS_STATUS_OK = 0,
5359   GUESTFS_STATUS_ERROR = 1
5360 };
5361
5362 const GUESTFS_ERROR_LEN = 256;
5363
5364 struct guestfs_message_error {
5365   string error_message<GUESTFS_ERROR_LEN>;
5366 };
5367
5368 struct guestfs_message_header {
5369   unsigned prog;                     /* GUESTFS_PROGRAM */
5370   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5371   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5372   guestfs_message_direction direction;
5373   unsigned serial;                   /* message serial number */
5374   guestfs_message_status status;
5375 };
5376
5377 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5378
5379 struct guestfs_chunk {
5380   int cancel;                        /* if non-zero, transfer is cancelled */
5381   /* data size is 0 bytes if the transfer has finished successfully */
5382   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5383 };
5384 "
5385
5386 (* Generate the guestfs-structs.h file. *)
5387 and generate_structs_h () =
5388   generate_header CStyle LGPLv2plus;
5389
5390   (* This is a public exported header file containing various
5391    * structures.  The structures are carefully written to have
5392    * exactly the same in-memory format as the XDR structures that
5393    * we use on the wire to the daemon.  The reason for creating
5394    * copies of these structures here is just so we don't have to
5395    * export the whole of guestfs_protocol.h (which includes much
5396    * unrelated and XDR-dependent stuff that we don't want to be
5397    * public, or required by clients).
5398    *
5399    * To reiterate, we will pass these structures to and from the
5400    * client with a simple assignment or memcpy, so the format
5401    * must be identical to what rpcgen / the RFC defines.
5402    *)
5403
5404   (* Public structures. *)
5405   List.iter (
5406     fun (typ, cols) ->
5407       pr "struct guestfs_%s {\n" typ;
5408       List.iter (
5409         function
5410         | name, FChar -> pr "  char %s;\n" name
5411         | name, FString -> pr "  char *%s;\n" name
5412         | name, FBuffer ->
5413             pr "  uint32_t %s_len;\n" name;
5414             pr "  char *%s;\n" name
5415         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5416         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5417         | name, FInt32 -> pr "  int32_t %s;\n" name
5418         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5419         | name, FInt64 -> pr "  int64_t %s;\n" name
5420         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5421       ) cols;
5422       pr "};\n";
5423       pr "\n";
5424       pr "struct guestfs_%s_list {\n" typ;
5425       pr "  uint32_t len;\n";
5426       pr "  struct guestfs_%s *val;\n" typ;
5427       pr "};\n";
5428       pr "\n";
5429       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5430       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5431       pr "\n"
5432   ) structs
5433
5434 (* Generate the guestfs-actions.h file. *)
5435 and generate_actions_h () =
5436   generate_header CStyle LGPLv2plus;
5437   List.iter (
5438     fun (shortname, style, _, _, _, _, _) ->
5439       let name = "guestfs_" ^ shortname in
5440       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5441         name style
5442   ) all_functions
5443
5444 (* Generate the guestfs-internal-actions.h file. *)
5445 and generate_internal_actions_h () =
5446   generate_header CStyle LGPLv2plus;
5447   List.iter (
5448     fun (shortname, style, _, _, _, _, _) ->
5449       let name = "guestfs__" ^ shortname in
5450       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5451         name style
5452   ) non_daemon_functions
5453
5454 (* Generate the client-side dispatch stubs. *)
5455 and generate_client_actions () =
5456   generate_header CStyle LGPLv2plus;
5457
5458   pr "\
5459 #include <stdio.h>
5460 #include <stdlib.h>
5461 #include <stdint.h>
5462 #include <string.h>
5463 #include <inttypes.h>
5464
5465 #include \"guestfs.h\"
5466 #include \"guestfs-internal.h\"
5467 #include \"guestfs-internal-actions.h\"
5468 #include \"guestfs_protocol.h\"
5469
5470 #define error guestfs_error
5471 //#define perrorf guestfs_perrorf
5472 #define safe_malloc guestfs_safe_malloc
5473 #define safe_realloc guestfs_safe_realloc
5474 //#define safe_strdup guestfs_safe_strdup
5475 #define safe_memdup guestfs_safe_memdup
5476
5477 /* Check the return message from a call for validity. */
5478 static int
5479 check_reply_header (guestfs_h *g,
5480                     const struct guestfs_message_header *hdr,
5481                     unsigned int proc_nr, unsigned int serial)
5482 {
5483   if (hdr->prog != GUESTFS_PROGRAM) {
5484     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5485     return -1;
5486   }
5487   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5488     error (g, \"wrong protocol version (%%d/%%d)\",
5489            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5490     return -1;
5491   }
5492   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5493     error (g, \"unexpected message direction (%%d/%%d)\",
5494            hdr->direction, GUESTFS_DIRECTION_REPLY);
5495     return -1;
5496   }
5497   if (hdr->proc != proc_nr) {
5498     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5499     return -1;
5500   }
5501   if (hdr->serial != serial) {
5502     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5503     return -1;
5504   }
5505
5506   return 0;
5507 }
5508
5509 /* Check we are in the right state to run a high-level action. */
5510 static int
5511 check_state (guestfs_h *g, const char *caller)
5512 {
5513   if (!guestfs__is_ready (g)) {
5514     if (guestfs__is_config (g) || guestfs__is_launching (g))
5515       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5516         caller);
5517     else
5518       error (g, \"%%s called from the wrong state, %%d != READY\",
5519         caller, guestfs__get_state (g));
5520     return -1;
5521   }
5522   return 0;
5523 }
5524
5525 ";
5526
5527   (* Generate code to generate guestfish call traces. *)
5528   let trace_call shortname style =
5529     pr "  if (guestfs__get_trace (g)) {\n";
5530
5531     let needs_i =
5532       List.exists (function
5533                    | StringList _ | DeviceList _ -> true
5534                    | _ -> false) (snd style) in
5535     if needs_i then (
5536       pr "    int i;\n";
5537       pr "\n"
5538     );
5539
5540     pr "    printf (\"%s\");\n" shortname;
5541     List.iter (
5542       function
5543       | String n                        (* strings *)
5544       | Device n
5545       | Pathname n
5546       | Dev_or_Path n
5547       | FileIn n
5548       | FileOut n ->
5549           (* guestfish doesn't support string escaping, so neither do we *)
5550           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5551       | OptString n ->                  (* string option *)
5552           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5553           pr "    else printf (\" null\");\n"
5554       | StringList n
5555       | DeviceList n ->                 (* string list *)
5556           pr "    putchar (' ');\n";
5557           pr "    putchar ('\"');\n";
5558           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5559           pr "      if (i > 0) putchar (' ');\n";
5560           pr "      fputs (%s[i], stdout);\n" n;
5561           pr "    }\n";
5562           pr "    putchar ('\"');\n";
5563       | Bool n ->                       (* boolean *)
5564           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5565       | Int n ->                        (* int *)
5566           pr "    printf (\" %%d\", %s);\n" n
5567       | Int64 n ->
5568           pr "    printf (\" %%\" PRIi64, %s);\n" n
5569     ) (snd style);
5570     pr "    putchar ('\\n');\n";
5571     pr "  }\n";
5572     pr "\n";
5573   in
5574
5575   (* For non-daemon functions, generate a wrapper around each function. *)
5576   List.iter (
5577     fun (shortname, style, _, _, _, _, _) ->
5578       let name = "guestfs_" ^ shortname in
5579
5580       generate_prototype ~extern:false ~semicolon:false ~newline:true
5581         ~handle:"g" name style;
5582       pr "{\n";
5583       trace_call shortname style;
5584       pr "  return guestfs__%s " shortname;
5585       generate_c_call_args ~handle:"g" style;
5586       pr ";\n";
5587       pr "}\n";
5588       pr "\n"
5589   ) non_daemon_functions;
5590
5591   (* Client-side stubs for each function. *)
5592   List.iter (
5593     fun (shortname, style, _, _, _, _, _) ->
5594       let name = "guestfs_" ^ shortname in
5595
5596       (* Generate the action stub. *)
5597       generate_prototype ~extern:false ~semicolon:false ~newline:true
5598         ~handle:"g" name style;
5599
5600       let error_code =
5601         match fst style with
5602         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5603         | RConstString _ | RConstOptString _ ->
5604             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5605         | RString _ | RStringList _
5606         | RStruct _ | RStructList _
5607         | RHashtable _ | RBufferOut _ ->
5608             "NULL" in
5609
5610       pr "{\n";
5611
5612       (match snd style with
5613        | [] -> ()
5614        | _ -> pr "  struct %s_args args;\n" name
5615       );
5616
5617       pr "  guestfs_message_header hdr;\n";
5618       pr "  guestfs_message_error err;\n";
5619       let has_ret =
5620         match fst style with
5621         | RErr -> false
5622         | RConstString _ | RConstOptString _ ->
5623             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5624         | RInt _ | RInt64 _
5625         | RBool _ | RString _ | RStringList _
5626         | RStruct _ | RStructList _
5627         | RHashtable _ | RBufferOut _ ->
5628             pr "  struct %s_ret ret;\n" name;
5629             true in
5630
5631       pr "  int serial;\n";
5632       pr "  int r;\n";
5633       pr "\n";
5634       trace_call shortname style;
5635       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5636       pr "  guestfs___set_busy (g);\n";
5637       pr "\n";
5638
5639       (* Send the main header and arguments. *)
5640       (match snd style with
5641        | [] ->
5642            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5643              (String.uppercase shortname)
5644        | args ->
5645            List.iter (
5646              function
5647              | Pathname n | Device n | Dev_or_Path n | String n ->
5648                  pr "  args.%s = (char *) %s;\n" n n
5649              | OptString n ->
5650                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5651              | StringList n | DeviceList n ->
5652                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5653                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5654              | Bool n ->
5655                  pr "  args.%s = %s;\n" n n
5656              | Int n ->
5657                  pr "  args.%s = %s;\n" n n
5658              | Int64 n ->
5659                  pr "  args.%s = %s;\n" n n
5660              | FileIn _ | FileOut _ -> ()
5661            ) args;
5662            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5663              (String.uppercase shortname);
5664            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5665              name;
5666       );
5667       pr "  if (serial == -1) {\n";
5668       pr "    guestfs___end_busy (g);\n";
5669       pr "    return %s;\n" error_code;
5670       pr "  }\n";
5671       pr "\n";
5672
5673       (* Send any additional files (FileIn) requested. *)
5674       let need_read_reply_label = ref false in
5675       List.iter (
5676         function
5677         | FileIn n ->
5678             pr "  r = guestfs___send_file (g, %s);\n" n;
5679             pr "  if (r == -1) {\n";
5680             pr "    guestfs___end_busy (g);\n";
5681             pr "    return %s;\n" error_code;
5682             pr "  }\n";
5683             pr "  if (r == -2) /* daemon cancelled */\n";
5684             pr "    goto read_reply;\n";
5685             need_read_reply_label := true;
5686             pr "\n";
5687         | _ -> ()
5688       ) (snd style);
5689
5690       (* Wait for the reply from the remote end. *)
5691       if !need_read_reply_label then pr " read_reply:\n";
5692       pr "  memset (&hdr, 0, sizeof hdr);\n";
5693       pr "  memset (&err, 0, sizeof err);\n";
5694       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5695       pr "\n";
5696       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5697       if not has_ret then
5698         pr "NULL, NULL"
5699       else
5700         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5701       pr ");\n";
5702
5703       pr "  if (r == -1) {\n";
5704       pr "    guestfs___end_busy (g);\n";
5705       pr "    return %s;\n" error_code;
5706       pr "  }\n";
5707       pr "\n";
5708
5709       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5710         (String.uppercase shortname);
5711       pr "    guestfs___end_busy (g);\n";
5712       pr "    return %s;\n" error_code;
5713       pr "  }\n";
5714       pr "\n";
5715
5716       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5717       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5718       pr "    free (err.error_message);\n";
5719       pr "    guestfs___end_busy (g);\n";
5720       pr "    return %s;\n" error_code;
5721       pr "  }\n";
5722       pr "\n";
5723
5724       (* Expecting to receive further files (FileOut)? *)
5725       List.iter (
5726         function
5727         | FileOut n ->
5728             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5729             pr "    guestfs___end_busy (g);\n";
5730             pr "    return %s;\n" error_code;
5731             pr "  }\n";
5732             pr "\n";
5733         | _ -> ()
5734       ) (snd style);
5735
5736       pr "  guestfs___end_busy (g);\n";
5737
5738       (match fst style with
5739        | RErr -> pr "  return 0;\n"
5740        | RInt n | RInt64 n | RBool n ->
5741            pr "  return ret.%s;\n" n
5742        | RConstString _ | RConstOptString _ ->
5743            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5744        | RString n ->
5745            pr "  return ret.%s; /* caller will free */\n" n
5746        | RStringList n | RHashtable n ->
5747            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5748            pr "  ret.%s.%s_val =\n" n n;
5749            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5750            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5751              n n;
5752            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5753            pr "  return ret.%s.%s_val;\n" n n
5754        | RStruct (n, _) ->
5755            pr "  /* caller will free this */\n";
5756            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5757        | RStructList (n, _) ->
5758            pr "  /* caller will free this */\n";
5759            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5760        | RBufferOut n ->
5761            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5762            pr "   * _val might be NULL here.  To make the API saner for\n";
5763            pr "   * callers, we turn this case into a unique pointer (using\n";
5764            pr "   * malloc(1)).\n";
5765            pr "   */\n";
5766            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5767            pr "    *size_r = ret.%s.%s_len;\n" n n;
5768            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5769            pr "  } else {\n";
5770            pr "    free (ret.%s.%s_val);\n" n n;
5771            pr "    char *p = safe_malloc (g, 1);\n";
5772            pr "    *size_r = ret.%s.%s_len;\n" n n;
5773            pr "    return p;\n";
5774            pr "  }\n";
5775       );
5776
5777       pr "}\n\n"
5778   ) daemon_functions;
5779
5780   (* Functions to free structures. *)
5781   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5782   pr " * structure format is identical to the XDR format.  See note in\n";
5783   pr " * generator.ml.\n";
5784   pr " */\n";
5785   pr "\n";
5786
5787   List.iter (
5788     fun (typ, _) ->
5789       pr "void\n";
5790       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5791       pr "{\n";
5792       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5793       pr "  free (x);\n";
5794       pr "}\n";
5795       pr "\n";
5796
5797       pr "void\n";
5798       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5799       pr "{\n";
5800       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5801       pr "  free (x);\n";
5802       pr "}\n";
5803       pr "\n";
5804
5805   ) structs;
5806
5807 (* Generate daemon/actions.h. *)
5808 and generate_daemon_actions_h () =
5809   generate_header CStyle GPLv2plus;
5810
5811   pr "#include \"../src/guestfs_protocol.h\"\n";
5812   pr "\n";
5813
5814   List.iter (
5815     fun (name, style, _, _, _, _, _) ->
5816       generate_prototype
5817         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5818         name style;
5819   ) daemon_functions
5820
5821 (* Generate the linker script which controls the visibility of
5822  * symbols in the public ABI and ensures no other symbols get
5823  * exported accidentally.
5824  *)
5825 and generate_linker_script () =
5826   generate_header HashStyle GPLv2plus;
5827
5828   let globals = [
5829     "guestfs_create";
5830     "guestfs_close";
5831     "guestfs_get_error_handler";
5832     "guestfs_get_out_of_memory_handler";
5833     "guestfs_last_error";
5834     "guestfs_set_error_handler";
5835     "guestfs_set_launch_done_callback";
5836     "guestfs_set_log_message_callback";
5837     "guestfs_set_out_of_memory_handler";
5838     "guestfs_set_subprocess_quit_callback";
5839
5840     (* Unofficial parts of the API: the bindings code use these
5841      * functions, so it is useful to export them.
5842      *)
5843     "guestfs_safe_calloc";
5844     "guestfs_safe_malloc";
5845   ] in
5846   let functions =
5847     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5848       all_functions in
5849   let structs =
5850     List.concat (
5851       List.map (fun (typ, _) ->
5852                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5853         structs
5854     ) in
5855   let globals = List.sort compare (globals @ functions @ structs) in
5856
5857   pr "{\n";
5858   pr "    global:\n";
5859   List.iter (pr "        %s;\n") globals;
5860   pr "\n";
5861
5862   pr "    local:\n";
5863   pr "        *;\n";
5864   pr "};\n"
5865
5866 (* Generate the server-side stubs. *)
5867 and generate_daemon_actions () =
5868   generate_header CStyle GPLv2plus;
5869
5870   pr "#include <config.h>\n";
5871   pr "\n";
5872   pr "#include <stdio.h>\n";
5873   pr "#include <stdlib.h>\n";
5874   pr "#include <string.h>\n";
5875   pr "#include <inttypes.h>\n";
5876   pr "#include <rpc/types.h>\n";
5877   pr "#include <rpc/xdr.h>\n";
5878   pr "\n";
5879   pr "#include \"daemon.h\"\n";
5880   pr "#include \"c-ctype.h\"\n";
5881   pr "#include \"../src/guestfs_protocol.h\"\n";
5882   pr "#include \"actions.h\"\n";
5883   pr "\n";
5884
5885   List.iter (
5886     fun (name, style, _, _, _, _, _) ->
5887       (* Generate server-side stubs. *)
5888       pr "static void %s_stub (XDR *xdr_in)\n" name;
5889       pr "{\n";
5890       let error_code =
5891         match fst style with
5892         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5893         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5894         | RBool _ -> pr "  int r;\n"; "-1"
5895         | RConstString _ | RConstOptString _ ->
5896             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5897         | RString _ -> pr "  char *r;\n"; "NULL"
5898         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5899         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5900         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5901         | RBufferOut _ ->
5902             pr "  size_t size = 1;\n";
5903             pr "  char *r;\n";
5904             "NULL" in
5905
5906       (match snd style with
5907        | [] -> ()
5908        | args ->
5909            pr "  struct guestfs_%s_args args;\n" name;
5910            List.iter (
5911              function
5912              | Device n | Dev_or_Path n
5913              | Pathname n
5914              | String n -> ()
5915              | OptString n -> pr "  char *%s;\n" n
5916              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5917              | Bool n -> pr "  int %s;\n" n
5918              | Int n -> pr "  int %s;\n" n
5919              | Int64 n -> pr "  int64_t %s;\n" n
5920              | FileIn _ | FileOut _ -> ()
5921            ) args
5922       );
5923       pr "\n";
5924
5925       (match snd style with
5926        | [] -> ()
5927        | args ->
5928            pr "  memset (&args, 0, sizeof args);\n";
5929            pr "\n";
5930            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5931            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5932            pr "    return;\n";
5933            pr "  }\n";
5934            let pr_args n =
5935              pr "  char *%s = args.%s;\n" n n
5936            in
5937            let pr_list_handling_code n =
5938              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5939              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5940              pr "  if (%s == NULL) {\n" n;
5941              pr "    reply_with_perror (\"realloc\");\n";
5942              pr "    goto done;\n";
5943              pr "  }\n";
5944              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5945              pr "  args.%s.%s_val = %s;\n" n n n;
5946            in
5947            List.iter (
5948              function
5949              | Pathname n ->
5950                  pr_args n;
5951                  pr "  ABS_PATH (%s, goto done);\n" n;
5952              | Device n ->
5953                  pr_args n;
5954                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5955              | Dev_or_Path n ->
5956                  pr_args n;
5957                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5958              | String n -> pr_args n
5959              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5960              | StringList n ->
5961                  pr_list_handling_code n;
5962              | DeviceList n ->
5963                  pr_list_handling_code n;
5964                  pr "  /* Ensure that each is a device,\n";
5965                  pr "   * and perform device name translation. */\n";
5966                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5967                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5968                  pr "  }\n";
5969              | Bool n -> pr "  %s = args.%s;\n" n n
5970              | Int n -> pr "  %s = args.%s;\n" n n
5971              | Int64 n -> pr "  %s = args.%s;\n" n n
5972              | FileIn _ | FileOut _ -> ()
5973            ) args;
5974            pr "\n"
5975       );
5976
5977
5978       (* this is used at least for do_equal *)
5979       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5980         (* Emit NEED_ROOT just once, even when there are two or
5981            more Pathname args *)
5982         pr "  NEED_ROOT (goto done);\n";
5983       );
5984
5985       (* Don't want to call the impl with any FileIn or FileOut
5986        * parameters, since these go "outside" the RPC protocol.
5987        *)
5988       let args' =
5989         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5990           (snd style) in
5991       pr "  r = do_%s " name;
5992       generate_c_call_args (fst style, args');
5993       pr ";\n";
5994
5995       (match fst style with
5996        | RErr | RInt _ | RInt64 _ | RBool _
5997        | RConstString _ | RConstOptString _
5998        | RString _ | RStringList _ | RHashtable _
5999        | RStruct (_, _) | RStructList (_, _) ->
6000            pr "  if (r == %s)\n" error_code;
6001            pr "    /* do_%s has already called reply_with_error */\n" name;
6002            pr "    goto done;\n";
6003            pr "\n"
6004        | RBufferOut _ ->
6005            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6006            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6007            pr "   */\n";
6008            pr "  if (size == 1 && r == %s)\n" error_code;
6009            pr "    /* do_%s has already called reply_with_error */\n" name;
6010            pr "    goto done;\n";
6011            pr "\n"
6012       );
6013
6014       (* If there are any FileOut parameters, then the impl must
6015        * send its own reply.
6016        *)
6017       let no_reply =
6018         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6019       if no_reply then
6020         pr "  /* do_%s has already sent a reply */\n" name
6021       else (
6022         match fst style with
6023         | RErr -> pr "  reply (NULL, NULL);\n"
6024         | RInt n | RInt64 n | RBool n ->
6025             pr "  struct guestfs_%s_ret ret;\n" name;
6026             pr "  ret.%s = r;\n" n;
6027             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6028               name
6029         | RConstString _ | RConstOptString _ ->
6030             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6031         | RString n ->
6032             pr "  struct guestfs_%s_ret ret;\n" name;
6033             pr "  ret.%s = r;\n" n;
6034             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6035               name;
6036             pr "  free (r);\n"
6037         | RStringList n | RHashtable n ->
6038             pr "  struct guestfs_%s_ret ret;\n" name;
6039             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6040             pr "  ret.%s.%s_val = r;\n" n n;
6041             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6042               name;
6043             pr "  free_strings (r);\n"
6044         | RStruct (n, _) ->
6045             pr "  struct guestfs_%s_ret ret;\n" name;
6046             pr "  ret.%s = *r;\n" n;
6047             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6048               name;
6049             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6050               name
6051         | RStructList (n, _) ->
6052             pr "  struct guestfs_%s_ret ret;\n" name;
6053             pr "  ret.%s = *r;\n" n;
6054             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6055               name;
6056             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6057               name
6058         | RBufferOut n ->
6059             pr "  struct guestfs_%s_ret ret;\n" name;
6060             pr "  ret.%s.%s_val = r;\n" n n;
6061             pr "  ret.%s.%s_len = size;\n" n n;
6062             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6063               name;
6064             pr "  free (r);\n"
6065       );
6066
6067       (* Free the args. *)
6068       (match snd style with
6069        | [] ->
6070            pr "done: ;\n";
6071        | _ ->
6072            pr "done:\n";
6073            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6074              name
6075       );
6076
6077       pr "}\n\n";
6078   ) daemon_functions;
6079
6080   (* Dispatch function. *)
6081   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6082   pr "{\n";
6083   pr "  switch (proc_nr) {\n";
6084
6085   List.iter (
6086     fun (name, style, _, _, _, _, _) ->
6087       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6088       pr "      %s_stub (xdr_in);\n" name;
6089       pr "      break;\n"
6090   ) daemon_functions;
6091
6092   pr "    default:\n";
6093   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";
6094   pr "  }\n";
6095   pr "}\n";
6096   pr "\n";
6097
6098   (* LVM columns and tokenization functions. *)
6099   (* XXX This generates crap code.  We should rethink how we
6100    * do this parsing.
6101    *)
6102   List.iter (
6103     function
6104     | typ, cols ->
6105         pr "static const char *lvm_%s_cols = \"%s\";\n"
6106           typ (String.concat "," (List.map fst cols));
6107         pr "\n";
6108
6109         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6110         pr "{\n";
6111         pr "  char *tok, *p, *next;\n";
6112         pr "  int i, j;\n";
6113         pr "\n";
6114         (*
6115           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6116           pr "\n";
6117         *)
6118         pr "  if (!str) {\n";
6119         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6120         pr "    return -1;\n";
6121         pr "  }\n";
6122         pr "  if (!*str || c_isspace (*str)) {\n";
6123         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6124         pr "    return -1;\n";
6125         pr "  }\n";
6126         pr "  tok = str;\n";
6127         List.iter (
6128           fun (name, coltype) ->
6129             pr "  if (!tok) {\n";
6130             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6131             pr "    return -1;\n";
6132             pr "  }\n";
6133             pr "  p = strchrnul (tok, ',');\n";
6134             pr "  if (*p) next = p+1; else next = NULL;\n";
6135             pr "  *p = '\\0';\n";
6136             (match coltype with
6137              | FString ->
6138                  pr "  r->%s = strdup (tok);\n" name;
6139                  pr "  if (r->%s == NULL) {\n" name;
6140                  pr "    perror (\"strdup\");\n";
6141                  pr "    return -1;\n";
6142                  pr "  }\n"
6143              | FUUID ->
6144                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6145                  pr "    if (tok[j] == '\\0') {\n";
6146                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6147                  pr "      return -1;\n";
6148                  pr "    } else if (tok[j] != '-')\n";
6149                  pr "      r->%s[i++] = tok[j];\n" name;
6150                  pr "  }\n";
6151              | FBytes ->
6152                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6153                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6154                  pr "    return -1;\n";
6155                  pr "  }\n";
6156              | FInt64 ->
6157                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6158                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6159                  pr "    return -1;\n";
6160                  pr "  }\n";
6161              | FOptPercent ->
6162                  pr "  if (tok[0] == '\\0')\n";
6163                  pr "    r->%s = -1;\n" name;
6164                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6165                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6166                  pr "    return -1;\n";
6167                  pr "  }\n";
6168              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6169                  assert false (* can never be an LVM column *)
6170             );
6171             pr "  tok = next;\n";
6172         ) cols;
6173
6174         pr "  if (tok != NULL) {\n";
6175         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6176         pr "    return -1;\n";
6177         pr "  }\n";
6178         pr "  return 0;\n";
6179         pr "}\n";
6180         pr "\n";
6181
6182         pr "guestfs_int_lvm_%s_list *\n" typ;
6183         pr "parse_command_line_%ss (void)\n" typ;
6184         pr "{\n";
6185         pr "  char *out, *err;\n";
6186         pr "  char *p, *pend;\n";
6187         pr "  int r, i;\n";
6188         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6189         pr "  void *newp;\n";
6190         pr "\n";
6191         pr "  ret = malloc (sizeof *ret);\n";
6192         pr "  if (!ret) {\n";
6193         pr "    reply_with_perror (\"malloc\");\n";
6194         pr "    return NULL;\n";
6195         pr "  }\n";
6196         pr "\n";
6197         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6198         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6199         pr "\n";
6200         pr "  r = command (&out, &err,\n";
6201         pr "           \"lvm\", \"%ss\",\n" typ;
6202         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6203         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6204         pr "  if (r == -1) {\n";
6205         pr "    reply_with_error (\"%%s\", err);\n";
6206         pr "    free (out);\n";
6207         pr "    free (err);\n";
6208         pr "    free (ret);\n";
6209         pr "    return NULL;\n";
6210         pr "  }\n";
6211         pr "\n";
6212         pr "  free (err);\n";
6213         pr "\n";
6214         pr "  /* Tokenize each line of the output. */\n";
6215         pr "  p = out;\n";
6216         pr "  i = 0;\n";
6217         pr "  while (p) {\n";
6218         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6219         pr "    if (pend) {\n";
6220         pr "      *pend = '\\0';\n";
6221         pr "      pend++;\n";
6222         pr "    }\n";
6223         pr "\n";
6224         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6225         pr "      p++;\n";
6226         pr "\n";
6227         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6228         pr "      p = pend;\n";
6229         pr "      continue;\n";
6230         pr "    }\n";
6231         pr "\n";
6232         pr "    /* Allocate some space to store this next entry. */\n";
6233         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6234         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6235         pr "    if (newp == NULL) {\n";
6236         pr "      reply_with_perror (\"realloc\");\n";
6237         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6238         pr "      free (ret);\n";
6239         pr "      free (out);\n";
6240         pr "      return NULL;\n";
6241         pr "    }\n";
6242         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6243         pr "\n";
6244         pr "    /* Tokenize the next entry. */\n";
6245         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6246         pr "    if (r == -1) {\n";
6247         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6248         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6249         pr "      free (ret);\n";
6250         pr "      free (out);\n";
6251         pr "      return NULL;\n";
6252         pr "    }\n";
6253         pr "\n";
6254         pr "    ++i;\n";
6255         pr "    p = pend;\n";
6256         pr "  }\n";
6257         pr "\n";
6258         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6259         pr "\n";
6260         pr "  free (out);\n";
6261         pr "  return ret;\n";
6262         pr "}\n"
6263
6264   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6265
6266 (* Generate a list of function names, for debugging in the daemon.. *)
6267 and generate_daemon_names () =
6268   generate_header CStyle GPLv2plus;
6269
6270   pr "#include <config.h>\n";
6271   pr "\n";
6272   pr "#include \"daemon.h\"\n";
6273   pr "\n";
6274
6275   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6276   pr "const char *function_names[] = {\n";
6277   List.iter (
6278     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6279   ) daemon_functions;
6280   pr "};\n";
6281
6282 (* Generate the optional groups for the daemon to implement
6283  * guestfs_available.
6284  *)
6285 and generate_daemon_optgroups_c () =
6286   generate_header CStyle GPLv2plus;
6287
6288   pr "#include <config.h>\n";
6289   pr "\n";
6290   pr "#include \"daemon.h\"\n";
6291   pr "#include \"optgroups.h\"\n";
6292   pr "\n";
6293
6294   pr "struct optgroup optgroups[] = {\n";
6295   List.iter (
6296     fun (group, _) ->
6297       pr "  { \"%s\", optgroup_%s_available },\n" group group
6298   ) optgroups;
6299   pr "  { NULL, NULL }\n";
6300   pr "};\n"
6301
6302 and generate_daemon_optgroups_h () =
6303   generate_header CStyle GPLv2plus;
6304
6305   List.iter (
6306     fun (group, _) ->
6307       pr "extern int optgroup_%s_available (void);\n" group
6308   ) optgroups
6309
6310 (* Generate the tests. *)
6311 and generate_tests () =
6312   generate_header CStyle GPLv2plus;
6313
6314   pr "\
6315 #include <stdio.h>
6316 #include <stdlib.h>
6317 #include <string.h>
6318 #include <unistd.h>
6319 #include <sys/types.h>
6320 #include <fcntl.h>
6321
6322 #include \"guestfs.h\"
6323 #include \"guestfs-internal.h\"
6324
6325 static guestfs_h *g;
6326 static int suppress_error = 0;
6327
6328 static void print_error (guestfs_h *g, void *data, const char *msg)
6329 {
6330   if (!suppress_error)
6331     fprintf (stderr, \"%%s\\n\", msg);
6332 }
6333
6334 /* FIXME: nearly identical code appears in fish.c */
6335 static void print_strings (char *const *argv)
6336 {
6337   int argc;
6338
6339   for (argc = 0; argv[argc] != NULL; ++argc)
6340     printf (\"\\t%%s\\n\", argv[argc]);
6341 }
6342
6343 /*
6344 static void print_table (char const *const *argv)
6345 {
6346   int i;
6347
6348   for (i = 0; argv[i] != NULL; i += 2)
6349     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6350 }
6351 */
6352
6353 ";
6354
6355   (* Generate a list of commands which are not tested anywhere. *)
6356   pr "static void no_test_warnings (void)\n";
6357   pr "{\n";
6358
6359   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6360   List.iter (
6361     fun (_, _, _, _, tests, _, _) ->
6362       let tests = filter_map (
6363         function
6364         | (_, (Always|If _|Unless _), test) -> Some test
6365         | (_, Disabled, _) -> None
6366       ) tests in
6367       let seq = List.concat (List.map seq_of_test tests) in
6368       let cmds_tested = List.map List.hd seq in
6369       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6370   ) all_functions;
6371
6372   List.iter (
6373     fun (name, _, _, _, _, _, _) ->
6374       if not (Hashtbl.mem hash name) then
6375         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6376   ) all_functions;
6377
6378   pr "}\n";
6379   pr "\n";
6380
6381   (* Generate the actual tests.  Note that we generate the tests
6382    * in reverse order, deliberately, so that (in general) the
6383    * newest tests run first.  This makes it quicker and easier to
6384    * debug them.
6385    *)
6386   let test_names =
6387     List.map (
6388       fun (name, _, _, flags, tests, _, _) ->
6389         mapi (generate_one_test name flags) tests
6390     ) (List.rev all_functions) in
6391   let test_names = List.concat test_names in
6392   let nr_tests = List.length test_names in
6393
6394   pr "\
6395 int main (int argc, char *argv[])
6396 {
6397   char c = 0;
6398   unsigned long int n_failed = 0;
6399   const char *filename;
6400   int fd;
6401   int nr_tests, test_num = 0;
6402
6403   setbuf (stdout, NULL);
6404
6405   no_test_warnings ();
6406
6407   g = guestfs_create ();
6408   if (g == NULL) {
6409     printf (\"guestfs_create FAILED\\n\");
6410     exit (EXIT_FAILURE);
6411   }
6412
6413   guestfs_set_error_handler (g, print_error, NULL);
6414
6415   guestfs_set_path (g, \"../appliance\");
6416
6417   filename = \"test1.img\";
6418   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6419   if (fd == -1) {
6420     perror (filename);
6421     exit (EXIT_FAILURE);
6422   }
6423   if (lseek (fd, %d, SEEK_SET) == -1) {
6424     perror (\"lseek\");
6425     close (fd);
6426     unlink (filename);
6427     exit (EXIT_FAILURE);
6428   }
6429   if (write (fd, &c, 1) == -1) {
6430     perror (\"write\");
6431     close (fd);
6432     unlink (filename);
6433     exit (EXIT_FAILURE);
6434   }
6435   if (close (fd) == -1) {
6436     perror (filename);
6437     unlink (filename);
6438     exit (EXIT_FAILURE);
6439   }
6440   if (guestfs_add_drive (g, filename) == -1) {
6441     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6442     exit (EXIT_FAILURE);
6443   }
6444
6445   filename = \"test2.img\";
6446   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6447   if (fd == -1) {
6448     perror (filename);
6449     exit (EXIT_FAILURE);
6450   }
6451   if (lseek (fd, %d, SEEK_SET) == -1) {
6452     perror (\"lseek\");
6453     close (fd);
6454     unlink (filename);
6455     exit (EXIT_FAILURE);
6456   }
6457   if (write (fd, &c, 1) == -1) {
6458     perror (\"write\");
6459     close (fd);
6460     unlink (filename);
6461     exit (EXIT_FAILURE);
6462   }
6463   if (close (fd) == -1) {
6464     perror (filename);
6465     unlink (filename);
6466     exit (EXIT_FAILURE);
6467   }
6468   if (guestfs_add_drive (g, filename) == -1) {
6469     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6470     exit (EXIT_FAILURE);
6471   }
6472
6473   filename = \"test3.img\";
6474   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6475   if (fd == -1) {
6476     perror (filename);
6477     exit (EXIT_FAILURE);
6478   }
6479   if (lseek (fd, %d, SEEK_SET) == -1) {
6480     perror (\"lseek\");
6481     close (fd);
6482     unlink (filename);
6483     exit (EXIT_FAILURE);
6484   }
6485   if (write (fd, &c, 1) == -1) {
6486     perror (\"write\");
6487     close (fd);
6488     unlink (filename);
6489     exit (EXIT_FAILURE);
6490   }
6491   if (close (fd) == -1) {
6492     perror (filename);
6493     unlink (filename);
6494     exit (EXIT_FAILURE);
6495   }
6496   if (guestfs_add_drive (g, filename) == -1) {
6497     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6498     exit (EXIT_FAILURE);
6499   }
6500
6501   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6502     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6503     exit (EXIT_FAILURE);
6504   }
6505
6506   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6507   alarm (600);
6508
6509   if (guestfs_launch (g) == -1) {
6510     printf (\"guestfs_launch FAILED\\n\");
6511     exit (EXIT_FAILURE);
6512   }
6513
6514   /* Cancel previous alarm. */
6515   alarm (0);
6516
6517   nr_tests = %d;
6518
6519 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6520
6521   iteri (
6522     fun i test_name ->
6523       pr "  test_num++;\n";
6524       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6525       pr "  if (%s () == -1) {\n" test_name;
6526       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6527       pr "    n_failed++;\n";
6528       pr "  }\n";
6529   ) test_names;
6530   pr "\n";
6531
6532   pr "  guestfs_close (g);\n";
6533   pr "  unlink (\"test1.img\");\n";
6534   pr "  unlink (\"test2.img\");\n";
6535   pr "  unlink (\"test3.img\");\n";
6536   pr "\n";
6537
6538   pr "  if (n_failed > 0) {\n";
6539   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6540   pr "    exit (EXIT_FAILURE);\n";
6541   pr "  }\n";
6542   pr "\n";
6543
6544   pr "  exit (EXIT_SUCCESS);\n";
6545   pr "}\n"
6546
6547 and generate_one_test name flags i (init, prereq, test) =
6548   let test_name = sprintf "test_%s_%d" name i in
6549
6550   pr "\
6551 static int %s_skip (void)
6552 {
6553   const char *str;
6554
6555   str = getenv (\"TEST_ONLY\");
6556   if (str)
6557     return strstr (str, \"%s\") == NULL;
6558   str = getenv (\"SKIP_%s\");
6559   if (str && STREQ (str, \"1\")) return 1;
6560   str = getenv (\"SKIP_TEST_%s\");
6561   if (str && STREQ (str, \"1\")) return 1;
6562   return 0;
6563 }
6564
6565 " test_name name (String.uppercase test_name) (String.uppercase name);
6566
6567   (match prereq with
6568    | Disabled | Always -> ()
6569    | If code | Unless code ->
6570        pr "static int %s_prereq (void)\n" test_name;
6571        pr "{\n";
6572        pr "  %s\n" code;
6573        pr "}\n";
6574        pr "\n";
6575   );
6576
6577   pr "\
6578 static int %s (void)
6579 {
6580   if (%s_skip ()) {
6581     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6582     return 0;
6583   }
6584
6585 " test_name test_name test_name;
6586
6587   (* Optional functions should only be tested if the relevant
6588    * support is available in the daemon.
6589    *)
6590   List.iter (
6591     function
6592     | Optional group ->
6593         pr "  {\n";
6594         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6595         pr "    int r;\n";
6596         pr "    suppress_error = 1;\n";
6597         pr "    r = guestfs_available (g, (char **) groups);\n";
6598         pr "    suppress_error = 0;\n";
6599         pr "    if (r == -1) {\n";
6600         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6601         pr "      return 0;\n";
6602         pr "    }\n";
6603         pr "  }\n";
6604     | _ -> ()
6605   ) flags;
6606
6607   (match prereq with
6608    | Disabled ->
6609        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6610    | If _ ->
6611        pr "  if (! %s_prereq ()) {\n" test_name;
6612        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6613        pr "    return 0;\n";
6614        pr "  }\n";
6615        pr "\n";
6616        generate_one_test_body name i test_name init test;
6617    | Unless _ ->
6618        pr "  if (%s_prereq ()) {\n" test_name;
6619        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6620        pr "    return 0;\n";
6621        pr "  }\n";
6622        pr "\n";
6623        generate_one_test_body name i test_name init test;
6624    | Always ->
6625        generate_one_test_body name i test_name init test
6626   );
6627
6628   pr "  return 0;\n";
6629   pr "}\n";
6630   pr "\n";
6631   test_name
6632
6633 and generate_one_test_body name i test_name init test =
6634   (match init with
6635    | InitNone (* XXX at some point, InitNone and InitEmpty became
6636                * folded together as the same thing.  Really we should
6637                * make InitNone do nothing at all, but the tests may
6638                * need to be checked to make sure this is OK.
6639                *)
6640    | InitEmpty ->
6641        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6642        List.iter (generate_test_command_call test_name)
6643          [["blockdev_setrw"; "/dev/sda"];
6644           ["umount_all"];
6645           ["lvm_remove_all"]]
6646    | InitPartition ->
6647        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6648        List.iter (generate_test_command_call test_name)
6649          [["blockdev_setrw"; "/dev/sda"];
6650           ["umount_all"];
6651           ["lvm_remove_all"];
6652           ["part_disk"; "/dev/sda"; "mbr"]]
6653    | InitBasicFS ->
6654        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6655        List.iter (generate_test_command_call test_name)
6656          [["blockdev_setrw"; "/dev/sda"];
6657           ["umount_all"];
6658           ["lvm_remove_all"];
6659           ["part_disk"; "/dev/sda"; "mbr"];
6660           ["mkfs"; "ext2"; "/dev/sda1"];
6661           ["mount_options"; ""; "/dev/sda1"; "/"]]
6662    | InitBasicFSonLVM ->
6663        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6664          test_name;
6665        List.iter (generate_test_command_call test_name)
6666          [["blockdev_setrw"; "/dev/sda"];
6667           ["umount_all"];
6668           ["lvm_remove_all"];
6669           ["part_disk"; "/dev/sda"; "mbr"];
6670           ["pvcreate"; "/dev/sda1"];
6671           ["vgcreate"; "VG"; "/dev/sda1"];
6672           ["lvcreate"; "LV"; "VG"; "8"];
6673           ["mkfs"; "ext2"; "/dev/VG/LV"];
6674           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6675    | InitISOFS ->
6676        pr "  /* InitISOFS for %s */\n" test_name;
6677        List.iter (generate_test_command_call test_name)
6678          [["blockdev_setrw"; "/dev/sda"];
6679           ["umount_all"];
6680           ["lvm_remove_all"];
6681           ["mount_ro"; "/dev/sdd"; "/"]]
6682   );
6683
6684   let get_seq_last = function
6685     | [] ->
6686         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6687           test_name
6688     | seq ->
6689         let seq = List.rev seq in
6690         List.rev (List.tl seq), List.hd seq
6691   in
6692
6693   match test with
6694   | TestRun seq ->
6695       pr "  /* TestRun for %s (%d) */\n" name i;
6696       List.iter (generate_test_command_call test_name) seq
6697   | TestOutput (seq, expected) ->
6698       pr "  /* TestOutput for %s (%d) */\n" name i;
6699       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6700       let seq, last = get_seq_last seq in
6701       let test () =
6702         pr "    if (STRNEQ (r, expected)) {\n";
6703         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6704         pr "      return -1;\n";
6705         pr "    }\n"
6706       in
6707       List.iter (generate_test_command_call test_name) seq;
6708       generate_test_command_call ~test test_name last
6709   | TestOutputList (seq, expected) ->
6710       pr "  /* TestOutputList for %s (%d) */\n" name i;
6711       let seq, last = get_seq_last seq in
6712       let test () =
6713         iteri (
6714           fun i str ->
6715             pr "    if (!r[%d]) {\n" i;
6716             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6717             pr "      print_strings (r);\n";
6718             pr "      return -1;\n";
6719             pr "    }\n";
6720             pr "    {\n";
6721             pr "      const char *expected = \"%s\";\n" (c_quote str);
6722             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6723             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6724             pr "        return -1;\n";
6725             pr "      }\n";
6726             pr "    }\n"
6727         ) expected;
6728         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6729         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6730           test_name;
6731         pr "      print_strings (r);\n";
6732         pr "      return -1;\n";
6733         pr "    }\n"
6734       in
6735       List.iter (generate_test_command_call test_name) seq;
6736       generate_test_command_call ~test test_name last
6737   | TestOutputListOfDevices (seq, expected) ->
6738       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6739       let seq, last = get_seq_last seq in
6740       let test () =
6741         iteri (
6742           fun i str ->
6743             pr "    if (!r[%d]) {\n" i;
6744             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6745             pr "      print_strings (r);\n";
6746             pr "      return -1;\n";
6747             pr "    }\n";
6748             pr "    {\n";
6749             pr "      const char *expected = \"%s\";\n" (c_quote str);
6750             pr "      r[%d][5] = 's';\n" i;
6751             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6752             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6753             pr "        return -1;\n";
6754             pr "      }\n";
6755             pr "    }\n"
6756         ) expected;
6757         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6758         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6759           test_name;
6760         pr "      print_strings (r);\n";
6761         pr "      return -1;\n";
6762         pr "    }\n"
6763       in
6764       List.iter (generate_test_command_call test_name) seq;
6765       generate_test_command_call ~test test_name last
6766   | TestOutputInt (seq, expected) ->
6767       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6768       let seq, last = get_seq_last seq in
6769       let test () =
6770         pr "    if (r != %d) {\n" expected;
6771         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6772           test_name expected;
6773         pr "               (int) r);\n";
6774         pr "      return -1;\n";
6775         pr "    }\n"
6776       in
6777       List.iter (generate_test_command_call test_name) seq;
6778       generate_test_command_call ~test test_name last
6779   | TestOutputIntOp (seq, op, expected) ->
6780       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6781       let seq, last = get_seq_last seq in
6782       let test () =
6783         pr "    if (! (r %s %d)) {\n" op expected;
6784         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6785           test_name op expected;
6786         pr "               (int) r);\n";
6787         pr "      return -1;\n";
6788         pr "    }\n"
6789       in
6790       List.iter (generate_test_command_call test_name) seq;
6791       generate_test_command_call ~test test_name last
6792   | TestOutputTrue seq ->
6793       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6794       let seq, last = get_seq_last seq in
6795       let test () =
6796         pr "    if (!r) {\n";
6797         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6798           test_name;
6799         pr "      return -1;\n";
6800         pr "    }\n"
6801       in
6802       List.iter (generate_test_command_call test_name) seq;
6803       generate_test_command_call ~test test_name last
6804   | TestOutputFalse seq ->
6805       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6806       let seq, last = get_seq_last seq in
6807       let test () =
6808         pr "    if (r) {\n";
6809         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6810           test_name;
6811         pr "      return -1;\n";
6812         pr "    }\n"
6813       in
6814       List.iter (generate_test_command_call test_name) seq;
6815       generate_test_command_call ~test test_name last
6816   | TestOutputLength (seq, expected) ->
6817       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6818       let seq, last = get_seq_last seq in
6819       let test () =
6820         pr "    int j;\n";
6821         pr "    for (j = 0; j < %d; ++j)\n" expected;
6822         pr "      if (r[j] == NULL) {\n";
6823         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6824           test_name;
6825         pr "        print_strings (r);\n";
6826         pr "        return -1;\n";
6827         pr "      }\n";
6828         pr "    if (r[j] != NULL) {\n";
6829         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6830           test_name;
6831         pr "      print_strings (r);\n";
6832         pr "      return -1;\n";
6833         pr "    }\n"
6834       in
6835       List.iter (generate_test_command_call test_name) seq;
6836       generate_test_command_call ~test test_name last
6837   | TestOutputBuffer (seq, expected) ->
6838       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6839       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6840       let seq, last = get_seq_last seq in
6841       let len = String.length expected in
6842       let test () =
6843         pr "    if (size != %d) {\n" len;
6844         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6845         pr "      return -1;\n";
6846         pr "    }\n";
6847         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6848         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6849         pr "      return -1;\n";
6850         pr "    }\n"
6851       in
6852       List.iter (generate_test_command_call test_name) seq;
6853       generate_test_command_call ~test test_name last
6854   | TestOutputStruct (seq, checks) ->
6855       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6856       let seq, last = get_seq_last seq in
6857       let test () =
6858         List.iter (
6859           function
6860           | CompareWithInt (field, expected) ->
6861               pr "    if (r->%s != %d) {\n" field expected;
6862               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6863                 test_name field expected;
6864               pr "               (int) r->%s);\n" field;
6865               pr "      return -1;\n";
6866               pr "    }\n"
6867           | CompareWithIntOp (field, op, expected) ->
6868               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6869               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6870                 test_name field op expected;
6871               pr "               (int) r->%s);\n" field;
6872               pr "      return -1;\n";
6873               pr "    }\n"
6874           | CompareWithString (field, expected) ->
6875               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6876               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6877                 test_name field expected;
6878               pr "               r->%s);\n" field;
6879               pr "      return -1;\n";
6880               pr "    }\n"
6881           | CompareFieldsIntEq (field1, field2) ->
6882               pr "    if (r->%s != r->%s) {\n" field1 field2;
6883               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6884                 test_name field1 field2;
6885               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6886               pr "      return -1;\n";
6887               pr "    }\n"
6888           | CompareFieldsStrEq (field1, field2) ->
6889               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6890               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6891                 test_name field1 field2;
6892               pr "               r->%s, r->%s);\n" field1 field2;
6893               pr "      return -1;\n";
6894               pr "    }\n"
6895         ) checks
6896       in
6897       List.iter (generate_test_command_call test_name) seq;
6898       generate_test_command_call ~test test_name last
6899   | TestLastFail seq ->
6900       pr "  /* TestLastFail for %s (%d) */\n" name i;
6901       let seq, last = get_seq_last seq in
6902       List.iter (generate_test_command_call test_name) seq;
6903       generate_test_command_call test_name ~expect_error:true last
6904
6905 (* Generate the code to run a command, leaving the result in 'r'.
6906  * If you expect to get an error then you should set expect_error:true.
6907  *)
6908 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6909   match cmd with
6910   | [] -> assert false
6911   | name :: args ->
6912       (* Look up the command to find out what args/ret it has. *)
6913       let style =
6914         try
6915           let _, style, _, _, _, _, _ =
6916             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6917           style
6918         with Not_found ->
6919           failwithf "%s: in test, command %s was not found" test_name name in
6920
6921       if List.length (snd style) <> List.length args then
6922         failwithf "%s: in test, wrong number of args given to %s"
6923           test_name name;
6924
6925       pr "  {\n";
6926
6927       List.iter (
6928         function
6929         | OptString n, "NULL" -> ()
6930         | Pathname n, arg
6931         | Device n, arg
6932         | Dev_or_Path n, arg
6933         | String n, arg
6934         | OptString n, arg ->
6935             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6936         | Int _, _
6937         | Int64 _, _
6938         | Bool _, _
6939         | FileIn _, _ | FileOut _, _ -> ()
6940         | StringList n, "" | DeviceList n, "" ->
6941             pr "    const char *const %s[1] = { NULL };\n" n
6942         | StringList n, arg | DeviceList n, arg ->
6943             let strs = string_split " " arg in
6944             iteri (
6945               fun i str ->
6946                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6947             ) strs;
6948             pr "    const char *const %s[] = {\n" n;
6949             iteri (
6950               fun i _ -> pr "      %s_%d,\n" n i
6951             ) strs;
6952             pr "      NULL\n";
6953             pr "    };\n";
6954       ) (List.combine (snd style) args);
6955
6956       let error_code =
6957         match fst style with
6958         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6959         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6960         | RConstString _ | RConstOptString _ ->
6961             pr "    const char *r;\n"; "NULL"
6962         | RString _ -> pr "    char *r;\n"; "NULL"
6963         | RStringList _ | RHashtable _ ->
6964             pr "    char **r;\n";
6965             pr "    int i;\n";
6966             "NULL"
6967         | RStruct (_, typ) ->
6968             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6969         | RStructList (_, typ) ->
6970             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6971         | RBufferOut _ ->
6972             pr "    char *r;\n";
6973             pr "    size_t size;\n";
6974             "NULL" in
6975
6976       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6977       pr "    r = guestfs_%s (g" name;
6978
6979       (* Generate the parameters. *)
6980       List.iter (
6981         function
6982         | OptString _, "NULL" -> pr ", NULL"
6983         | Pathname n, _
6984         | Device n, _ | Dev_or_Path n, _
6985         | String n, _
6986         | OptString n, _ ->
6987             pr ", %s" n
6988         | FileIn _, arg | FileOut _, arg ->
6989             pr ", \"%s\"" (c_quote arg)
6990         | StringList n, _ | DeviceList n, _ ->
6991             pr ", (char **) %s" n
6992         | Int _, arg ->
6993             let i =
6994               try int_of_string arg
6995               with Failure "int_of_string" ->
6996                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6997             pr ", %d" i
6998         | Int64 _, arg ->
6999             let i =
7000               try Int64.of_string arg
7001               with Failure "int_of_string" ->
7002                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7003             pr ", %Ld" i
7004         | Bool _, arg ->
7005             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7006       ) (List.combine (snd style) args);
7007
7008       (match fst style with
7009        | RBufferOut _ -> pr ", &size"
7010        | _ -> ()
7011       );
7012
7013       pr ");\n";
7014
7015       if not expect_error then
7016         pr "    if (r == %s)\n" error_code
7017       else
7018         pr "    if (r != %s)\n" error_code;
7019       pr "      return -1;\n";
7020
7021       (* Insert the test code. *)
7022       (match test with
7023        | None -> ()
7024        | Some f -> f ()
7025       );
7026
7027       (match fst style with
7028        | RErr | RInt _ | RInt64 _ | RBool _
7029        | RConstString _ | RConstOptString _ -> ()
7030        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7031        | RStringList _ | RHashtable _ ->
7032            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7033            pr "      free (r[i]);\n";
7034            pr "    free (r);\n"
7035        | RStruct (_, typ) ->
7036            pr "    guestfs_free_%s (r);\n" typ
7037        | RStructList (_, typ) ->
7038            pr "    guestfs_free_%s_list (r);\n" typ
7039       );
7040
7041       pr "  }\n"
7042
7043 and c_quote str =
7044   let str = replace_str str "\r" "\\r" in
7045   let str = replace_str str "\n" "\\n" in
7046   let str = replace_str str "\t" "\\t" in
7047   let str = replace_str str "\000" "\\0" in
7048   str
7049
7050 (* Generate a lot of different functions for guestfish. *)
7051 and generate_fish_cmds () =
7052   generate_header CStyle GPLv2plus;
7053
7054   let all_functions =
7055     List.filter (
7056       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7057     ) all_functions in
7058   let all_functions_sorted =
7059     List.filter (
7060       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7061     ) all_functions_sorted in
7062
7063   pr "#include <config.h>\n";
7064   pr "\n";
7065   pr "#include <stdio.h>\n";
7066   pr "#include <stdlib.h>\n";
7067   pr "#include <string.h>\n";
7068   pr "#include <inttypes.h>\n";
7069   pr "\n";
7070   pr "#include <guestfs.h>\n";
7071   pr "#include \"c-ctype.h\"\n";
7072   pr "#include \"full-write.h\"\n";
7073   pr "#include \"xstrtol.h\"\n";
7074   pr "#include \"fish.h\"\n";
7075   pr "\n";
7076
7077   (* list_commands function, which implements guestfish -h *)
7078   pr "void list_commands (void)\n";
7079   pr "{\n";
7080   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7081   pr "  list_builtin_commands ();\n";
7082   List.iter (
7083     fun (name, _, _, flags, _, shortdesc, _) ->
7084       let name = replace_char name '_' '-' in
7085       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7086         name shortdesc
7087   ) all_functions_sorted;
7088   pr "  printf (\"    %%s\\n\",";
7089   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7090   pr "}\n";
7091   pr "\n";
7092
7093   (* display_command function, which implements guestfish -h cmd *)
7094   pr "void display_command (const char *cmd)\n";
7095   pr "{\n";
7096   List.iter (
7097     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7098       let name2 = replace_char name '_' '-' in
7099       let alias =
7100         try find_map (function FishAlias n -> Some n | _ -> None) flags
7101         with Not_found -> name in
7102       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7103       let synopsis =
7104         match snd style with
7105         | [] -> name2
7106         | args ->
7107             sprintf "%s %s"
7108               name2 (String.concat " " (List.map name_of_argt args)) in
7109
7110       let warnings =
7111         if List.mem ProtocolLimitWarning flags then
7112           ("\n\n" ^ protocol_limit_warning)
7113         else "" in
7114
7115       (* For DangerWillRobinson commands, we should probably have
7116        * guestfish prompt before allowing you to use them (especially
7117        * in interactive mode). XXX
7118        *)
7119       let warnings =
7120         warnings ^
7121           if List.mem DangerWillRobinson flags then
7122             ("\n\n" ^ danger_will_robinson)
7123           else "" in
7124
7125       let warnings =
7126         warnings ^
7127           match deprecation_notice flags with
7128           | None -> ""
7129           | Some txt -> "\n\n" ^ txt in
7130
7131       let describe_alias =
7132         if name <> alias then
7133           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7134         else "" in
7135
7136       pr "  if (";
7137       pr "STRCASEEQ (cmd, \"%s\")" name;
7138       if name <> name2 then
7139         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7140       if name <> alias then
7141         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7142       pr ")\n";
7143       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7144         name2 shortdesc
7145         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7146          "=head1 DESCRIPTION\n\n" ^
7147          longdesc ^ warnings ^ describe_alias);
7148       pr "  else\n"
7149   ) all_functions;
7150   pr "    display_builtin_command (cmd);\n";
7151   pr "}\n";
7152   pr "\n";
7153
7154   let emit_print_list_function typ =
7155     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7156       typ typ typ;
7157     pr "{\n";
7158     pr "  unsigned int i;\n";
7159     pr "\n";
7160     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7161     pr "    printf (\"[%%d] = {\\n\", i);\n";
7162     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7163     pr "    printf (\"}\\n\");\n";
7164     pr "  }\n";
7165     pr "}\n";
7166     pr "\n";
7167   in
7168
7169   (* print_* functions *)
7170   List.iter (
7171     fun (typ, cols) ->
7172       let needs_i =
7173         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7174
7175       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7176       pr "{\n";
7177       if needs_i then (
7178         pr "  unsigned int i;\n";
7179         pr "\n"
7180       );
7181       List.iter (
7182         function
7183         | name, FString ->
7184             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7185         | name, FUUID ->
7186             pr "  printf (\"%%s%s: \", indent);\n" name;
7187             pr "  for (i = 0; i < 32; ++i)\n";
7188             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7189             pr "  printf (\"\\n\");\n"
7190         | name, FBuffer ->
7191             pr "  printf (\"%%s%s: \", indent);\n" name;
7192             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7193             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7194             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7195             pr "    else\n";
7196             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7197             pr "  printf (\"\\n\");\n"
7198         | name, (FUInt64|FBytes) ->
7199             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7200               name typ name
7201         | name, FInt64 ->
7202             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7203               name typ name
7204         | name, FUInt32 ->
7205             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7206               name typ name
7207         | name, FInt32 ->
7208             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7209               name typ name
7210         | name, FChar ->
7211             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7212               name typ name
7213         | name, FOptPercent ->
7214             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7215               typ name name typ name;
7216             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7217       ) cols;
7218       pr "}\n";
7219       pr "\n";
7220   ) structs;
7221
7222   (* Emit a print_TYPE_list function definition only if that function is used. *)
7223   List.iter (
7224     function
7225     | typ, (RStructListOnly | RStructAndList) ->
7226         (* generate the function for typ *)
7227         emit_print_list_function typ
7228     | typ, _ -> () (* empty *)
7229   ) (rstructs_used_by all_functions);
7230
7231   (* Emit a print_TYPE function definition only if that function is used. *)
7232   List.iter (
7233     function
7234     | typ, (RStructOnly | RStructAndList) ->
7235         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7236         pr "{\n";
7237         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7238         pr "}\n";
7239         pr "\n";
7240     | typ, _ -> () (* empty *)
7241   ) (rstructs_used_by all_functions);
7242
7243   (* run_<action> actions *)
7244   List.iter (
7245     fun (name, style, _, flags, _, _, _) ->
7246       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7247       pr "{\n";
7248       (match fst style with
7249        | RErr
7250        | RInt _
7251        | RBool _ -> pr "  int r;\n"
7252        | RInt64 _ -> pr "  int64_t r;\n"
7253        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7254        | RString _ -> pr "  char *r;\n"
7255        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7256        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7257        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7258        | RBufferOut _ ->
7259            pr "  char *r;\n";
7260            pr "  size_t size;\n";
7261       );
7262       List.iter (
7263         function
7264         | Device n
7265         | String n
7266         | OptString n
7267         | FileIn n
7268         | FileOut n -> pr "  const char *%s;\n" n
7269         | Pathname n
7270         | Dev_or_Path n -> pr "  char *%s;\n" n
7271         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7272         | Bool n -> pr "  int %s;\n" n
7273         | Int n -> pr "  int %s;\n" n
7274         | Int64 n -> pr "  int64_t %s;\n" n
7275       ) (snd style);
7276
7277       (* Check and convert parameters. *)
7278       let argc_expected = List.length (snd style) in
7279       pr "  if (argc != %d) {\n" argc_expected;
7280       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7281         argc_expected;
7282       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7283       pr "    return -1;\n";
7284       pr "  }\n";
7285
7286       let parse_integer fn fntyp rtyp range name i =
7287         pr "  {\n";
7288         pr "    strtol_error xerr;\n";
7289         pr "    %s r;\n" fntyp;
7290         pr "\n";
7291         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7292         pr "    if (xerr != LONGINT_OK) {\n";
7293         pr "      fprintf (stderr,\n";
7294         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7295         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7296         pr "      return -1;\n";
7297         pr "    }\n";
7298         (match range with
7299          | None -> ()
7300          | Some (min, max, comment) ->
7301              pr "    /* %s */\n" comment;
7302              pr "    if (r < %s || r > %s) {\n" min max;
7303              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7304                name;
7305              pr "      return -1;\n";
7306              pr "    }\n";
7307              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7308         );
7309         pr "    %s = r;\n" name;
7310         pr "  }\n";
7311       in
7312
7313       iteri (
7314         fun i ->
7315           function
7316           | Device name
7317           | String name ->
7318               pr "  %s = argv[%d];\n" name i
7319           | Pathname name
7320           | Dev_or_Path name ->
7321               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7322               pr "  if (%s == NULL) return -1;\n" name
7323           | OptString name ->
7324               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7325                 name i i
7326           | FileIn name ->
7327               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7328                 name i i
7329           | FileOut name ->
7330               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7331                 name i i
7332           | StringList name | DeviceList name ->
7333               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7334               pr "  if (%s == NULL) return -1;\n" name;
7335           | Bool name ->
7336               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7337           | Int name ->
7338               let range =
7339                 let min = "(-(2LL<<30))"
7340                 and max = "((2LL<<30)-1)"
7341                 and comment =
7342                   "The Int type in the generator is a signed 31 bit int." in
7343                 Some (min, max, comment) in
7344               parse_integer "xstrtoll" "long long" "int" range name i
7345           | Int64 name ->
7346               parse_integer "xstrtoll" "long long" "int64_t" None name i
7347       ) (snd style);
7348
7349       (* Call C API function. *)
7350       let fn =
7351         try find_map (function FishAction n -> Some n | _ -> None) flags
7352         with Not_found -> sprintf "guestfs_%s" name in
7353       pr "  r = %s " fn;
7354       generate_c_call_args ~handle:"g" style;
7355       pr ";\n";
7356
7357       List.iter (
7358         function
7359         | Device name | String name
7360         | OptString name | FileIn name | FileOut name | Bool name
7361         | Int name | Int64 name -> ()
7362         | Pathname name | Dev_or_Path name ->
7363             pr "  free (%s);\n" name
7364         | StringList name | DeviceList name ->
7365             pr "  free_strings (%s);\n" name
7366       ) (snd style);
7367
7368       (* Check return value for errors and display command results. *)
7369       (match fst style with
7370        | RErr -> pr "  return r;\n"
7371        | RInt _ ->
7372            pr "  if (r == -1) return -1;\n";
7373            pr "  printf (\"%%d\\n\", r);\n";
7374            pr "  return 0;\n"
7375        | RInt64 _ ->
7376            pr "  if (r == -1) return -1;\n";
7377            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7378            pr "  return 0;\n"
7379        | RBool _ ->
7380            pr "  if (r == -1) return -1;\n";
7381            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7382            pr "  return 0;\n"
7383        | RConstString _ ->
7384            pr "  if (r == NULL) return -1;\n";
7385            pr "  printf (\"%%s\\n\", r);\n";
7386            pr "  return 0;\n"
7387        | RConstOptString _ ->
7388            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7389            pr "  return 0;\n"
7390        | RString _ ->
7391            pr "  if (r == NULL) return -1;\n";
7392            pr "  printf (\"%%s\\n\", r);\n";
7393            pr "  free (r);\n";
7394            pr "  return 0;\n"
7395        | RStringList _ ->
7396            pr "  if (r == NULL) return -1;\n";
7397            pr "  print_strings (r);\n";
7398            pr "  free_strings (r);\n";
7399            pr "  return 0;\n"
7400        | RStruct (_, typ) ->
7401            pr "  if (r == NULL) return -1;\n";
7402            pr "  print_%s (r);\n" typ;
7403            pr "  guestfs_free_%s (r);\n" typ;
7404            pr "  return 0;\n"
7405        | RStructList (_, typ) ->
7406            pr "  if (r == NULL) return -1;\n";
7407            pr "  print_%s_list (r);\n" typ;
7408            pr "  guestfs_free_%s_list (r);\n" typ;
7409            pr "  return 0;\n"
7410        | RHashtable _ ->
7411            pr "  if (r == NULL) return -1;\n";
7412            pr "  print_table (r);\n";
7413            pr "  free_strings (r);\n";
7414            pr "  return 0;\n"
7415        | RBufferOut _ ->
7416            pr "  if (r == NULL) return -1;\n";
7417            pr "  if (full_write (1, r, size) != size) {\n";
7418            pr "    perror (\"write\");\n";
7419            pr "    free (r);\n";
7420            pr "    return -1;\n";
7421            pr "  }\n";
7422            pr "  free (r);\n";
7423            pr "  return 0;\n"
7424       );
7425       pr "}\n";
7426       pr "\n"
7427   ) all_functions;
7428
7429   (* run_action function *)
7430   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7431   pr "{\n";
7432   List.iter (
7433     fun (name, _, _, flags, _, _, _) ->
7434       let name2 = replace_char name '_' '-' in
7435       let alias =
7436         try find_map (function FishAlias n -> Some n | _ -> None) flags
7437         with Not_found -> name in
7438       pr "  if (";
7439       pr "STRCASEEQ (cmd, \"%s\")" name;
7440       if name <> name2 then
7441         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7442       if name <> alias then
7443         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7444       pr ")\n";
7445       pr "    return run_%s (cmd, argc, argv);\n" name;
7446       pr "  else\n";
7447   ) all_functions;
7448   pr "    {\n";
7449   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7450   pr "      if (command_num == 1)\n";
7451   pr "        extended_help_message ();\n";
7452   pr "      return -1;\n";
7453   pr "    }\n";
7454   pr "  return 0;\n";
7455   pr "}\n";
7456   pr "\n"
7457
7458 (* Readline completion for guestfish. *)
7459 and generate_fish_completion () =
7460   generate_header CStyle GPLv2plus;
7461
7462   let all_functions =
7463     List.filter (
7464       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7465     ) all_functions in
7466
7467   pr "\
7468 #include <config.h>
7469
7470 #include <stdio.h>
7471 #include <stdlib.h>
7472 #include <string.h>
7473
7474 #ifdef HAVE_LIBREADLINE
7475 #include <readline/readline.h>
7476 #endif
7477
7478 #include \"fish.h\"
7479
7480 #ifdef HAVE_LIBREADLINE
7481
7482 static const char *const commands[] = {
7483   BUILTIN_COMMANDS_FOR_COMPLETION,
7484 ";
7485
7486   (* Get the commands, including the aliases.  They don't need to be
7487    * sorted - the generator() function just does a dumb linear search.
7488    *)
7489   let commands =
7490     List.map (
7491       fun (name, _, _, flags, _, _, _) ->
7492         let name2 = replace_char name '_' '-' in
7493         let alias =
7494           try find_map (function FishAlias n -> Some n | _ -> None) flags
7495           with Not_found -> name in
7496
7497         if name <> alias then [name2; alias] else [name2]
7498     ) all_functions in
7499   let commands = List.flatten commands in
7500
7501   List.iter (pr "  \"%s\",\n") commands;
7502
7503   pr "  NULL
7504 };
7505
7506 static char *
7507 generator (const char *text, int state)
7508 {
7509   static int index, len;
7510   const char *name;
7511
7512   if (!state) {
7513     index = 0;
7514     len = strlen (text);
7515   }
7516
7517   rl_attempted_completion_over = 1;
7518
7519   while ((name = commands[index]) != NULL) {
7520     index++;
7521     if (STRCASEEQLEN (name, text, len))
7522       return strdup (name);
7523   }
7524
7525   return NULL;
7526 }
7527
7528 #endif /* HAVE_LIBREADLINE */
7529
7530 #ifdef HAVE_RL_COMPLETION_MATCHES
7531 #define RL_COMPLETION_MATCHES rl_completion_matches
7532 #else
7533 #ifdef HAVE_COMPLETION_MATCHES
7534 #define RL_COMPLETION_MATCHES completion_matches
7535 #endif
7536 #endif /* else just fail if we don't have either symbol */
7537
7538 char **
7539 do_completion (const char *text, int start, int end)
7540 {
7541   char **matches = NULL;
7542
7543 #ifdef HAVE_LIBREADLINE
7544   rl_completion_append_character = ' ';
7545
7546   if (start == 0)
7547     matches = RL_COMPLETION_MATCHES (text, generator);
7548   else if (complete_dest_paths)
7549     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7550 #endif
7551
7552   return matches;
7553 }
7554 ";
7555
7556 (* Generate the POD documentation for guestfish. *)
7557 and generate_fish_actions_pod () =
7558   let all_functions_sorted =
7559     List.filter (
7560       fun (_, _, _, flags, _, _, _) ->
7561         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7562     ) all_functions_sorted in
7563
7564   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7565
7566   List.iter (
7567     fun (name, style, _, flags, _, _, longdesc) ->
7568       let longdesc =
7569         Str.global_substitute rex (
7570           fun s ->
7571             let sub =
7572               try Str.matched_group 1 s
7573               with Not_found ->
7574                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7575             "C<" ^ replace_char sub '_' '-' ^ ">"
7576         ) longdesc in
7577       let name = replace_char name '_' '-' in
7578       let alias =
7579         try find_map (function FishAlias n -> Some n | _ -> None) flags
7580         with Not_found -> name in
7581
7582       pr "=head2 %s" name;
7583       if name <> alias then
7584         pr " | %s" alias;
7585       pr "\n";
7586       pr "\n";
7587       pr " %s" name;
7588       List.iter (
7589         function
7590         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7591         | OptString n -> pr " %s" n
7592         | StringList n | DeviceList n -> pr " '%s ...'" n
7593         | Bool _ -> pr " true|false"
7594         | Int n -> pr " %s" n
7595         | Int64 n -> pr " %s" n
7596         | FileIn n | FileOut n -> pr " (%s|-)" n
7597       ) (snd style);
7598       pr "\n";
7599       pr "\n";
7600       pr "%s\n\n" longdesc;
7601
7602       if List.exists (function FileIn _ | FileOut _ -> true
7603                       | _ -> false) (snd style) then
7604         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7605
7606       if List.mem ProtocolLimitWarning flags then
7607         pr "%s\n\n" protocol_limit_warning;
7608
7609       if List.mem DangerWillRobinson flags then
7610         pr "%s\n\n" danger_will_robinson;
7611
7612       match deprecation_notice flags with
7613       | None -> ()
7614       | Some txt -> pr "%s\n\n" txt
7615   ) all_functions_sorted
7616
7617 (* Generate a C function prototype. *)
7618 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7619     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7620     ?(prefix = "")
7621     ?handle name style =
7622   if extern then pr "extern ";
7623   if static then pr "static ";
7624   (match fst style with
7625    | RErr -> pr "int "
7626    | RInt _ -> pr "int "
7627    | RInt64 _ -> pr "int64_t "
7628    | RBool _ -> pr "int "
7629    | RConstString _ | RConstOptString _ -> pr "const char *"
7630    | RString _ | RBufferOut _ -> pr "char *"
7631    | RStringList _ | RHashtable _ -> pr "char **"
7632    | RStruct (_, typ) ->
7633        if not in_daemon then pr "struct guestfs_%s *" typ
7634        else pr "guestfs_int_%s *" typ
7635    | RStructList (_, typ) ->
7636        if not in_daemon then pr "struct guestfs_%s_list *" typ
7637        else pr "guestfs_int_%s_list *" typ
7638   );
7639   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7640   pr "%s%s (" prefix name;
7641   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7642     pr "void"
7643   else (
7644     let comma = ref false in
7645     (match handle with
7646      | None -> ()
7647      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7648     );
7649     let next () =
7650       if !comma then (
7651         if single_line then pr ", " else pr ",\n\t\t"
7652       );
7653       comma := true
7654     in
7655     List.iter (
7656       function
7657       | Pathname n
7658       | Device n | Dev_or_Path n
7659       | String n
7660       | OptString n ->
7661           next ();
7662           pr "const char *%s" n
7663       | StringList n | DeviceList n ->
7664           next ();
7665           pr "char *const *%s" n
7666       | Bool n -> next (); pr "int %s" n
7667       | Int n -> next (); pr "int %s" n
7668       | Int64 n -> next (); pr "int64_t %s" n
7669       | FileIn n
7670       | FileOut n ->
7671           if not in_daemon then (next (); pr "const char *%s" n)
7672     ) (snd style);
7673     if is_RBufferOut then (next (); pr "size_t *size_r");
7674   );
7675   pr ")";
7676   if semicolon then pr ";";
7677   if newline then pr "\n"
7678
7679 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7680 and generate_c_call_args ?handle ?(decl = false) style =
7681   pr "(";
7682   let comma = ref false in
7683   let next () =
7684     if !comma then pr ", ";
7685     comma := true
7686   in
7687   (match handle with
7688    | None -> ()
7689    | Some handle -> pr "%s" handle; comma := true
7690   );
7691   List.iter (
7692     fun arg ->
7693       next ();
7694       pr "%s" (name_of_argt arg)
7695   ) (snd style);
7696   (* For RBufferOut calls, add implicit &size parameter. *)
7697   if not decl then (
7698     match fst style with
7699     | RBufferOut _ ->
7700         next ();
7701         pr "&size"
7702     | _ -> ()
7703   );
7704   pr ")"
7705
7706 (* Generate the OCaml bindings interface. *)
7707 and generate_ocaml_mli () =
7708   generate_header OCamlStyle LGPLv2plus;
7709
7710   pr "\
7711 (** For API documentation you should refer to the C API
7712     in the guestfs(3) manual page.  The OCaml API uses almost
7713     exactly the same calls. *)
7714
7715 type t
7716 (** A [guestfs_h] handle. *)
7717
7718 exception Error of string
7719 (** This exception is raised when there is an error. *)
7720
7721 exception Handle_closed of string
7722 (** This exception is raised if you use a {!Guestfs.t} handle
7723     after calling {!close} on it.  The string is the name of
7724     the function. *)
7725
7726 val create : unit -> t
7727 (** Create a {!Guestfs.t} handle. *)
7728
7729 val close : t -> unit
7730 (** Close the {!Guestfs.t} handle and free up all resources used
7731     by it immediately.
7732
7733     Handles are closed by the garbage collector when they become
7734     unreferenced, but callers can call this in order to provide
7735     predictable cleanup. *)
7736
7737 ";
7738   generate_ocaml_structure_decls ();
7739
7740   (* The actions. *)
7741   List.iter (
7742     fun (name, style, _, _, _, shortdesc, _) ->
7743       generate_ocaml_prototype name style;
7744       pr "(** %s *)\n" shortdesc;
7745       pr "\n"
7746   ) all_functions_sorted
7747
7748 (* Generate the OCaml bindings implementation. *)
7749 and generate_ocaml_ml () =
7750   generate_header OCamlStyle LGPLv2plus;
7751
7752   pr "\
7753 type t
7754
7755 exception Error of string
7756 exception Handle_closed of string
7757
7758 external create : unit -> t = \"ocaml_guestfs_create\"
7759 external close : t -> unit = \"ocaml_guestfs_close\"
7760
7761 (* Give the exceptions names, so they can be raised from the C code. *)
7762 let () =
7763   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7764   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7765
7766 ";
7767
7768   generate_ocaml_structure_decls ();
7769
7770   (* The actions. *)
7771   List.iter (
7772     fun (name, style, _, _, _, shortdesc, _) ->
7773       generate_ocaml_prototype ~is_external:true name style;
7774   ) all_functions_sorted
7775
7776 (* Generate the OCaml bindings C implementation. *)
7777 and generate_ocaml_c () =
7778   generate_header CStyle LGPLv2plus;
7779
7780   pr "\
7781 #include <stdio.h>
7782 #include <stdlib.h>
7783 #include <string.h>
7784
7785 #include <caml/config.h>
7786 #include <caml/alloc.h>
7787 #include <caml/callback.h>
7788 #include <caml/fail.h>
7789 #include <caml/memory.h>
7790 #include <caml/mlvalues.h>
7791 #include <caml/signals.h>
7792
7793 #include <guestfs.h>
7794
7795 #include \"guestfs_c.h\"
7796
7797 /* Copy a hashtable of string pairs into an assoc-list.  We return
7798  * the list in reverse order, but hashtables aren't supposed to be
7799  * ordered anyway.
7800  */
7801 static CAMLprim value
7802 copy_table (char * const * argv)
7803 {
7804   CAMLparam0 ();
7805   CAMLlocal5 (rv, pairv, kv, vv, cons);
7806   int i;
7807
7808   rv = Val_int (0);
7809   for (i = 0; argv[i] != NULL; i += 2) {
7810     kv = caml_copy_string (argv[i]);
7811     vv = caml_copy_string (argv[i+1]);
7812     pairv = caml_alloc (2, 0);
7813     Store_field (pairv, 0, kv);
7814     Store_field (pairv, 1, vv);
7815     cons = caml_alloc (2, 0);
7816     Store_field (cons, 1, rv);
7817     rv = cons;
7818     Store_field (cons, 0, pairv);
7819   }
7820
7821   CAMLreturn (rv);
7822 }
7823
7824 ";
7825
7826   (* Struct copy functions. *)
7827
7828   let emit_ocaml_copy_list_function typ =
7829     pr "static CAMLprim value\n";
7830     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7831     pr "{\n";
7832     pr "  CAMLparam0 ();\n";
7833     pr "  CAMLlocal2 (rv, v);\n";
7834     pr "  unsigned int i;\n";
7835     pr "\n";
7836     pr "  if (%ss->len == 0)\n" typ;
7837     pr "    CAMLreturn (Atom (0));\n";
7838     pr "  else {\n";
7839     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7840     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7841     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7842     pr "      caml_modify (&Field (rv, i), v);\n";
7843     pr "    }\n";
7844     pr "    CAMLreturn (rv);\n";
7845     pr "  }\n";
7846     pr "}\n";
7847     pr "\n";
7848   in
7849
7850   List.iter (
7851     fun (typ, cols) ->
7852       let has_optpercent_col =
7853         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7854
7855       pr "static CAMLprim value\n";
7856       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7857       pr "{\n";
7858       pr "  CAMLparam0 ();\n";
7859       if has_optpercent_col then
7860         pr "  CAMLlocal3 (rv, v, v2);\n"
7861       else
7862         pr "  CAMLlocal2 (rv, v);\n";
7863       pr "\n";
7864       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7865       iteri (
7866         fun i col ->
7867           (match col with
7868            | name, FString ->
7869                pr "  v = caml_copy_string (%s->%s);\n" typ name
7870            | name, FBuffer ->
7871                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7872                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7873                  typ name typ name
7874            | name, FUUID ->
7875                pr "  v = caml_alloc_string (32);\n";
7876                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7877            | name, (FBytes|FInt64|FUInt64) ->
7878                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7879            | name, (FInt32|FUInt32) ->
7880                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7881            | name, FOptPercent ->
7882                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7883                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7884                pr "    v = caml_alloc (1, 0);\n";
7885                pr "    Store_field (v, 0, v2);\n";
7886                pr "  } else /* None */\n";
7887                pr "    v = Val_int (0);\n";
7888            | name, FChar ->
7889                pr "  v = Val_int (%s->%s);\n" typ name
7890           );
7891           pr "  Store_field (rv, %d, v);\n" i
7892       ) cols;
7893       pr "  CAMLreturn (rv);\n";
7894       pr "}\n";
7895       pr "\n";
7896   ) structs;
7897
7898   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7899   List.iter (
7900     function
7901     | typ, (RStructListOnly | RStructAndList) ->
7902         (* generate the function for typ *)
7903         emit_ocaml_copy_list_function typ
7904     | typ, _ -> () (* empty *)
7905   ) (rstructs_used_by all_functions);
7906
7907   (* The wrappers. *)
7908   List.iter (
7909     fun (name, style, _, _, _, _, _) ->
7910       pr "/* Automatically generated wrapper for function\n";
7911       pr " * ";
7912       generate_ocaml_prototype name style;
7913       pr " */\n";
7914       pr "\n";
7915
7916       let params =
7917         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7918
7919       let needs_extra_vs =
7920         match fst style with RConstOptString _ -> true | _ -> false in
7921
7922       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7923       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7924       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7925       pr "\n";
7926
7927       pr "CAMLprim value\n";
7928       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7929       List.iter (pr ", value %s") (List.tl params);
7930       pr ")\n";
7931       pr "{\n";
7932
7933       (match params with
7934        | [p1; p2; p3; p4; p5] ->
7935            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7936        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7937            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7938            pr "  CAMLxparam%d (%s);\n"
7939              (List.length rest) (String.concat ", " rest)
7940        | ps ->
7941            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7942       );
7943       if not needs_extra_vs then
7944         pr "  CAMLlocal1 (rv);\n"
7945       else
7946         pr "  CAMLlocal3 (rv, v, v2);\n";
7947       pr "\n";
7948
7949       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7950       pr "  if (g == NULL)\n";
7951       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7952       pr "\n";
7953
7954       List.iter (
7955         function
7956         | Pathname n
7957         | Device n | Dev_or_Path n
7958         | String n
7959         | FileIn n
7960         | FileOut n ->
7961             pr "  const char *%s = String_val (%sv);\n" n n
7962         | OptString n ->
7963             pr "  const char *%s =\n" n;
7964             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7965               n n
7966         | StringList n | DeviceList n ->
7967             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7968         | Bool n ->
7969             pr "  int %s = Bool_val (%sv);\n" n n
7970         | Int n ->
7971             pr "  int %s = Int_val (%sv);\n" n n
7972         | Int64 n ->
7973             pr "  int64_t %s = Int64_val (%sv);\n" n n
7974       ) (snd style);
7975       let error_code =
7976         match fst style with
7977         | RErr -> pr "  int r;\n"; "-1"
7978         | RInt _ -> pr "  int r;\n"; "-1"
7979         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7980         | RBool _ -> pr "  int r;\n"; "-1"
7981         | RConstString _ | RConstOptString _ ->
7982             pr "  const char *r;\n"; "NULL"
7983         | RString _ -> pr "  char *r;\n"; "NULL"
7984         | RStringList _ ->
7985             pr "  int i;\n";
7986             pr "  char **r;\n";
7987             "NULL"
7988         | RStruct (_, typ) ->
7989             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7990         | RStructList (_, typ) ->
7991             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7992         | RHashtable _ ->
7993             pr "  int i;\n";
7994             pr "  char **r;\n";
7995             "NULL"
7996         | RBufferOut _ ->
7997             pr "  char *r;\n";
7998             pr "  size_t size;\n";
7999             "NULL" in
8000       pr "\n";
8001
8002       pr "  caml_enter_blocking_section ();\n";
8003       pr "  r = guestfs_%s " name;
8004       generate_c_call_args ~handle:"g" style;
8005       pr ";\n";
8006       pr "  caml_leave_blocking_section ();\n";
8007
8008       List.iter (
8009         function
8010         | StringList n | DeviceList n ->
8011             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8012         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8013         | Bool _ | Int _ | Int64 _
8014         | FileIn _ | FileOut _ -> ()
8015       ) (snd style);
8016
8017       pr "  if (r == %s)\n" error_code;
8018       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8019       pr "\n";
8020
8021       (match fst style with
8022        | RErr -> pr "  rv = Val_unit;\n"
8023        | RInt _ -> pr "  rv = Val_int (r);\n"
8024        | RInt64 _ ->
8025            pr "  rv = caml_copy_int64 (r);\n"
8026        | RBool _ -> pr "  rv = Val_bool (r);\n"
8027        | RConstString _ ->
8028            pr "  rv = caml_copy_string (r);\n"
8029        | RConstOptString _ ->
8030            pr "  if (r) { /* Some string */\n";
8031            pr "    v = caml_alloc (1, 0);\n";
8032            pr "    v2 = caml_copy_string (r);\n";
8033            pr "    Store_field (v, 0, v2);\n";
8034            pr "  } else /* None */\n";
8035            pr "    v = Val_int (0);\n";
8036        | RString _ ->
8037            pr "  rv = caml_copy_string (r);\n";
8038            pr "  free (r);\n"
8039        | RStringList _ ->
8040            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8041            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8042            pr "  free (r);\n"
8043        | RStruct (_, typ) ->
8044            pr "  rv = copy_%s (r);\n" typ;
8045            pr "  guestfs_free_%s (r);\n" typ;
8046        | RStructList (_, typ) ->
8047            pr "  rv = copy_%s_list (r);\n" typ;
8048            pr "  guestfs_free_%s_list (r);\n" typ;
8049        | RHashtable _ ->
8050            pr "  rv = copy_table (r);\n";
8051            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8052            pr "  free (r);\n";
8053        | RBufferOut _ ->
8054            pr "  rv = caml_alloc_string (size);\n";
8055            pr "  memcpy (String_val (rv), r, size);\n";
8056       );
8057
8058       pr "  CAMLreturn (rv);\n";
8059       pr "}\n";
8060       pr "\n";
8061
8062       if List.length params > 5 then (
8063         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8064         pr "CAMLprim value ";
8065         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8066         pr "CAMLprim value\n";
8067         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8068         pr "{\n";
8069         pr "  return ocaml_guestfs_%s (argv[0]" name;
8070         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8071         pr ");\n";
8072         pr "}\n";
8073         pr "\n"
8074       )
8075   ) all_functions_sorted
8076
8077 and generate_ocaml_structure_decls () =
8078   List.iter (
8079     fun (typ, cols) ->
8080       pr "type %s = {\n" typ;
8081       List.iter (
8082         function
8083         | name, FString -> pr "  %s : string;\n" name
8084         | name, FBuffer -> pr "  %s : string;\n" name
8085         | name, FUUID -> pr "  %s : string;\n" name
8086         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8087         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8088         | name, FChar -> pr "  %s : char;\n" name
8089         | name, FOptPercent -> pr "  %s : float option;\n" name
8090       ) cols;
8091       pr "}\n";
8092       pr "\n"
8093   ) structs
8094
8095 and generate_ocaml_prototype ?(is_external = false) name style =
8096   if is_external then pr "external " else pr "val ";
8097   pr "%s : t -> " name;
8098   List.iter (
8099     function
8100     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8101     | OptString _ -> pr "string option -> "
8102     | StringList _ | DeviceList _ -> pr "string array -> "
8103     | Bool _ -> pr "bool -> "
8104     | Int _ -> pr "int -> "
8105     | Int64 _ -> pr "int64 -> "
8106   ) (snd style);
8107   (match fst style with
8108    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8109    | RInt _ -> pr "int"
8110    | RInt64 _ -> pr "int64"
8111    | RBool _ -> pr "bool"
8112    | RConstString _ -> pr "string"
8113    | RConstOptString _ -> pr "string option"
8114    | RString _ | RBufferOut _ -> pr "string"
8115    | RStringList _ -> pr "string array"
8116    | RStruct (_, typ) -> pr "%s" typ
8117    | RStructList (_, typ) -> pr "%s array" typ
8118    | RHashtable _ -> pr "(string * string) list"
8119   );
8120   if is_external then (
8121     pr " = ";
8122     if List.length (snd style) + 1 > 5 then
8123       pr "\"ocaml_guestfs_%s_byte\" " name;
8124     pr "\"ocaml_guestfs_%s\"" name
8125   );
8126   pr "\n"
8127
8128 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8129 and generate_perl_xs () =
8130   generate_header CStyle LGPLv2plus;
8131
8132   pr "\
8133 #include \"EXTERN.h\"
8134 #include \"perl.h\"
8135 #include \"XSUB.h\"
8136
8137 #include <guestfs.h>
8138
8139 #ifndef PRId64
8140 #define PRId64 \"lld\"
8141 #endif
8142
8143 static SV *
8144 my_newSVll(long long val) {
8145 #ifdef USE_64_BIT_ALL
8146   return newSViv(val);
8147 #else
8148   char buf[100];
8149   int len;
8150   len = snprintf(buf, 100, \"%%\" PRId64, val);
8151   return newSVpv(buf, len);
8152 #endif
8153 }
8154
8155 #ifndef PRIu64
8156 #define PRIu64 \"llu\"
8157 #endif
8158
8159 static SV *
8160 my_newSVull(unsigned long long val) {
8161 #ifdef USE_64_BIT_ALL
8162   return newSVuv(val);
8163 #else
8164   char buf[100];
8165   int len;
8166   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8167   return newSVpv(buf, len);
8168 #endif
8169 }
8170
8171 /* http://www.perlmonks.org/?node_id=680842 */
8172 static char **
8173 XS_unpack_charPtrPtr (SV *arg) {
8174   char **ret;
8175   AV *av;
8176   I32 i;
8177
8178   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8179     croak (\"array reference expected\");
8180
8181   av = (AV *)SvRV (arg);
8182   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8183   if (!ret)
8184     croak (\"malloc failed\");
8185
8186   for (i = 0; i <= av_len (av); i++) {
8187     SV **elem = av_fetch (av, i, 0);
8188
8189     if (!elem || !*elem)
8190       croak (\"missing element in list\");
8191
8192     ret[i] = SvPV_nolen (*elem);
8193   }
8194
8195   ret[i] = NULL;
8196
8197   return ret;
8198 }
8199
8200 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8201
8202 PROTOTYPES: ENABLE
8203
8204 guestfs_h *
8205 _create ()
8206    CODE:
8207       RETVAL = guestfs_create ();
8208       if (!RETVAL)
8209         croak (\"could not create guestfs handle\");
8210       guestfs_set_error_handler (RETVAL, NULL, NULL);
8211  OUTPUT:
8212       RETVAL
8213
8214 void
8215 DESTROY (g)
8216       guestfs_h *g;
8217  PPCODE:
8218       guestfs_close (g);
8219
8220 ";
8221
8222   List.iter (
8223     fun (name, style, _, _, _, _, _) ->
8224       (match fst style with
8225        | RErr -> pr "void\n"
8226        | RInt _ -> pr "SV *\n"
8227        | RInt64 _ -> pr "SV *\n"
8228        | RBool _ -> pr "SV *\n"
8229        | RConstString _ -> pr "SV *\n"
8230        | RConstOptString _ -> pr "SV *\n"
8231        | RString _ -> pr "SV *\n"
8232        | RBufferOut _ -> pr "SV *\n"
8233        | RStringList _
8234        | RStruct _ | RStructList _
8235        | RHashtable _ ->
8236            pr "void\n" (* all lists returned implictly on the stack *)
8237       );
8238       (* Call and arguments. *)
8239       pr "%s " name;
8240       generate_c_call_args ~handle:"g" ~decl:true style;
8241       pr "\n";
8242       pr "      guestfs_h *g;\n";
8243       iteri (
8244         fun i ->
8245           function
8246           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8247               pr "      char *%s;\n" n
8248           | OptString n ->
8249               (* http://www.perlmonks.org/?node_id=554277
8250                * Note that the implicit handle argument means we have
8251                * to add 1 to the ST(x) operator.
8252                *)
8253               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8254           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8255           | Bool n -> pr "      int %s;\n" n
8256           | Int n -> pr "      int %s;\n" n
8257           | Int64 n -> pr "      int64_t %s;\n" n
8258       ) (snd style);
8259
8260       let do_cleanups () =
8261         List.iter (
8262           function
8263           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8264           | Bool _ | Int _ | Int64 _
8265           | FileIn _ | FileOut _ -> ()
8266           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8267         ) (snd style)
8268       in
8269
8270       (* Code. *)
8271       (match fst style with
8272        | RErr ->
8273            pr "PREINIT:\n";
8274            pr "      int r;\n";
8275            pr " PPCODE:\n";
8276            pr "      r = guestfs_%s " name;
8277            generate_c_call_args ~handle:"g" style;
8278            pr ";\n";
8279            do_cleanups ();
8280            pr "      if (r == -1)\n";
8281            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8282        | RInt n
8283        | RBool n ->
8284            pr "PREINIT:\n";
8285            pr "      int %s;\n" n;
8286            pr "   CODE:\n";
8287            pr "      %s = guestfs_%s " n name;
8288            generate_c_call_args ~handle:"g" style;
8289            pr ";\n";
8290            do_cleanups ();
8291            pr "      if (%s == -1)\n" n;
8292            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8293            pr "      RETVAL = newSViv (%s);\n" n;
8294            pr " OUTPUT:\n";
8295            pr "      RETVAL\n"
8296        | RInt64 n ->
8297            pr "PREINIT:\n";
8298            pr "      int64_t %s;\n" n;
8299            pr "   CODE:\n";
8300            pr "      %s = guestfs_%s " n name;
8301            generate_c_call_args ~handle:"g" style;
8302            pr ";\n";
8303            do_cleanups ();
8304            pr "      if (%s == -1)\n" n;
8305            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8306            pr "      RETVAL = my_newSVll (%s);\n" n;
8307            pr " OUTPUT:\n";
8308            pr "      RETVAL\n"
8309        | RConstString n ->
8310            pr "PREINIT:\n";
8311            pr "      const char *%s;\n" n;
8312            pr "   CODE:\n";
8313            pr "      %s = guestfs_%s " n name;
8314            generate_c_call_args ~handle:"g" style;
8315            pr ";\n";
8316            do_cleanups ();
8317            pr "      if (%s == NULL)\n" n;
8318            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8319            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8320            pr " OUTPUT:\n";
8321            pr "      RETVAL\n"
8322        | RConstOptString n ->
8323            pr "PREINIT:\n";
8324            pr "      const char *%s;\n" n;
8325            pr "   CODE:\n";
8326            pr "      %s = guestfs_%s " n name;
8327            generate_c_call_args ~handle:"g" style;
8328            pr ";\n";
8329            do_cleanups ();
8330            pr "      if (%s == NULL)\n" n;
8331            pr "        RETVAL = &PL_sv_undef;\n";
8332            pr "      else\n";
8333            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8334            pr " OUTPUT:\n";
8335            pr "      RETVAL\n"
8336        | RString n ->
8337            pr "PREINIT:\n";
8338            pr "      char *%s;\n" n;
8339            pr "   CODE:\n";
8340            pr "      %s = guestfs_%s " n name;
8341            generate_c_call_args ~handle:"g" style;
8342            pr ";\n";
8343            do_cleanups ();
8344            pr "      if (%s == NULL)\n" n;
8345            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8346            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8347            pr "      free (%s);\n" n;
8348            pr " OUTPUT:\n";
8349            pr "      RETVAL\n"
8350        | RStringList n | RHashtable n ->
8351            pr "PREINIT:\n";
8352            pr "      char **%s;\n" n;
8353            pr "      int i, n;\n";
8354            pr " PPCODE:\n";
8355            pr "      %s = guestfs_%s " n name;
8356            generate_c_call_args ~handle:"g" style;
8357            pr ";\n";
8358            do_cleanups ();
8359            pr "      if (%s == NULL)\n" n;
8360            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8361            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8362            pr "      EXTEND (SP, n);\n";
8363            pr "      for (i = 0; i < n; ++i) {\n";
8364            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8365            pr "        free (%s[i]);\n" n;
8366            pr "      }\n";
8367            pr "      free (%s);\n" n;
8368        | RStruct (n, typ) ->
8369            let cols = cols_of_struct typ in
8370            generate_perl_struct_code typ cols name style n do_cleanups
8371        | RStructList (n, typ) ->
8372            let cols = cols_of_struct typ in
8373            generate_perl_struct_list_code typ cols name style n do_cleanups
8374        | RBufferOut n ->
8375            pr "PREINIT:\n";
8376            pr "      char *%s;\n" n;
8377            pr "      size_t size;\n";
8378            pr "   CODE:\n";
8379            pr "      %s = guestfs_%s " n name;
8380            generate_c_call_args ~handle:"g" style;
8381            pr ";\n";
8382            do_cleanups ();
8383            pr "      if (%s == NULL)\n" n;
8384            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8385            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8386            pr "      free (%s);\n" n;
8387            pr " OUTPUT:\n";
8388            pr "      RETVAL\n"
8389       );
8390
8391       pr "\n"
8392   ) all_functions
8393
8394 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8395   pr "PREINIT:\n";
8396   pr "      struct guestfs_%s_list *%s;\n" typ n;
8397   pr "      int i;\n";
8398   pr "      HV *hv;\n";
8399   pr " PPCODE:\n";
8400   pr "      %s = guestfs_%s " n name;
8401   generate_c_call_args ~handle:"g" style;
8402   pr ";\n";
8403   do_cleanups ();
8404   pr "      if (%s == NULL)\n" n;
8405   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8406   pr "      EXTEND (SP, %s->len);\n" n;
8407   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8408   pr "        hv = newHV ();\n";
8409   List.iter (
8410     function
8411     | name, FString ->
8412         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8413           name (String.length name) n name
8414     | name, FUUID ->
8415         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8416           name (String.length name) n name
8417     | name, FBuffer ->
8418         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8419           name (String.length name) n name n name
8420     | name, (FBytes|FUInt64) ->
8421         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8422           name (String.length name) n name
8423     | name, FInt64 ->
8424         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8425           name (String.length name) n name
8426     | name, (FInt32|FUInt32) ->
8427         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8428           name (String.length name) n name
8429     | name, FChar ->
8430         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8431           name (String.length name) n name
8432     | name, FOptPercent ->
8433         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8434           name (String.length name) n name
8435   ) cols;
8436   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8437   pr "      }\n";
8438   pr "      guestfs_free_%s_list (%s);\n" typ n
8439
8440 and generate_perl_struct_code typ cols name style n do_cleanups =
8441   pr "PREINIT:\n";
8442   pr "      struct guestfs_%s *%s;\n" typ n;
8443   pr " PPCODE:\n";
8444   pr "      %s = guestfs_%s " n name;
8445   generate_c_call_args ~handle:"g" style;
8446   pr ";\n";
8447   do_cleanups ();
8448   pr "      if (%s == NULL)\n" n;
8449   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8450   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8451   List.iter (
8452     fun ((name, _) as col) ->
8453       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8454
8455       match col with
8456       | name, FString ->
8457           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8458             n name
8459       | name, FBuffer ->
8460           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8461             n name n name
8462       | name, FUUID ->
8463           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8464             n name
8465       | name, (FBytes|FUInt64) ->
8466           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8467             n name
8468       | name, FInt64 ->
8469           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8470             n name
8471       | name, (FInt32|FUInt32) ->
8472           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8473             n name
8474       | name, FChar ->
8475           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8476             n name
8477       | name, FOptPercent ->
8478           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8479             n name
8480   ) cols;
8481   pr "      free (%s);\n" n
8482
8483 (* Generate Sys/Guestfs.pm. *)
8484 and generate_perl_pm () =
8485   generate_header HashStyle LGPLv2plus;
8486
8487   pr "\
8488 =pod
8489
8490 =head1 NAME
8491
8492 Sys::Guestfs - Perl bindings for libguestfs
8493
8494 =head1 SYNOPSIS
8495
8496  use Sys::Guestfs;
8497
8498  my $h = Sys::Guestfs->new ();
8499  $h->add_drive ('guest.img');
8500  $h->launch ();
8501  $h->mount ('/dev/sda1', '/');
8502  $h->touch ('/hello');
8503  $h->sync ();
8504
8505 =head1 DESCRIPTION
8506
8507 The C<Sys::Guestfs> module provides a Perl XS binding to the
8508 libguestfs API for examining and modifying virtual machine
8509 disk images.
8510
8511 Amongst the things this is good for: making batch configuration
8512 changes to guests, getting disk used/free statistics (see also:
8513 virt-df), migrating between virtualization systems (see also:
8514 virt-p2v), performing partial backups, performing partial guest
8515 clones, cloning guests and changing registry/UUID/hostname info, and
8516 much else besides.
8517
8518 Libguestfs uses Linux kernel and qemu code, and can access any type of
8519 guest filesystem that Linux and qemu can, including but not limited
8520 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8521 schemes, qcow, qcow2, vmdk.
8522
8523 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8524 LVs, what filesystem is in each LV, etc.).  It can also run commands
8525 in the context of the guest.  Also you can access filesystems over
8526 FUSE.
8527
8528 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8529 functions for using libguestfs from Perl, including integration
8530 with libvirt.
8531
8532 =head1 ERRORS
8533
8534 All errors turn into calls to C<croak> (see L<Carp(3)>).
8535
8536 =head1 METHODS
8537
8538 =over 4
8539
8540 =cut
8541
8542 package Sys::Guestfs;
8543
8544 use strict;
8545 use warnings;
8546
8547 require XSLoader;
8548 XSLoader::load ('Sys::Guestfs');
8549
8550 =item $h = Sys::Guestfs->new ();
8551
8552 Create a new guestfs handle.
8553
8554 =cut
8555
8556 sub new {
8557   my $proto = shift;
8558   my $class = ref ($proto) || $proto;
8559
8560   my $self = Sys::Guestfs::_create ();
8561   bless $self, $class;
8562   return $self;
8563 }
8564
8565 ";
8566
8567   (* Actions.  We only need to print documentation for these as
8568    * they are pulled in from the XS code automatically.
8569    *)
8570   List.iter (
8571     fun (name, style, _, flags, _, _, longdesc) ->
8572       if not (List.mem NotInDocs flags) then (
8573         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8574         pr "=item ";
8575         generate_perl_prototype name style;
8576         pr "\n\n";
8577         pr "%s\n\n" longdesc;
8578         if List.mem ProtocolLimitWarning flags then
8579           pr "%s\n\n" protocol_limit_warning;
8580         if List.mem DangerWillRobinson flags then
8581           pr "%s\n\n" danger_will_robinson;
8582         match deprecation_notice flags with
8583         | None -> ()
8584         | Some txt -> pr "%s\n\n" txt
8585       )
8586   ) all_functions_sorted;
8587
8588   (* End of file. *)
8589   pr "\
8590 =cut
8591
8592 1;
8593
8594 =back
8595
8596 =head1 COPYRIGHT
8597
8598 Copyright (C) %s Red Hat Inc.
8599
8600 =head1 LICENSE
8601
8602 Please see the file COPYING.LIB for the full license.
8603
8604 =head1 SEE ALSO
8605
8606 L<guestfs(3)>,
8607 L<guestfish(1)>,
8608 L<http://libguestfs.org>,
8609 L<Sys::Guestfs::Lib(3)>.
8610
8611 =cut
8612 " copyright_years
8613
8614 and generate_perl_prototype name style =
8615   (match fst style with
8616    | RErr -> ()
8617    | RBool n
8618    | RInt n
8619    | RInt64 n
8620    | RConstString n
8621    | RConstOptString n
8622    | RString n
8623    | RBufferOut n -> pr "$%s = " n
8624    | RStruct (n,_)
8625    | RHashtable n -> pr "%%%s = " n
8626    | RStringList n
8627    | RStructList (n,_) -> pr "@%s = " n
8628   );
8629   pr "$h->%s (" name;
8630   let comma = ref false in
8631   List.iter (
8632     fun arg ->
8633       if !comma then pr ", ";
8634       comma := true;
8635       match arg with
8636       | Pathname n | Device n | Dev_or_Path n | String n
8637       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8638           pr "$%s" n
8639       | StringList n | DeviceList n ->
8640           pr "\\@%s" n
8641   ) (snd style);
8642   pr ");"
8643
8644 (* Generate Python C module. *)
8645 and generate_python_c () =
8646   generate_header CStyle LGPLv2plus;
8647
8648   pr "\
8649 #include <Python.h>
8650
8651 #include <stdio.h>
8652 #include <stdlib.h>
8653 #include <assert.h>
8654
8655 #include \"guestfs.h\"
8656
8657 typedef struct {
8658   PyObject_HEAD
8659   guestfs_h *g;
8660 } Pyguestfs_Object;
8661
8662 static guestfs_h *
8663 get_handle (PyObject *obj)
8664 {
8665   assert (obj);
8666   assert (obj != Py_None);
8667   return ((Pyguestfs_Object *) obj)->g;
8668 }
8669
8670 static PyObject *
8671 put_handle (guestfs_h *g)
8672 {
8673   assert (g);
8674   return
8675     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8676 }
8677
8678 /* This list should be freed (but not the strings) after use. */
8679 static char **
8680 get_string_list (PyObject *obj)
8681 {
8682   int i, len;
8683   char **r;
8684
8685   assert (obj);
8686
8687   if (!PyList_Check (obj)) {
8688     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8689     return NULL;
8690   }
8691
8692   len = PyList_Size (obj);
8693   r = malloc (sizeof (char *) * (len+1));
8694   if (r == NULL) {
8695     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8696     return NULL;
8697   }
8698
8699   for (i = 0; i < len; ++i)
8700     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8701   r[len] = NULL;
8702
8703   return r;
8704 }
8705
8706 static PyObject *
8707 put_string_list (char * const * const argv)
8708 {
8709   PyObject *list;
8710   int argc, i;
8711
8712   for (argc = 0; argv[argc] != NULL; ++argc)
8713     ;
8714
8715   list = PyList_New (argc);
8716   for (i = 0; i < argc; ++i)
8717     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8718
8719   return list;
8720 }
8721
8722 static PyObject *
8723 put_table (char * const * const argv)
8724 {
8725   PyObject *list, *item;
8726   int argc, i;
8727
8728   for (argc = 0; argv[argc] != NULL; ++argc)
8729     ;
8730
8731   list = PyList_New (argc >> 1);
8732   for (i = 0; i < argc; i += 2) {
8733     item = PyTuple_New (2);
8734     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8735     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8736     PyList_SetItem (list, i >> 1, item);
8737   }
8738
8739   return list;
8740 }
8741
8742 static void
8743 free_strings (char **argv)
8744 {
8745   int argc;
8746
8747   for (argc = 0; argv[argc] != NULL; ++argc)
8748     free (argv[argc]);
8749   free (argv);
8750 }
8751
8752 static PyObject *
8753 py_guestfs_create (PyObject *self, PyObject *args)
8754 {
8755   guestfs_h *g;
8756
8757   g = guestfs_create ();
8758   if (g == NULL) {
8759     PyErr_SetString (PyExc_RuntimeError,
8760                      \"guestfs.create: failed to allocate handle\");
8761     return NULL;
8762   }
8763   guestfs_set_error_handler (g, NULL, NULL);
8764   return put_handle (g);
8765 }
8766
8767 static PyObject *
8768 py_guestfs_close (PyObject *self, PyObject *args)
8769 {
8770   PyObject *py_g;
8771   guestfs_h *g;
8772
8773   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8774     return NULL;
8775   g = get_handle (py_g);
8776
8777   guestfs_close (g);
8778
8779   Py_INCREF (Py_None);
8780   return Py_None;
8781 }
8782
8783 ";
8784
8785   let emit_put_list_function typ =
8786     pr "static PyObject *\n";
8787     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8788     pr "{\n";
8789     pr "  PyObject *list;\n";
8790     pr "  int i;\n";
8791     pr "\n";
8792     pr "  list = PyList_New (%ss->len);\n" typ;
8793     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8794     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8795     pr "  return list;\n";
8796     pr "};\n";
8797     pr "\n"
8798   in
8799
8800   (* Structures, turned into Python dictionaries. *)
8801   List.iter (
8802     fun (typ, cols) ->
8803       pr "static PyObject *\n";
8804       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8805       pr "{\n";
8806       pr "  PyObject *dict;\n";
8807       pr "\n";
8808       pr "  dict = PyDict_New ();\n";
8809       List.iter (
8810         function
8811         | name, FString ->
8812             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8813             pr "                        PyString_FromString (%s->%s));\n"
8814               typ name
8815         | name, FBuffer ->
8816             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8817             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8818               typ name typ name
8819         | name, FUUID ->
8820             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8821             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8822               typ name
8823         | name, (FBytes|FUInt64) ->
8824             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8825             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8826               typ name
8827         | name, FInt64 ->
8828             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8829             pr "                        PyLong_FromLongLong (%s->%s));\n"
8830               typ name
8831         | name, FUInt32 ->
8832             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8833             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8834               typ name
8835         | name, FInt32 ->
8836             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8837             pr "                        PyLong_FromLong (%s->%s));\n"
8838               typ name
8839         | name, FOptPercent ->
8840             pr "  if (%s->%s >= 0)\n" typ name;
8841             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8842             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8843               typ name;
8844             pr "  else {\n";
8845             pr "    Py_INCREF (Py_None);\n";
8846             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8847             pr "  }\n"
8848         | name, FChar ->
8849             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8850             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8851       ) cols;
8852       pr "  return dict;\n";
8853       pr "};\n";
8854       pr "\n";
8855
8856   ) structs;
8857
8858   (* Emit a put_TYPE_list function definition only if that function is used. *)
8859   List.iter (
8860     function
8861     | typ, (RStructListOnly | RStructAndList) ->
8862         (* generate the function for typ *)
8863         emit_put_list_function typ
8864     | typ, _ -> () (* empty *)
8865   ) (rstructs_used_by all_functions);
8866
8867   (* Python wrapper functions. *)
8868   List.iter (
8869     fun (name, style, _, _, _, _, _) ->
8870       pr "static PyObject *\n";
8871       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8872       pr "{\n";
8873
8874       pr "  PyObject *py_g;\n";
8875       pr "  guestfs_h *g;\n";
8876       pr "  PyObject *py_r;\n";
8877
8878       let error_code =
8879         match fst style with
8880         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8881         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8882         | RConstString _ | RConstOptString _ ->
8883             pr "  const char *r;\n"; "NULL"
8884         | RString _ -> pr "  char *r;\n"; "NULL"
8885         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8886         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8887         | RStructList (_, typ) ->
8888             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8889         | RBufferOut _ ->
8890             pr "  char *r;\n";
8891             pr "  size_t size;\n";
8892             "NULL" in
8893
8894       List.iter (
8895         function
8896         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8897             pr "  const char *%s;\n" n
8898         | OptString n -> pr "  const char *%s;\n" n
8899         | StringList n | DeviceList n ->
8900             pr "  PyObject *py_%s;\n" n;
8901             pr "  char **%s;\n" n
8902         | Bool n -> pr "  int %s;\n" n
8903         | Int n -> pr "  int %s;\n" n
8904         | Int64 n -> pr "  long long %s;\n" n
8905       ) (snd style);
8906
8907       pr "\n";
8908
8909       (* Convert the parameters. *)
8910       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8911       List.iter (
8912         function
8913         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8914         | OptString _ -> pr "z"
8915         | StringList _ | DeviceList _ -> pr "O"
8916         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8917         | Int _ -> pr "i"
8918         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8919                              * emulate C's int/long/long long in Python?
8920                              *)
8921       ) (snd style);
8922       pr ":guestfs_%s\",\n" name;
8923       pr "                         &py_g";
8924       List.iter (
8925         function
8926         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8927         | OptString n -> pr ", &%s" n
8928         | StringList n | DeviceList n -> pr ", &py_%s" n
8929         | Bool n -> pr ", &%s" n
8930         | Int n -> pr ", &%s" n
8931         | Int64 n -> pr ", &%s" n
8932       ) (snd style);
8933
8934       pr "))\n";
8935       pr "    return NULL;\n";
8936
8937       pr "  g = get_handle (py_g);\n";
8938       List.iter (
8939         function
8940         | Pathname _ | Device _ | Dev_or_Path _ | String _
8941         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8942         | StringList n | DeviceList n ->
8943             pr "  %s = get_string_list (py_%s);\n" n n;
8944             pr "  if (!%s) return NULL;\n" n
8945       ) (snd style);
8946
8947       pr "\n";
8948
8949       pr "  r = guestfs_%s " name;
8950       generate_c_call_args ~handle:"g" style;
8951       pr ";\n";
8952
8953       List.iter (
8954         function
8955         | Pathname _ | Device _ | Dev_or_Path _ | String _
8956         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8957         | StringList n | DeviceList n ->
8958             pr "  free (%s);\n" n
8959       ) (snd style);
8960
8961       pr "  if (r == %s) {\n" error_code;
8962       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8963       pr "    return NULL;\n";
8964       pr "  }\n";
8965       pr "\n";
8966
8967       (match fst style with
8968        | RErr ->
8969            pr "  Py_INCREF (Py_None);\n";
8970            pr "  py_r = Py_None;\n"
8971        | RInt _
8972        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8973        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8974        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8975        | RConstOptString _ ->
8976            pr "  if (r)\n";
8977            pr "    py_r = PyString_FromString (r);\n";
8978            pr "  else {\n";
8979            pr "    Py_INCREF (Py_None);\n";
8980            pr "    py_r = Py_None;\n";
8981            pr "  }\n"
8982        | RString _ ->
8983            pr "  py_r = PyString_FromString (r);\n";
8984            pr "  free (r);\n"
8985        | RStringList _ ->
8986            pr "  py_r = put_string_list (r);\n";
8987            pr "  free_strings (r);\n"
8988        | RStruct (_, typ) ->
8989            pr "  py_r = put_%s (r);\n" typ;
8990            pr "  guestfs_free_%s (r);\n" typ
8991        | RStructList (_, typ) ->
8992            pr "  py_r = put_%s_list (r);\n" typ;
8993            pr "  guestfs_free_%s_list (r);\n" typ
8994        | RHashtable n ->
8995            pr "  py_r = put_table (r);\n";
8996            pr "  free_strings (r);\n"
8997        | RBufferOut _ ->
8998            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8999            pr "  free (r);\n"
9000       );
9001
9002       pr "  return py_r;\n";
9003       pr "}\n";
9004       pr "\n"
9005   ) all_functions;
9006
9007   (* Table of functions. *)
9008   pr "static PyMethodDef methods[] = {\n";
9009   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9010   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9011   List.iter (
9012     fun (name, _, _, _, _, _, _) ->
9013       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9014         name name
9015   ) all_functions;
9016   pr "  { NULL, NULL, 0, NULL }\n";
9017   pr "};\n";
9018   pr "\n";
9019
9020   (* Init function. *)
9021   pr "\
9022 void
9023 initlibguestfsmod (void)
9024 {
9025   static int initialized = 0;
9026
9027   if (initialized) return;
9028   Py_InitModule ((char *) \"libguestfsmod\", methods);
9029   initialized = 1;
9030 }
9031 "
9032
9033 (* Generate Python module. *)
9034 and generate_python_py () =
9035   generate_header HashStyle LGPLv2plus;
9036
9037   pr "\
9038 u\"\"\"Python bindings for libguestfs
9039
9040 import guestfs
9041 g = guestfs.GuestFS ()
9042 g.add_drive (\"guest.img\")
9043 g.launch ()
9044 parts = g.list_partitions ()
9045
9046 The guestfs module provides a Python binding to the libguestfs API
9047 for examining and modifying virtual machine disk images.
9048
9049 Amongst the things this is good for: making batch configuration
9050 changes to guests, getting disk used/free statistics (see also:
9051 virt-df), migrating between virtualization systems (see also:
9052 virt-p2v), performing partial backups, performing partial guest
9053 clones, cloning guests and changing registry/UUID/hostname info, and
9054 much else besides.
9055
9056 Libguestfs uses Linux kernel and qemu code, and can access any type of
9057 guest filesystem that Linux and qemu can, including but not limited
9058 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9059 schemes, qcow, qcow2, vmdk.
9060
9061 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9062 LVs, what filesystem is in each LV, etc.).  It can also run commands
9063 in the context of the guest.  Also you can access filesystems over
9064 FUSE.
9065
9066 Errors which happen while using the API are turned into Python
9067 RuntimeError exceptions.
9068
9069 To create a guestfs handle you usually have to perform the following
9070 sequence of calls:
9071
9072 # Create the handle, call add_drive at least once, and possibly
9073 # several times if the guest has multiple block devices:
9074 g = guestfs.GuestFS ()
9075 g.add_drive (\"guest.img\")
9076
9077 # Launch the qemu subprocess and wait for it to become ready:
9078 g.launch ()
9079
9080 # Now you can issue commands, for example:
9081 logvols = g.lvs ()
9082
9083 \"\"\"
9084
9085 import libguestfsmod
9086
9087 class GuestFS:
9088     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9089
9090     def __init__ (self):
9091         \"\"\"Create a new libguestfs handle.\"\"\"
9092         self._o = libguestfsmod.create ()
9093
9094     def __del__ (self):
9095         libguestfsmod.close (self._o)
9096
9097 ";
9098
9099   List.iter (
9100     fun (name, style, _, flags, _, _, longdesc) ->
9101       pr "    def %s " name;
9102       generate_py_call_args ~handle:"self" (snd style);
9103       pr ":\n";
9104
9105       if not (List.mem NotInDocs flags) then (
9106         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9107         let doc =
9108           match fst style with
9109           | RErr | RInt _ | RInt64 _ | RBool _
9110           | RConstOptString _ | RConstString _
9111           | RString _ | RBufferOut _ -> doc
9112           | RStringList _ ->
9113               doc ^ "\n\nThis function returns a list of strings."
9114           | RStruct (_, typ) ->
9115               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9116           | RStructList (_, typ) ->
9117               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9118           | RHashtable _ ->
9119               doc ^ "\n\nThis function returns a dictionary." in
9120         let doc =
9121           if List.mem ProtocolLimitWarning flags then
9122             doc ^ "\n\n" ^ protocol_limit_warning
9123           else doc in
9124         let doc =
9125           if List.mem DangerWillRobinson flags then
9126             doc ^ "\n\n" ^ danger_will_robinson
9127           else doc in
9128         let doc =
9129           match deprecation_notice flags with
9130           | None -> doc
9131           | Some txt -> doc ^ "\n\n" ^ txt in
9132         let doc = pod2text ~width:60 name doc in
9133         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9134         let doc = String.concat "\n        " doc in
9135         pr "        u\"\"\"%s\"\"\"\n" doc;
9136       );
9137       pr "        return libguestfsmod.%s " name;
9138       generate_py_call_args ~handle:"self._o" (snd style);
9139       pr "\n";
9140       pr "\n";
9141   ) all_functions
9142
9143 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9144 and generate_py_call_args ~handle args =
9145   pr "(%s" handle;
9146   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9147   pr ")"
9148
9149 (* Useful if you need the longdesc POD text as plain text.  Returns a
9150  * list of lines.
9151  *
9152  * Because this is very slow (the slowest part of autogeneration),
9153  * we memoize the results.
9154  *)
9155 and pod2text ~width name longdesc =
9156   let key = width, name, longdesc in
9157   try Hashtbl.find pod2text_memo key
9158   with Not_found ->
9159     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9160     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9161     close_out chan;
9162     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9163     let chan = open_process_in cmd in
9164     let lines = ref [] in
9165     let rec loop i =
9166       let line = input_line chan in
9167       if i = 1 then             (* discard the first line of output *)
9168         loop (i+1)
9169       else (
9170         let line = triml line in
9171         lines := line :: !lines;
9172         loop (i+1)
9173       ) in
9174     let lines = try loop 1 with End_of_file -> List.rev !lines in
9175     unlink filename;
9176     (match close_process_in chan with
9177      | WEXITED 0 -> ()
9178      | WEXITED i ->
9179          failwithf "pod2text: process exited with non-zero status (%d)" i
9180      | WSIGNALED i | WSTOPPED i ->
9181          failwithf "pod2text: process signalled or stopped by signal %d" i
9182     );
9183     Hashtbl.add pod2text_memo key lines;
9184     pod2text_memo_updated ();
9185     lines
9186
9187 (* Generate ruby bindings. *)
9188 and generate_ruby_c () =
9189   generate_header CStyle LGPLv2plus;
9190
9191   pr "\
9192 #include <stdio.h>
9193 #include <stdlib.h>
9194
9195 #include <ruby.h>
9196
9197 #include \"guestfs.h\"
9198
9199 #include \"extconf.h\"
9200
9201 /* For Ruby < 1.9 */
9202 #ifndef RARRAY_LEN
9203 #define RARRAY_LEN(r) (RARRAY((r))->len)
9204 #endif
9205
9206 static VALUE m_guestfs;                 /* guestfs module */
9207 static VALUE c_guestfs;                 /* guestfs_h handle */
9208 static VALUE e_Error;                   /* used for all errors */
9209
9210 static void ruby_guestfs_free (void *p)
9211 {
9212   if (!p) return;
9213   guestfs_close ((guestfs_h *) p);
9214 }
9215
9216 static VALUE ruby_guestfs_create (VALUE m)
9217 {
9218   guestfs_h *g;
9219
9220   g = guestfs_create ();
9221   if (!g)
9222     rb_raise (e_Error, \"failed to create guestfs handle\");
9223
9224   /* Don't print error messages to stderr by default. */
9225   guestfs_set_error_handler (g, NULL, NULL);
9226
9227   /* Wrap it, and make sure the close function is called when the
9228    * handle goes away.
9229    */
9230   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9231 }
9232
9233 static VALUE ruby_guestfs_close (VALUE gv)
9234 {
9235   guestfs_h *g;
9236   Data_Get_Struct (gv, guestfs_h, g);
9237
9238   ruby_guestfs_free (g);
9239   DATA_PTR (gv) = NULL;
9240
9241   return Qnil;
9242 }
9243
9244 ";
9245
9246   List.iter (
9247     fun (name, style, _, _, _, _, _) ->
9248       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9249       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9250       pr ")\n";
9251       pr "{\n";
9252       pr "  guestfs_h *g;\n";
9253       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9254       pr "  if (!g)\n";
9255       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9256         name;
9257       pr "\n";
9258
9259       List.iter (
9260         function
9261         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9262             pr "  Check_Type (%sv, T_STRING);\n" n;
9263             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9264             pr "  if (!%s)\n" n;
9265             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9266             pr "              \"%s\", \"%s\");\n" n name
9267         | OptString n ->
9268             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9269         | StringList n | DeviceList n ->
9270             pr "  char **%s;\n" n;
9271             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9272             pr "  {\n";
9273             pr "    int i, len;\n";
9274             pr "    len = RARRAY_LEN (%sv);\n" n;
9275             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9276               n;
9277             pr "    for (i = 0; i < len; ++i) {\n";
9278             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9279             pr "      %s[i] = StringValueCStr (v);\n" n;
9280             pr "    }\n";
9281             pr "    %s[len] = NULL;\n" n;
9282             pr "  }\n";
9283         | Bool n ->
9284             pr "  int %s = RTEST (%sv);\n" n n
9285         | Int n ->
9286             pr "  int %s = NUM2INT (%sv);\n" n n
9287         | Int64 n ->
9288             pr "  long long %s = NUM2LL (%sv);\n" n n
9289       ) (snd style);
9290       pr "\n";
9291
9292       let error_code =
9293         match fst style with
9294         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9295         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9296         | RConstString _ | RConstOptString _ ->
9297             pr "  const char *r;\n"; "NULL"
9298         | RString _ -> pr "  char *r;\n"; "NULL"
9299         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9300         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9301         | RStructList (_, typ) ->
9302             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9303         | RBufferOut _ ->
9304             pr "  char *r;\n";
9305             pr "  size_t size;\n";
9306             "NULL" in
9307       pr "\n";
9308
9309       pr "  r = guestfs_%s " name;
9310       generate_c_call_args ~handle:"g" style;
9311       pr ";\n";
9312
9313       List.iter (
9314         function
9315         | Pathname _ | Device _ | Dev_or_Path _ | String _
9316         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9317         | StringList n | DeviceList n ->
9318             pr "  free (%s);\n" n
9319       ) (snd style);
9320
9321       pr "  if (r == %s)\n" error_code;
9322       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9323       pr "\n";
9324
9325       (match fst style with
9326        | RErr ->
9327            pr "  return Qnil;\n"
9328        | RInt _ | RBool _ ->
9329            pr "  return INT2NUM (r);\n"
9330        | RInt64 _ ->
9331            pr "  return ULL2NUM (r);\n"
9332        | RConstString _ ->
9333            pr "  return rb_str_new2 (r);\n";
9334        | RConstOptString _ ->
9335            pr "  if (r)\n";
9336            pr "    return rb_str_new2 (r);\n";
9337            pr "  else\n";
9338            pr "    return Qnil;\n";
9339        | RString _ ->
9340            pr "  VALUE rv = rb_str_new2 (r);\n";
9341            pr "  free (r);\n";
9342            pr "  return rv;\n";
9343        | RStringList _ ->
9344            pr "  int i, len = 0;\n";
9345            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9346            pr "  VALUE rv = rb_ary_new2 (len);\n";
9347            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9348            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9349            pr "    free (r[i]);\n";
9350            pr "  }\n";
9351            pr "  free (r);\n";
9352            pr "  return rv;\n"
9353        | RStruct (_, typ) ->
9354            let cols = cols_of_struct typ in
9355            generate_ruby_struct_code typ cols
9356        | RStructList (_, typ) ->
9357            let cols = cols_of_struct typ in
9358            generate_ruby_struct_list_code typ cols
9359        | RHashtable _ ->
9360            pr "  VALUE rv = rb_hash_new ();\n";
9361            pr "  int i;\n";
9362            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9363            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9364            pr "    free (r[i]);\n";
9365            pr "    free (r[i+1]);\n";
9366            pr "  }\n";
9367            pr "  free (r);\n";
9368            pr "  return rv;\n"
9369        | RBufferOut _ ->
9370            pr "  VALUE rv = rb_str_new (r, size);\n";
9371            pr "  free (r);\n";
9372            pr "  return rv;\n";
9373       );
9374
9375       pr "}\n";
9376       pr "\n"
9377   ) all_functions;
9378
9379   pr "\
9380 /* Initialize the module. */
9381 void Init__guestfs ()
9382 {
9383   m_guestfs = rb_define_module (\"Guestfs\");
9384   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9385   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9386
9387   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9388   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9389
9390 ";
9391   (* Define the rest of the methods. *)
9392   List.iter (
9393     fun (name, style, _, _, _, _, _) ->
9394       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9395       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9396   ) all_functions;
9397
9398   pr "}\n"
9399
9400 (* Ruby code to return a struct. *)
9401 and generate_ruby_struct_code typ cols =
9402   pr "  VALUE rv = rb_hash_new ();\n";
9403   List.iter (
9404     function
9405     | name, FString ->
9406         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9407     | name, FBuffer ->
9408         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9409     | name, FUUID ->
9410         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9411     | name, (FBytes|FUInt64) ->
9412         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9413     | name, FInt64 ->
9414         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9415     | name, FUInt32 ->
9416         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9417     | name, FInt32 ->
9418         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9419     | name, FOptPercent ->
9420         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9421     | name, FChar -> (* XXX wrong? *)
9422         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9423   ) cols;
9424   pr "  guestfs_free_%s (r);\n" typ;
9425   pr "  return rv;\n"
9426
9427 (* Ruby code to return a struct list. *)
9428 and generate_ruby_struct_list_code typ cols =
9429   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9430   pr "  int i;\n";
9431   pr "  for (i = 0; i < r->len; ++i) {\n";
9432   pr "    VALUE hv = rb_hash_new ();\n";
9433   List.iter (
9434     function
9435     | name, FString ->
9436         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9437     | name, FBuffer ->
9438         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
9439     | name, FUUID ->
9440         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9441     | name, (FBytes|FUInt64) ->
9442         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9443     | name, FInt64 ->
9444         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9445     | name, FUInt32 ->
9446         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9447     | name, FInt32 ->
9448         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9449     | name, FOptPercent ->
9450         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9451     | name, FChar -> (* XXX wrong? *)
9452         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9453   ) cols;
9454   pr "    rb_ary_push (rv, hv);\n";
9455   pr "  }\n";
9456   pr "  guestfs_free_%s_list (r);\n" typ;
9457   pr "  return rv;\n"
9458
9459 (* Generate Java bindings GuestFS.java file. *)
9460 and generate_java_java () =
9461   generate_header CStyle LGPLv2plus;
9462
9463   pr "\
9464 package com.redhat.et.libguestfs;
9465
9466 import java.util.HashMap;
9467 import com.redhat.et.libguestfs.LibGuestFSException;
9468 import com.redhat.et.libguestfs.PV;
9469 import com.redhat.et.libguestfs.VG;
9470 import com.redhat.et.libguestfs.LV;
9471 import com.redhat.et.libguestfs.Stat;
9472 import com.redhat.et.libguestfs.StatVFS;
9473 import com.redhat.et.libguestfs.IntBool;
9474 import com.redhat.et.libguestfs.Dirent;
9475
9476 /**
9477  * The GuestFS object is a libguestfs handle.
9478  *
9479  * @author rjones
9480  */
9481 public class GuestFS {
9482   // Load the native code.
9483   static {
9484     System.loadLibrary (\"guestfs_jni\");
9485   }
9486
9487   /**
9488    * The native guestfs_h pointer.
9489    */
9490   long g;
9491
9492   /**
9493    * Create a libguestfs handle.
9494    *
9495    * @throws LibGuestFSException
9496    */
9497   public GuestFS () throws LibGuestFSException
9498   {
9499     g = _create ();
9500   }
9501   private native long _create () throws LibGuestFSException;
9502
9503   /**
9504    * Close a libguestfs handle.
9505    *
9506    * You can also leave handles to be collected by the garbage
9507    * collector, but this method ensures that the resources used
9508    * by the handle are freed up immediately.  If you call any
9509    * other methods after closing the handle, you will get an
9510    * exception.
9511    *
9512    * @throws LibGuestFSException
9513    */
9514   public void close () throws LibGuestFSException
9515   {
9516     if (g != 0)
9517       _close (g);
9518     g = 0;
9519   }
9520   private native void _close (long g) throws LibGuestFSException;
9521
9522   public void finalize () throws LibGuestFSException
9523   {
9524     close ();
9525   }
9526
9527 ";
9528
9529   List.iter (
9530     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9531       if not (List.mem NotInDocs flags); then (
9532         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9533         let doc =
9534           if List.mem ProtocolLimitWarning flags then
9535             doc ^ "\n\n" ^ protocol_limit_warning
9536           else doc in
9537         let doc =
9538           if List.mem DangerWillRobinson flags then
9539             doc ^ "\n\n" ^ danger_will_robinson
9540           else doc in
9541         let doc =
9542           match deprecation_notice flags with
9543           | None -> doc
9544           | Some txt -> doc ^ "\n\n" ^ txt in
9545         let doc = pod2text ~width:60 name doc in
9546         let doc = List.map (            (* RHBZ#501883 *)
9547           function
9548           | "" -> "<p>"
9549           | nonempty -> nonempty
9550         ) doc in
9551         let doc = String.concat "\n   * " doc in
9552
9553         pr "  /**\n";
9554         pr "   * %s\n" shortdesc;
9555         pr "   * <p>\n";
9556         pr "   * %s\n" doc;
9557         pr "   * @throws LibGuestFSException\n";
9558         pr "   */\n";
9559         pr "  ";
9560       );
9561       generate_java_prototype ~public:true ~semicolon:false name style;
9562       pr "\n";
9563       pr "  {\n";
9564       pr "    if (g == 0)\n";
9565       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9566         name;
9567       pr "    ";
9568       if fst style <> RErr then pr "return ";
9569       pr "_%s " name;
9570       generate_java_call_args ~handle:"g" (snd style);
9571       pr ";\n";
9572       pr "  }\n";
9573       pr "  ";
9574       generate_java_prototype ~privat:true ~native:true name style;
9575       pr "\n";
9576       pr "\n";
9577   ) all_functions;
9578
9579   pr "}\n"
9580
9581 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9582 and generate_java_call_args ~handle args =
9583   pr "(%s" handle;
9584   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9585   pr ")"
9586
9587 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9588     ?(semicolon=true) name style =
9589   if privat then pr "private ";
9590   if public then pr "public ";
9591   if native then pr "native ";
9592
9593   (* return type *)
9594   (match fst style with
9595    | RErr -> pr "void ";
9596    | RInt _ -> pr "int ";
9597    | RInt64 _ -> pr "long ";
9598    | RBool _ -> pr "boolean ";
9599    | RConstString _ | RConstOptString _ | RString _
9600    | RBufferOut _ -> pr "String ";
9601    | RStringList _ -> pr "String[] ";
9602    | RStruct (_, typ) ->
9603        let name = java_name_of_struct typ in
9604        pr "%s " name;
9605    | RStructList (_, typ) ->
9606        let name = java_name_of_struct typ in
9607        pr "%s[] " name;
9608    | RHashtable _ -> pr "HashMap<String,String> ";
9609   );
9610
9611   if native then pr "_%s " name else pr "%s " name;
9612   pr "(";
9613   let needs_comma = ref false in
9614   if native then (
9615     pr "long g";
9616     needs_comma := true
9617   );
9618
9619   (* args *)
9620   List.iter (
9621     fun arg ->
9622       if !needs_comma then pr ", ";
9623       needs_comma := true;
9624
9625       match arg with
9626       | Pathname n
9627       | Device n | Dev_or_Path n
9628       | String n
9629       | OptString n
9630       | FileIn n
9631       | FileOut n ->
9632           pr "String %s" n
9633       | StringList n | DeviceList n ->
9634           pr "String[] %s" n
9635       | Bool n ->
9636           pr "boolean %s" n
9637       | Int n ->
9638           pr "int %s" n
9639       | Int64 n ->
9640           pr "long %s" n
9641   ) (snd style);
9642
9643   pr ")\n";
9644   pr "    throws LibGuestFSException";
9645   if semicolon then pr ";"
9646
9647 and generate_java_struct jtyp cols () =
9648   generate_header CStyle LGPLv2plus;
9649
9650   pr "\
9651 package com.redhat.et.libguestfs;
9652
9653 /**
9654  * Libguestfs %s structure.
9655  *
9656  * @author rjones
9657  * @see GuestFS
9658  */
9659 public class %s {
9660 " jtyp jtyp;
9661
9662   List.iter (
9663     function
9664     | name, FString
9665     | name, FUUID
9666     | name, FBuffer -> pr "  public String %s;\n" name
9667     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9668     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9669     | name, FChar -> pr "  public char %s;\n" name
9670     | name, FOptPercent ->
9671         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9672         pr "  public float %s;\n" name
9673   ) cols;
9674
9675   pr "}\n"
9676
9677 and generate_java_c () =
9678   generate_header CStyle LGPLv2plus;
9679
9680   pr "\
9681 #include <stdio.h>
9682 #include <stdlib.h>
9683 #include <string.h>
9684
9685 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9686 #include \"guestfs.h\"
9687
9688 /* Note that this function returns.  The exception is not thrown
9689  * until after the wrapper function returns.
9690  */
9691 static void
9692 throw_exception (JNIEnv *env, const char *msg)
9693 {
9694   jclass cl;
9695   cl = (*env)->FindClass (env,
9696                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9697   (*env)->ThrowNew (env, cl, msg);
9698 }
9699
9700 JNIEXPORT jlong JNICALL
9701 Java_com_redhat_et_libguestfs_GuestFS__1create
9702   (JNIEnv *env, jobject obj)
9703 {
9704   guestfs_h *g;
9705
9706   g = guestfs_create ();
9707   if (g == NULL) {
9708     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9709     return 0;
9710   }
9711   guestfs_set_error_handler (g, NULL, NULL);
9712   return (jlong) (long) g;
9713 }
9714
9715 JNIEXPORT void JNICALL
9716 Java_com_redhat_et_libguestfs_GuestFS__1close
9717   (JNIEnv *env, jobject obj, jlong jg)
9718 {
9719   guestfs_h *g = (guestfs_h *) (long) jg;
9720   guestfs_close (g);
9721 }
9722
9723 ";
9724
9725   List.iter (
9726     fun (name, style, _, _, _, _, _) ->
9727       pr "JNIEXPORT ";
9728       (match fst style with
9729        | RErr -> pr "void ";
9730        | RInt _ -> pr "jint ";
9731        | RInt64 _ -> pr "jlong ";
9732        | RBool _ -> pr "jboolean ";
9733        | RConstString _ | RConstOptString _ | RString _
9734        | RBufferOut _ -> pr "jstring ";
9735        | RStruct _ | RHashtable _ ->
9736            pr "jobject ";
9737        | RStringList _ | RStructList _ ->
9738            pr "jobjectArray ";
9739       );
9740       pr "JNICALL\n";
9741       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9742       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9743       pr "\n";
9744       pr "  (JNIEnv *env, jobject obj, jlong jg";
9745       List.iter (
9746         function
9747         | Pathname n
9748         | Device n | Dev_or_Path n
9749         | String n
9750         | OptString n
9751         | FileIn n
9752         | FileOut n ->
9753             pr ", jstring j%s" n
9754         | StringList n | DeviceList n ->
9755             pr ", jobjectArray j%s" n
9756         | Bool n ->
9757             pr ", jboolean j%s" n
9758         | Int n ->
9759             pr ", jint j%s" n
9760         | Int64 n ->
9761             pr ", jlong j%s" n
9762       ) (snd style);
9763       pr ")\n";
9764       pr "{\n";
9765       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9766       let error_code, no_ret =
9767         match fst style with
9768         | RErr -> pr "  int r;\n"; "-1", ""
9769         | RBool _
9770         | RInt _ -> pr "  int r;\n"; "-1", "0"
9771         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9772         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9773         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9774         | RString _ ->
9775             pr "  jstring jr;\n";
9776             pr "  char *r;\n"; "NULL", "NULL"
9777         | RStringList _ ->
9778             pr "  jobjectArray jr;\n";
9779             pr "  int r_len;\n";
9780             pr "  jclass cl;\n";
9781             pr "  jstring jstr;\n";
9782             pr "  char **r;\n"; "NULL", "NULL"
9783         | RStruct (_, typ) ->
9784             pr "  jobject jr;\n";
9785             pr "  jclass cl;\n";
9786             pr "  jfieldID fl;\n";
9787             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9788         | RStructList (_, typ) ->
9789             pr "  jobjectArray jr;\n";
9790             pr "  jclass cl;\n";
9791             pr "  jfieldID fl;\n";
9792             pr "  jobject jfl;\n";
9793             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9794         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9795         | RBufferOut _ ->
9796             pr "  jstring jr;\n";
9797             pr "  char *r;\n";
9798             pr "  size_t size;\n";
9799             "NULL", "NULL" in
9800       List.iter (
9801         function
9802         | Pathname n
9803         | Device n | Dev_or_Path n
9804         | String n
9805         | OptString n
9806         | FileIn n
9807         | FileOut n ->
9808             pr "  const char *%s;\n" n
9809         | StringList n | DeviceList n ->
9810             pr "  int %s_len;\n" n;
9811             pr "  const char **%s;\n" n
9812         | Bool n
9813         | Int n ->
9814             pr "  int %s;\n" n
9815         | Int64 n ->
9816             pr "  int64_t %s;\n" n
9817       ) (snd style);
9818
9819       let needs_i =
9820         (match fst style with
9821          | RStringList _ | RStructList _ -> true
9822          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9823          | RConstOptString _
9824          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9825           List.exists (function
9826                        | StringList _ -> true
9827                        | DeviceList _ -> true
9828                        | _ -> false) (snd style) in
9829       if needs_i then
9830         pr "  int i;\n";
9831
9832       pr "\n";
9833
9834       (* Get the parameters. *)
9835       List.iter (
9836         function
9837         | Pathname n
9838         | Device n | Dev_or_Path n
9839         | String n
9840         | FileIn n
9841         | FileOut n ->
9842             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9843         | OptString n ->
9844             (* This is completely undocumented, but Java null becomes
9845              * a NULL parameter.
9846              *)
9847             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9848         | StringList n | DeviceList n ->
9849             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9850             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9851             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9852             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9853               n;
9854             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9855             pr "  }\n";
9856             pr "  %s[%s_len] = NULL;\n" n n;
9857         | Bool n
9858         | Int n
9859         | Int64 n ->
9860             pr "  %s = j%s;\n" n n
9861       ) (snd style);
9862
9863       (* Make the call. *)
9864       pr "  r = guestfs_%s " name;
9865       generate_c_call_args ~handle:"g" style;
9866       pr ";\n";
9867
9868       (* Release the parameters. *)
9869       List.iter (
9870         function
9871         | Pathname n
9872         | Device n | Dev_or_Path n
9873         | String n
9874         | FileIn n
9875         | FileOut n ->
9876             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9877         | OptString n ->
9878             pr "  if (j%s)\n" n;
9879             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9880         | StringList n | DeviceList n ->
9881             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9882             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9883               n;
9884             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9885             pr "  }\n";
9886             pr "  free (%s);\n" n
9887         | Bool n
9888         | Int n
9889         | Int64 n -> ()
9890       ) (snd style);
9891
9892       (* Check for errors. *)
9893       pr "  if (r == %s) {\n" error_code;
9894       pr "    throw_exception (env, guestfs_last_error (g));\n";
9895       pr "    return %s;\n" no_ret;
9896       pr "  }\n";
9897
9898       (* Return value. *)
9899       (match fst style with
9900        | RErr -> ()
9901        | RInt _ -> pr "  return (jint) r;\n"
9902        | RBool _ -> pr "  return (jboolean) r;\n"
9903        | RInt64 _ -> pr "  return (jlong) r;\n"
9904        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9905        | RConstOptString _ ->
9906            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9907        | RString _ ->
9908            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9909            pr "  free (r);\n";
9910            pr "  return jr;\n"
9911        | RStringList _ ->
9912            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9913            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9914            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9915            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9916            pr "  for (i = 0; i < r_len; ++i) {\n";
9917            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9918            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9919            pr "    free (r[i]);\n";
9920            pr "  }\n";
9921            pr "  free (r);\n";
9922            pr "  return jr;\n"
9923        | RStruct (_, typ) ->
9924            let jtyp = java_name_of_struct typ in
9925            let cols = cols_of_struct typ in
9926            generate_java_struct_return typ jtyp cols
9927        | RStructList (_, typ) ->
9928            let jtyp = java_name_of_struct typ in
9929            let cols = cols_of_struct typ in
9930            generate_java_struct_list_return typ jtyp cols
9931        | RHashtable _ ->
9932            (* XXX *)
9933            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9934            pr "  return NULL;\n"
9935        | RBufferOut _ ->
9936            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9937            pr "  free (r);\n";
9938            pr "  return jr;\n"
9939       );
9940
9941       pr "}\n";
9942       pr "\n"
9943   ) all_functions
9944
9945 and generate_java_struct_return typ jtyp cols =
9946   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9947   pr "  jr = (*env)->AllocObject (env, cl);\n";
9948   List.iter (
9949     function
9950     | name, FString ->
9951         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9952         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9953     | name, FUUID ->
9954         pr "  {\n";
9955         pr "    char s[33];\n";
9956         pr "    memcpy (s, r->%s, 32);\n" name;
9957         pr "    s[32] = 0;\n";
9958         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9959         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9960         pr "  }\n";
9961     | name, FBuffer ->
9962         pr "  {\n";
9963         pr "    int len = r->%s_len;\n" name;
9964         pr "    char s[len+1];\n";
9965         pr "    memcpy (s, r->%s, len);\n" name;
9966         pr "    s[len] = 0;\n";
9967         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9968         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9969         pr "  }\n";
9970     | name, (FBytes|FUInt64|FInt64) ->
9971         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9972         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9973     | name, (FUInt32|FInt32) ->
9974         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9975         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9976     | name, FOptPercent ->
9977         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9978         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9979     | name, FChar ->
9980         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9981         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9982   ) cols;
9983   pr "  free (r);\n";
9984   pr "  return jr;\n"
9985
9986 and generate_java_struct_list_return typ jtyp cols =
9987   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9988   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9989   pr "  for (i = 0; i < r->len; ++i) {\n";
9990   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9991   List.iter (
9992     function
9993     | name, FString ->
9994         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9995         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9996     | name, FUUID ->
9997         pr "    {\n";
9998         pr "      char s[33];\n";
9999         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10000         pr "      s[32] = 0;\n";
10001         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10002         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10003         pr "    }\n";
10004     | name, FBuffer ->
10005         pr "    {\n";
10006         pr "      int len = r->val[i].%s_len;\n" name;
10007         pr "      char s[len+1];\n";
10008         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10009         pr "      s[len] = 0;\n";
10010         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10011         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10012         pr "    }\n";
10013     | name, (FBytes|FUInt64|FInt64) ->
10014         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10015         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10016     | name, (FUInt32|FInt32) ->
10017         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10018         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10019     | name, FOptPercent ->
10020         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10021         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10022     | name, FChar ->
10023         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10024         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10025   ) cols;
10026   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10027   pr "  }\n";
10028   pr "  guestfs_free_%s_list (r);\n" typ;
10029   pr "  return jr;\n"
10030
10031 and generate_java_makefile_inc () =
10032   generate_header HashStyle GPLv2plus;
10033
10034   pr "java_built_sources = \\\n";
10035   List.iter (
10036     fun (typ, jtyp) ->
10037         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10038   ) java_structs;
10039   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10040
10041 and generate_haskell_hs () =
10042   generate_header HaskellStyle LGPLv2plus;
10043
10044   (* XXX We only know how to generate partial FFI for Haskell
10045    * at the moment.  Please help out!
10046    *)
10047   let can_generate style =
10048     match style with
10049     | RErr, _
10050     | RInt _, _
10051     | RInt64 _, _ -> true
10052     | RBool _, _
10053     | RConstString _, _
10054     | RConstOptString _, _
10055     | RString _, _
10056     | RStringList _, _
10057     | RStruct _, _
10058     | RStructList _, _
10059     | RHashtable _, _
10060     | RBufferOut _, _ -> false in
10061
10062   pr "\
10063 {-# INCLUDE <guestfs.h> #-}
10064 {-# LANGUAGE ForeignFunctionInterface #-}
10065
10066 module Guestfs (
10067   create";
10068
10069   (* List out the names of the actions we want to export. *)
10070   List.iter (
10071     fun (name, style, _, _, _, _, _) ->
10072       if can_generate style then pr ",\n  %s" name
10073   ) all_functions;
10074
10075   pr "
10076   ) where
10077
10078 -- Unfortunately some symbols duplicate ones already present
10079 -- in Prelude.  We don't know which, so we hard-code a list
10080 -- here.
10081 import Prelude hiding (truncate)
10082
10083 import Foreign
10084 import Foreign.C
10085 import Foreign.C.Types
10086 import IO
10087 import Control.Exception
10088 import Data.Typeable
10089
10090 data GuestfsS = GuestfsS            -- represents the opaque C struct
10091 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10092 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10093
10094 -- XXX define properly later XXX
10095 data PV = PV
10096 data VG = VG
10097 data LV = LV
10098 data IntBool = IntBool
10099 data Stat = Stat
10100 data StatVFS = StatVFS
10101 data Hashtable = Hashtable
10102
10103 foreign import ccall unsafe \"guestfs_create\" c_create
10104   :: IO GuestfsP
10105 foreign import ccall unsafe \"&guestfs_close\" c_close
10106   :: FunPtr (GuestfsP -> IO ())
10107 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10108   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10109
10110 create :: IO GuestfsH
10111 create = do
10112   p <- c_create
10113   c_set_error_handler p nullPtr nullPtr
10114   h <- newForeignPtr c_close p
10115   return h
10116
10117 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10118   :: GuestfsP -> IO CString
10119
10120 -- last_error :: GuestfsH -> IO (Maybe String)
10121 -- last_error h = do
10122 --   str <- withForeignPtr h (\\p -> c_last_error p)
10123 --   maybePeek peekCString str
10124
10125 last_error :: GuestfsH -> IO (String)
10126 last_error h = do
10127   str <- withForeignPtr h (\\p -> c_last_error p)
10128   if (str == nullPtr)
10129     then return \"no error\"
10130     else peekCString str
10131
10132 ";
10133
10134   (* Generate wrappers for each foreign function. *)
10135   List.iter (
10136     fun (name, style, _, _, _, _, _) ->
10137       if can_generate style then (
10138         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10139         pr "  :: ";
10140         generate_haskell_prototype ~handle:"GuestfsP" style;
10141         pr "\n";
10142         pr "\n";
10143         pr "%s :: " name;
10144         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10145         pr "\n";
10146         pr "%s %s = do\n" name
10147           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10148         pr "  r <- ";
10149         (* Convert pointer arguments using with* functions. *)
10150         List.iter (
10151           function
10152           | FileIn n
10153           | FileOut n
10154           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10155           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10156           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10157           | Bool _ | Int _ | Int64 _ -> ()
10158         ) (snd style);
10159         (* Convert integer arguments. *)
10160         let args =
10161           List.map (
10162             function
10163             | Bool n -> sprintf "(fromBool %s)" n
10164             | Int n -> sprintf "(fromIntegral %s)" n
10165             | Int64 n -> sprintf "(fromIntegral %s)" n
10166             | FileIn n | FileOut n
10167             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10168           ) (snd style) in
10169         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10170           (String.concat " " ("p" :: args));
10171         (match fst style with
10172          | RErr | RInt _ | RInt64 _ | RBool _ ->
10173              pr "  if (r == -1)\n";
10174              pr "    then do\n";
10175              pr "      err <- last_error h\n";
10176              pr "      fail err\n";
10177          | RConstString _ | RConstOptString _ | RString _
10178          | RStringList _ | RStruct _
10179          | RStructList _ | RHashtable _ | RBufferOut _ ->
10180              pr "  if (r == nullPtr)\n";
10181              pr "    then do\n";
10182              pr "      err <- last_error h\n";
10183              pr "      fail err\n";
10184         );
10185         (match fst style with
10186          | RErr ->
10187              pr "    else return ()\n"
10188          | RInt _ ->
10189              pr "    else return (fromIntegral r)\n"
10190          | RInt64 _ ->
10191              pr "    else return (fromIntegral r)\n"
10192          | RBool _ ->
10193              pr "    else return (toBool r)\n"
10194          | RConstString _
10195          | RConstOptString _
10196          | RString _
10197          | RStringList _
10198          | RStruct _
10199          | RStructList _
10200          | RHashtable _
10201          | RBufferOut _ ->
10202              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10203         );
10204         pr "\n";
10205       )
10206   ) all_functions
10207
10208 and generate_haskell_prototype ~handle ?(hs = false) style =
10209   pr "%s -> " handle;
10210   let string = if hs then "String" else "CString" in
10211   let int = if hs then "Int" else "CInt" in
10212   let bool = if hs then "Bool" else "CInt" in
10213   let int64 = if hs then "Integer" else "Int64" in
10214   List.iter (
10215     fun arg ->
10216       (match arg with
10217        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10218        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10219        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10220        | Bool _ -> pr "%s" bool
10221        | Int _ -> pr "%s" int
10222        | Int64 _ -> pr "%s" int
10223        | FileIn _ -> pr "%s" string
10224        | FileOut _ -> pr "%s" string
10225       );
10226       pr " -> ";
10227   ) (snd style);
10228   pr "IO (";
10229   (match fst style with
10230    | RErr -> if not hs then pr "CInt"
10231    | RInt _ -> pr "%s" int
10232    | RInt64 _ -> pr "%s" int64
10233    | RBool _ -> pr "%s" bool
10234    | RConstString _ -> pr "%s" string
10235    | RConstOptString _ -> pr "Maybe %s" string
10236    | RString _ -> pr "%s" string
10237    | RStringList _ -> pr "[%s]" string
10238    | RStruct (_, typ) ->
10239        let name = java_name_of_struct typ in
10240        pr "%s" name
10241    | RStructList (_, typ) ->
10242        let name = java_name_of_struct typ in
10243        pr "[%s]" name
10244    | RHashtable _ -> pr "Hashtable"
10245    | RBufferOut _ -> pr "%s" string
10246   );
10247   pr ")"
10248
10249 and generate_csharp () =
10250   generate_header CPlusPlusStyle LGPLv2plus;
10251
10252   (* XXX Make this configurable by the C# assembly users. *)
10253   let library = "libguestfs.so.0" in
10254
10255   pr "\
10256 // These C# bindings are highly experimental at present.
10257 //
10258 // Firstly they only work on Linux (ie. Mono).  In order to get them
10259 // to work on Windows (ie. .Net) you would need to port the library
10260 // itself to Windows first.
10261 //
10262 // The second issue is that some calls are known to be incorrect and
10263 // can cause Mono to segfault.  Particularly: calls which pass or
10264 // return string[], or return any structure value.  This is because
10265 // we haven't worked out the correct way to do this from C#.
10266 //
10267 // The third issue is that when compiling you get a lot of warnings.
10268 // We are not sure whether the warnings are important or not.
10269 //
10270 // Fourthly we do not routinely build or test these bindings as part
10271 // of the make && make check cycle, which means that regressions might
10272 // go unnoticed.
10273 //
10274 // Suggestions and patches are welcome.
10275
10276 // To compile:
10277 //
10278 // gmcs Libguestfs.cs
10279 // mono Libguestfs.exe
10280 //
10281 // (You'll probably want to add a Test class / static main function
10282 // otherwise this won't do anything useful).
10283
10284 using System;
10285 using System.IO;
10286 using System.Runtime.InteropServices;
10287 using System.Runtime.Serialization;
10288 using System.Collections;
10289
10290 namespace Guestfs
10291 {
10292   class Error : System.ApplicationException
10293   {
10294     public Error (string message) : base (message) {}
10295     protected Error (SerializationInfo info, StreamingContext context) {}
10296   }
10297
10298   class Guestfs
10299   {
10300     IntPtr _handle;
10301
10302     [DllImport (\"%s\")]
10303     static extern IntPtr guestfs_create ();
10304
10305     public Guestfs ()
10306     {
10307       _handle = guestfs_create ();
10308       if (_handle == IntPtr.Zero)
10309         throw new Error (\"could not create guestfs handle\");
10310     }
10311
10312     [DllImport (\"%s\")]
10313     static extern void guestfs_close (IntPtr h);
10314
10315     ~Guestfs ()
10316     {
10317       guestfs_close (_handle);
10318     }
10319
10320     [DllImport (\"%s\")]
10321     static extern string guestfs_last_error (IntPtr h);
10322
10323 " library library library;
10324
10325   (* Generate C# structure bindings.  We prefix struct names with
10326    * underscore because C# cannot have conflicting struct names and
10327    * method names (eg. "class stat" and "stat").
10328    *)
10329   List.iter (
10330     fun (typ, cols) ->
10331       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10332       pr "    public class _%s {\n" typ;
10333       List.iter (
10334         function
10335         | name, FChar -> pr "      char %s;\n" name
10336         | name, FString -> pr "      string %s;\n" name
10337         | name, FBuffer ->
10338             pr "      uint %s_len;\n" name;
10339             pr "      string %s;\n" name
10340         | name, FUUID ->
10341             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10342             pr "      string %s;\n" name
10343         | name, FUInt32 -> pr "      uint %s;\n" name
10344         | name, FInt32 -> pr "      int %s;\n" name
10345         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10346         | name, FInt64 -> pr "      long %s;\n" name
10347         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10348       ) cols;
10349       pr "    }\n";
10350       pr "\n"
10351   ) structs;
10352
10353   (* Generate C# function bindings. *)
10354   List.iter (
10355     fun (name, style, _, _, _, shortdesc, _) ->
10356       let rec csharp_return_type () =
10357         match fst style with
10358         | RErr -> "void"
10359         | RBool n -> "bool"
10360         | RInt n -> "int"
10361         | RInt64 n -> "long"
10362         | RConstString n
10363         | RConstOptString n
10364         | RString n
10365         | RBufferOut n -> "string"
10366         | RStruct (_,n) -> "_" ^ n
10367         | RHashtable n -> "Hashtable"
10368         | RStringList n -> "string[]"
10369         | RStructList (_,n) -> sprintf "_%s[]" n
10370
10371       and c_return_type () =
10372         match fst style with
10373         | RErr
10374         | RBool _
10375         | RInt _ -> "int"
10376         | RInt64 _ -> "long"
10377         | RConstString _
10378         | RConstOptString _
10379         | RString _
10380         | RBufferOut _ -> "string"
10381         | RStruct (_,n) -> "_" ^ n
10382         | RHashtable _
10383         | RStringList _ -> "string[]"
10384         | RStructList (_,n) -> sprintf "_%s[]" n
10385
10386       and c_error_comparison () =
10387         match fst style with
10388         | RErr
10389         | RBool _
10390         | RInt _
10391         | RInt64 _ -> "== -1"
10392         | RConstString _
10393         | RConstOptString _
10394         | RString _
10395         | RBufferOut _
10396         | RStruct (_,_)
10397         | RHashtable _
10398         | RStringList _
10399         | RStructList (_,_) -> "== null"
10400
10401       and generate_extern_prototype () =
10402         pr "    static extern %s guestfs_%s (IntPtr h"
10403           (c_return_type ()) name;
10404         List.iter (
10405           function
10406           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10407           | FileIn n | FileOut n ->
10408               pr ", [In] string %s" n
10409           | StringList n | DeviceList n ->
10410               pr ", [In] string[] %s" n
10411           | Bool n ->
10412               pr ", bool %s" n
10413           | Int n ->
10414               pr ", int %s" n
10415           | Int64 n ->
10416               pr ", long %s" n
10417         ) (snd style);
10418         pr ");\n"
10419
10420       and generate_public_prototype () =
10421         pr "    public %s %s (" (csharp_return_type ()) name;
10422         let comma = ref false in
10423         let next () =
10424           if !comma then pr ", ";
10425           comma := true
10426         in
10427         List.iter (
10428           function
10429           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10430           | FileIn n | FileOut n ->
10431               next (); pr "string %s" n
10432           | StringList n | DeviceList n ->
10433               next (); pr "string[] %s" n
10434           | Bool n ->
10435               next (); pr "bool %s" n
10436           | Int n ->
10437               next (); pr "int %s" n
10438           | Int64 n ->
10439               next (); pr "long %s" n
10440         ) (snd style);
10441         pr ")\n"
10442
10443       and generate_call () =
10444         pr "guestfs_%s (_handle" name;
10445         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10446         pr ");\n";
10447       in
10448
10449       pr "    [DllImport (\"%s\")]\n" library;
10450       generate_extern_prototype ();
10451       pr "\n";
10452       pr "    /// <summary>\n";
10453       pr "    /// %s\n" shortdesc;
10454       pr "    /// </summary>\n";
10455       generate_public_prototype ();
10456       pr "    {\n";
10457       pr "      %s r;\n" (c_return_type ());
10458       pr "      r = ";
10459       generate_call ();
10460       pr "      if (r %s)\n" (c_error_comparison ());
10461       pr "        throw new Error (guestfs_last_error (_handle));\n";
10462       (match fst style with
10463        | RErr -> ()
10464        | RBool _ ->
10465            pr "      return r != 0 ? true : false;\n"
10466        | RHashtable _ ->
10467            pr "      Hashtable rr = new Hashtable ();\n";
10468            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10469            pr "        rr.Add (r[i], r[i+1]);\n";
10470            pr "      return rr;\n"
10471        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10472        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10473        | RStructList _ ->
10474            pr "      return r;\n"
10475       );
10476       pr "    }\n";
10477       pr "\n";
10478   ) all_functions_sorted;
10479
10480   pr "  }
10481 }
10482 "
10483
10484 and generate_bindtests () =
10485   generate_header CStyle LGPLv2plus;
10486
10487   pr "\
10488 #include <stdio.h>
10489 #include <stdlib.h>
10490 #include <inttypes.h>
10491 #include <string.h>
10492
10493 #include \"guestfs.h\"
10494 #include \"guestfs-internal.h\"
10495 #include \"guestfs-internal-actions.h\"
10496 #include \"guestfs_protocol.h\"
10497
10498 #define error guestfs_error
10499 #define safe_calloc guestfs_safe_calloc
10500 #define safe_malloc guestfs_safe_malloc
10501
10502 static void
10503 print_strings (char *const *argv)
10504 {
10505   int argc;
10506
10507   printf (\"[\");
10508   for (argc = 0; argv[argc] != NULL; ++argc) {
10509     if (argc > 0) printf (\", \");
10510     printf (\"\\\"%%s\\\"\", argv[argc]);
10511   }
10512   printf (\"]\\n\");
10513 }
10514
10515 /* The test0 function prints its parameters to stdout. */
10516 ";
10517
10518   let test0, tests =
10519     match test_functions with
10520     | [] -> assert false
10521     | test0 :: tests -> test0, tests in
10522
10523   let () =
10524     let (name, style, _, _, _, _, _) = test0 in
10525     generate_prototype ~extern:false ~semicolon:false ~newline:true
10526       ~handle:"g" ~prefix:"guestfs__" name style;
10527     pr "{\n";
10528     List.iter (
10529       function
10530       | Pathname n
10531       | Device n | Dev_or_Path n
10532       | String n
10533       | FileIn n
10534       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10535       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10536       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10537       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10538       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10539       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10540     ) (snd style);
10541     pr "  /* Java changes stdout line buffering so we need this: */\n";
10542     pr "  fflush (stdout);\n";
10543     pr "  return 0;\n";
10544     pr "}\n";
10545     pr "\n" in
10546
10547   List.iter (
10548     fun (name, style, _, _, _, _, _) ->
10549       if String.sub name (String.length name - 3) 3 <> "err" then (
10550         pr "/* Test normal return. */\n";
10551         generate_prototype ~extern:false ~semicolon:false ~newline:true
10552           ~handle:"g" ~prefix:"guestfs__" name style;
10553         pr "{\n";
10554         (match fst style with
10555          | RErr ->
10556              pr "  return 0;\n"
10557          | RInt _ ->
10558              pr "  int r;\n";
10559              pr "  sscanf (val, \"%%d\", &r);\n";
10560              pr "  return r;\n"
10561          | RInt64 _ ->
10562              pr "  int64_t r;\n";
10563              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10564              pr "  return r;\n"
10565          | RBool _ ->
10566              pr "  return STREQ (val, \"true\");\n"
10567          | RConstString _
10568          | RConstOptString _ ->
10569              (* Can't return the input string here.  Return a static
10570               * string so we ensure we get a segfault if the caller
10571               * tries to free it.
10572               *)
10573              pr "  return \"static string\";\n"
10574          | RString _ ->
10575              pr "  return strdup (val);\n"
10576          | RStringList _ ->
10577              pr "  char **strs;\n";
10578              pr "  int n, i;\n";
10579              pr "  sscanf (val, \"%%d\", &n);\n";
10580              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10581              pr "  for (i = 0; i < n; ++i) {\n";
10582              pr "    strs[i] = safe_malloc (g, 16);\n";
10583              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10584              pr "  }\n";
10585              pr "  strs[n] = NULL;\n";
10586              pr "  return strs;\n"
10587          | RStruct (_, typ) ->
10588              pr "  struct guestfs_%s *r;\n" typ;
10589              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10590              pr "  return r;\n"
10591          | RStructList (_, typ) ->
10592              pr "  struct guestfs_%s_list *r;\n" typ;
10593              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10594              pr "  sscanf (val, \"%%d\", &r->len);\n";
10595              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10596              pr "  return r;\n"
10597          | RHashtable _ ->
10598              pr "  char **strs;\n";
10599              pr "  int n, i;\n";
10600              pr "  sscanf (val, \"%%d\", &n);\n";
10601              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10602              pr "  for (i = 0; i < n; ++i) {\n";
10603              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10604              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10605              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10606              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10607              pr "  }\n";
10608              pr "  strs[n*2] = NULL;\n";
10609              pr "  return strs;\n"
10610          | RBufferOut _ ->
10611              pr "  return strdup (val);\n"
10612         );
10613         pr "}\n";
10614         pr "\n"
10615       ) else (
10616         pr "/* Test error return. */\n";
10617         generate_prototype ~extern:false ~semicolon:false ~newline:true
10618           ~handle:"g" ~prefix:"guestfs__" name style;
10619         pr "{\n";
10620         pr "  error (g, \"error\");\n";
10621         (match fst style with
10622          | RErr | RInt _ | RInt64 _ | RBool _ ->
10623              pr "  return -1;\n"
10624          | RConstString _ | RConstOptString _
10625          | RString _ | RStringList _ | RStruct _
10626          | RStructList _
10627          | RHashtable _
10628          | RBufferOut _ ->
10629              pr "  return NULL;\n"
10630         );
10631         pr "}\n";
10632         pr "\n"
10633       )
10634   ) tests
10635
10636 and generate_ocaml_bindtests () =
10637   generate_header OCamlStyle GPLv2plus;
10638
10639   pr "\
10640 let () =
10641   let g = Guestfs.create () in
10642 ";
10643
10644   let mkargs args =
10645     String.concat " " (
10646       List.map (
10647         function
10648         | CallString s -> "\"" ^ s ^ "\""
10649         | CallOptString None -> "None"
10650         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10651         | CallStringList xs ->
10652             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10653         | CallInt i when i >= 0 -> string_of_int i
10654         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10655         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10656         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10657         | CallBool b -> string_of_bool b
10658       ) args
10659     )
10660   in
10661
10662   generate_lang_bindtests (
10663     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10664   );
10665
10666   pr "print_endline \"EOF\"\n"
10667
10668 and generate_perl_bindtests () =
10669   pr "#!/usr/bin/perl -w\n";
10670   generate_header HashStyle GPLv2plus;
10671
10672   pr "\
10673 use strict;
10674
10675 use Sys::Guestfs;
10676
10677 my $g = Sys::Guestfs->new ();
10678 ";
10679
10680   let mkargs args =
10681     String.concat ", " (
10682       List.map (
10683         function
10684         | CallString s -> "\"" ^ s ^ "\""
10685         | CallOptString None -> "undef"
10686         | CallOptString (Some s) -> sprintf "\"%s\"" s
10687         | CallStringList xs ->
10688             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10689         | CallInt i -> string_of_int i
10690         | CallInt64 i -> Int64.to_string i
10691         | CallBool b -> if b then "1" else "0"
10692       ) args
10693     )
10694   in
10695
10696   generate_lang_bindtests (
10697     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10698   );
10699
10700   pr "print \"EOF\\n\"\n"
10701
10702 and generate_python_bindtests () =
10703   generate_header HashStyle GPLv2plus;
10704
10705   pr "\
10706 import guestfs
10707
10708 g = guestfs.GuestFS ()
10709 ";
10710
10711   let mkargs args =
10712     String.concat ", " (
10713       List.map (
10714         function
10715         | CallString s -> "\"" ^ s ^ "\""
10716         | CallOptString None -> "None"
10717         | CallOptString (Some s) -> sprintf "\"%s\"" s
10718         | CallStringList xs ->
10719             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10720         | CallInt i -> string_of_int i
10721         | CallInt64 i -> Int64.to_string i
10722         | CallBool b -> if b then "1" else "0"
10723       ) args
10724     )
10725   in
10726
10727   generate_lang_bindtests (
10728     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10729   );
10730
10731   pr "print \"EOF\"\n"
10732
10733 and generate_ruby_bindtests () =
10734   generate_header HashStyle GPLv2plus;
10735
10736   pr "\
10737 require 'guestfs'
10738
10739 g = Guestfs::create()
10740 ";
10741
10742   let mkargs args =
10743     String.concat ", " (
10744       List.map (
10745         function
10746         | CallString s -> "\"" ^ s ^ "\""
10747         | CallOptString None -> "nil"
10748         | CallOptString (Some s) -> sprintf "\"%s\"" s
10749         | CallStringList xs ->
10750             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10751         | CallInt i -> string_of_int i
10752         | CallInt64 i -> Int64.to_string i
10753         | CallBool b -> string_of_bool b
10754       ) args
10755     )
10756   in
10757
10758   generate_lang_bindtests (
10759     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10760   );
10761
10762   pr "print \"EOF\\n\"\n"
10763
10764 and generate_java_bindtests () =
10765   generate_header CStyle GPLv2plus;
10766
10767   pr "\
10768 import com.redhat.et.libguestfs.*;
10769
10770 public class Bindtests {
10771     public static void main (String[] argv)
10772     {
10773         try {
10774             GuestFS g = new GuestFS ();
10775 ";
10776
10777   let mkargs args =
10778     String.concat ", " (
10779       List.map (
10780         function
10781         | CallString s -> "\"" ^ s ^ "\""
10782         | CallOptString None -> "null"
10783         | CallOptString (Some s) -> sprintf "\"%s\"" s
10784         | CallStringList xs ->
10785             "new String[]{" ^
10786               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10787         | CallInt i -> string_of_int i
10788         | CallInt64 i -> Int64.to_string i
10789         | CallBool b -> string_of_bool b
10790       ) args
10791     )
10792   in
10793
10794   generate_lang_bindtests (
10795     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10796   );
10797
10798   pr "
10799             System.out.println (\"EOF\");
10800         }
10801         catch (Exception exn) {
10802             System.err.println (exn);
10803             System.exit (1);
10804         }
10805     }
10806 }
10807 "
10808
10809 and generate_haskell_bindtests () =
10810   generate_header HaskellStyle GPLv2plus;
10811
10812   pr "\
10813 module Bindtests where
10814 import qualified Guestfs
10815
10816 main = do
10817   g <- Guestfs.create
10818 ";
10819
10820   let mkargs args =
10821     String.concat " " (
10822       List.map (
10823         function
10824         | CallString s -> "\"" ^ s ^ "\""
10825         | CallOptString None -> "Nothing"
10826         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10827         | CallStringList xs ->
10828             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10829         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10830         | CallInt i -> string_of_int i
10831         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10832         | CallInt64 i -> Int64.to_string i
10833         | CallBool true -> "True"
10834         | CallBool false -> "False"
10835       ) args
10836     )
10837   in
10838
10839   generate_lang_bindtests (
10840     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10841   );
10842
10843   pr "  putStrLn \"EOF\"\n"
10844
10845 (* Language-independent bindings tests - we do it this way to
10846  * ensure there is parity in testing bindings across all languages.
10847  *)
10848 and generate_lang_bindtests call =
10849   call "test0" [CallString "abc"; CallOptString (Some "def");
10850                 CallStringList []; CallBool false;
10851                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10852   call "test0" [CallString "abc"; CallOptString None;
10853                 CallStringList []; CallBool false;
10854                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10855   call "test0" [CallString ""; CallOptString (Some "def");
10856                 CallStringList []; CallBool false;
10857                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10858   call "test0" [CallString ""; CallOptString (Some "");
10859                 CallStringList []; CallBool false;
10860                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10861   call "test0" [CallString "abc"; CallOptString (Some "def");
10862                 CallStringList ["1"]; CallBool false;
10863                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10864   call "test0" [CallString "abc"; CallOptString (Some "def");
10865                 CallStringList ["1"; "2"]; CallBool false;
10866                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10867   call "test0" [CallString "abc"; CallOptString (Some "def");
10868                 CallStringList ["1"]; CallBool true;
10869                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10870   call "test0" [CallString "abc"; CallOptString (Some "def");
10871                 CallStringList ["1"]; CallBool false;
10872                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10873   call "test0" [CallString "abc"; CallOptString (Some "def");
10874                 CallStringList ["1"]; CallBool false;
10875                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10876   call "test0" [CallString "abc"; CallOptString (Some "def");
10877                 CallStringList ["1"]; CallBool false;
10878                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10879   call "test0" [CallString "abc"; CallOptString (Some "def");
10880                 CallStringList ["1"]; CallBool false;
10881                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10882   call "test0" [CallString "abc"; CallOptString (Some "def");
10883                 CallStringList ["1"]; CallBool false;
10884                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10885   call "test0" [CallString "abc"; CallOptString (Some "def");
10886                 CallStringList ["1"]; CallBool false;
10887                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10888
10889 (* XXX Add here tests of the return and error functions. *)
10890
10891 (* Code to generator bindings for virt-inspector.  Currently only
10892  * implemented for OCaml code (for virt-p2v 2.0).
10893  *)
10894 let rng_input = "inspector/virt-inspector.rng"
10895
10896 (* Read the input file and parse it into internal structures.  This is
10897  * by no means a complete RELAX NG parser, but is just enough to be
10898  * able to parse the specific input file.
10899  *)
10900 type rng =
10901   | Element of string * rng list        (* <element name=name/> *)
10902   | Attribute of string * rng list        (* <attribute name=name/> *)
10903   | Interleave of rng list                (* <interleave/> *)
10904   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10905   | OneOrMore of rng                        (* <oneOrMore/> *)
10906   | Optional of rng                        (* <optional/> *)
10907   | Choice of string list                (* <choice><value/>*</choice> *)
10908   | Value of string                        (* <value>str</value> *)
10909   | Text                                (* <text/> *)
10910
10911 let rec string_of_rng = function
10912   | Element (name, xs) ->
10913       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10914   | Attribute (name, xs) ->
10915       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10916   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10917   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10918   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10919   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10920   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10921   | Value value -> "Value \"" ^ value ^ "\""
10922   | Text -> "Text"
10923
10924 and string_of_rng_list xs =
10925   String.concat ", " (List.map string_of_rng xs)
10926
10927 let rec parse_rng ?defines context = function
10928   | [] -> []
10929   | Xml.Element ("element", ["name", name], children) :: rest ->
10930       Element (name, parse_rng ?defines context children)
10931       :: parse_rng ?defines context rest
10932   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10933       Attribute (name, parse_rng ?defines context children)
10934       :: parse_rng ?defines context rest
10935   | Xml.Element ("interleave", [], children) :: rest ->
10936       Interleave (parse_rng ?defines context children)
10937       :: parse_rng ?defines context rest
10938   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10939       let rng = parse_rng ?defines context [child] in
10940       (match rng with
10941        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10942        | _ ->
10943            failwithf "%s: <zeroOrMore> contains more than one child element"
10944              context
10945       )
10946   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10947       let rng = parse_rng ?defines context [child] in
10948       (match rng with
10949        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10950        | _ ->
10951            failwithf "%s: <oneOrMore> contains more than one child element"
10952              context
10953       )
10954   | Xml.Element ("optional", [], [child]) :: rest ->
10955       let rng = parse_rng ?defines context [child] in
10956       (match rng with
10957        | [child] -> Optional child :: parse_rng ?defines context rest
10958        | _ ->
10959            failwithf "%s: <optional> contains more than one child element"
10960              context
10961       )
10962   | Xml.Element ("choice", [], children) :: rest ->
10963       let values = List.map (
10964         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10965         | _ ->
10966             failwithf "%s: can't handle anything except <value> in <choice>"
10967               context
10968       ) children in
10969       Choice values
10970       :: parse_rng ?defines context rest
10971   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10972       Value value :: parse_rng ?defines context rest
10973   | Xml.Element ("text", [], []) :: rest ->
10974       Text :: parse_rng ?defines context rest
10975   | Xml.Element ("ref", ["name", name], []) :: rest ->
10976       (* Look up the reference.  Because of limitations in this parser,
10977        * we can't handle arbitrarily nested <ref> yet.  You can only
10978        * use <ref> from inside <start>.
10979        *)
10980       (match defines with
10981        | None ->
10982            failwithf "%s: contains <ref>, but no refs are defined yet" context
10983        | Some map ->
10984            let rng = StringMap.find name map in
10985            rng @ parse_rng ?defines context rest
10986       )
10987   | x :: _ ->
10988       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10989
10990 let grammar =
10991   let xml = Xml.parse_file rng_input in
10992   match xml with
10993   | Xml.Element ("grammar", _,
10994                  Xml.Element ("start", _, gram) :: defines) ->
10995       (* The <define/> elements are referenced in the <start> section,
10996        * so build a map of those first.
10997        *)
10998       let defines = List.fold_left (
10999         fun map ->
11000           function Xml.Element ("define", ["name", name], defn) ->
11001             StringMap.add name defn map
11002           | _ ->
11003               failwithf "%s: expected <define name=name/>" rng_input
11004       ) StringMap.empty defines in
11005       let defines = StringMap.mapi parse_rng defines in
11006
11007       (* Parse the <start> clause, passing the defines. *)
11008       parse_rng ~defines "<start>" gram
11009   | _ ->
11010       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11011         rng_input
11012
11013 let name_of_field = function
11014   | Element (name, _) | Attribute (name, _)
11015   | ZeroOrMore (Element (name, _))
11016   | OneOrMore (Element (name, _))
11017   | Optional (Element (name, _)) -> name
11018   | Optional (Attribute (name, _)) -> name
11019   | Text -> (* an unnamed field in an element *)
11020       "data"
11021   | rng ->
11022       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11023
11024 (* At the moment this function only generates OCaml types.  However we
11025  * should parameterize it later so it can generate types/structs in a
11026  * variety of languages.
11027  *)
11028 let generate_types xs =
11029   (* A simple type is one that can be printed out directly, eg.
11030    * "string option".  A complex type is one which has a name and has
11031    * to be defined via another toplevel definition, eg. a struct.
11032    *
11033    * generate_type generates code for either simple or complex types.
11034    * In the simple case, it returns the string ("string option").  In
11035    * the complex case, it returns the name ("mountpoint").  In the
11036    * complex case it has to print out the definition before returning,
11037    * so it should only be called when we are at the beginning of a
11038    * new line (BOL context).
11039    *)
11040   let rec generate_type = function
11041     | Text ->                                (* string *)
11042         "string", true
11043     | Choice values ->                        (* [`val1|`val2|...] *)
11044         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11045     | ZeroOrMore rng ->                        (* <rng> list *)
11046         let t, is_simple = generate_type rng in
11047         t ^ " list (* 0 or more *)", is_simple
11048     | OneOrMore rng ->                        (* <rng> list *)
11049         let t, is_simple = generate_type rng in
11050         t ^ " list (* 1 or more *)", is_simple
11051                                         (* virt-inspector hack: bool *)
11052     | Optional (Attribute (name, [Value "1"])) ->
11053         "bool", true
11054     | Optional rng ->                        (* <rng> list *)
11055         let t, is_simple = generate_type rng in
11056         t ^ " option", is_simple
11057                                         (* type name = { fields ... } *)
11058     | Element (name, fields) when is_attrs_interleave fields ->
11059         generate_type_struct name (get_attrs_interleave fields)
11060     | Element (name, [field])                (* type name = field *)
11061     | Attribute (name, [field]) ->
11062         let t, is_simple = generate_type field in
11063         if is_simple then (t, true)
11064         else (
11065           pr "type %s = %s\n" name t;
11066           name, false
11067         )
11068     | Element (name, fields) ->              (* type name = { fields ... } *)
11069         generate_type_struct name fields
11070     | rng ->
11071         failwithf "generate_type failed at: %s" (string_of_rng rng)
11072
11073   and is_attrs_interleave = function
11074     | [Interleave _] -> true
11075     | Attribute _ :: fields -> is_attrs_interleave fields
11076     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11077     | _ -> false
11078
11079   and get_attrs_interleave = function
11080     | [Interleave fields] -> fields
11081     | ((Attribute _) as field) :: fields
11082     | ((Optional (Attribute _)) as field) :: fields ->
11083         field :: get_attrs_interleave fields
11084     | _ -> assert false
11085
11086   and generate_types xs =
11087     List.iter (fun x -> ignore (generate_type x)) xs
11088
11089   and generate_type_struct name fields =
11090     (* Calculate the types of the fields first.  We have to do this
11091      * before printing anything so we are still in BOL context.
11092      *)
11093     let types = List.map fst (List.map generate_type fields) in
11094
11095     (* Special case of a struct containing just a string and another
11096      * field.  Turn it into an assoc list.
11097      *)
11098     match types with
11099     | ["string"; other] ->
11100         let fname1, fname2 =
11101           match fields with
11102           | [f1; f2] -> name_of_field f1, name_of_field f2
11103           | _ -> assert false in
11104         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11105         name, false
11106
11107     | types ->
11108         pr "type %s = {\n" name;
11109         List.iter (
11110           fun (field, ftype) ->
11111             let fname = name_of_field field in
11112             pr "  %s_%s : %s;\n" name fname ftype
11113         ) (List.combine fields types);
11114         pr "}\n";
11115         (* Return the name of this type, and
11116          * false because it's not a simple type.
11117          *)
11118         name, false
11119   in
11120
11121   generate_types xs
11122
11123 let generate_parsers xs =
11124   (* As for generate_type above, generate_parser makes a parser for
11125    * some type, and returns the name of the parser it has generated.
11126    * Because it (may) need to print something, it should always be
11127    * called in BOL context.
11128    *)
11129   let rec generate_parser = function
11130     | Text ->                                (* string *)
11131         "string_child_or_empty"
11132     | Choice values ->                        (* [`val1|`val2|...] *)
11133         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11134           (String.concat "|"
11135              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11136     | ZeroOrMore rng ->                        (* <rng> list *)
11137         let pa = generate_parser rng in
11138         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11139     | OneOrMore rng ->                        (* <rng> list *)
11140         let pa = generate_parser rng in
11141         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11142                                         (* virt-inspector hack: bool *)
11143     | Optional (Attribute (name, [Value "1"])) ->
11144         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11145     | Optional rng ->                        (* <rng> list *)
11146         let pa = generate_parser rng in
11147         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11148                                         (* type name = { fields ... } *)
11149     | Element (name, fields) when is_attrs_interleave fields ->
11150         generate_parser_struct name (get_attrs_interleave fields)
11151     | Element (name, [field]) ->        (* type name = field *)
11152         let pa = generate_parser field in
11153         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11154         pr "let %s =\n" parser_name;
11155         pr "  %s\n" pa;
11156         pr "let parse_%s = %s\n" name parser_name;
11157         parser_name
11158     | Attribute (name, [field]) ->
11159         let pa = generate_parser field in
11160         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11161         pr "let %s =\n" parser_name;
11162         pr "  %s\n" pa;
11163         pr "let parse_%s = %s\n" name parser_name;
11164         parser_name
11165     | Element (name, fields) ->              (* type name = { fields ... } *)
11166         generate_parser_struct name ([], fields)
11167     | rng ->
11168         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11169
11170   and is_attrs_interleave = function
11171     | [Interleave _] -> true
11172     | Attribute _ :: fields -> is_attrs_interleave fields
11173     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11174     | _ -> false
11175
11176   and get_attrs_interleave = function
11177     | [Interleave fields] -> [], fields
11178     | ((Attribute _) as field) :: fields
11179     | ((Optional (Attribute _)) as field) :: fields ->
11180         let attrs, interleaves = get_attrs_interleave fields in
11181         (field :: attrs), interleaves
11182     | _ -> assert false
11183
11184   and generate_parsers xs =
11185     List.iter (fun x -> ignore (generate_parser x)) xs
11186
11187   and generate_parser_struct name (attrs, interleaves) =
11188     (* Generate parsers for the fields first.  We have to do this
11189      * before printing anything so we are still in BOL context.
11190      *)
11191     let fields = attrs @ interleaves in
11192     let pas = List.map generate_parser fields in
11193
11194     (* Generate an intermediate tuple from all the fields first.
11195      * If the type is just a string + another field, then we will
11196      * return this directly, otherwise it is turned into a record.
11197      *
11198      * RELAX NG note: This code treats <interleave> and plain lists of
11199      * fields the same.  In other words, it doesn't bother enforcing
11200      * any ordering of fields in the XML.
11201      *)
11202     pr "let parse_%s x =\n" name;
11203     pr "  let t = (\n    ";
11204     let comma = ref false in
11205     List.iter (
11206       fun x ->
11207         if !comma then pr ",\n    ";
11208         comma := true;
11209         match x with
11210         | Optional (Attribute (fname, [field])), pa ->
11211             pr "%s x" pa
11212         | Optional (Element (fname, [field])), pa ->
11213             pr "%s (optional_child %S x)" pa fname
11214         | Attribute (fname, [Text]), _ ->
11215             pr "attribute %S x" fname
11216         | (ZeroOrMore _ | OneOrMore _), pa ->
11217             pr "%s x" pa
11218         | Text, pa ->
11219             pr "%s x" pa
11220         | (field, pa) ->
11221             let fname = name_of_field field in
11222             pr "%s (child %S x)" pa fname
11223     ) (List.combine fields pas);
11224     pr "\n  ) in\n";
11225
11226     (match fields with
11227      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11228          pr "  t\n"
11229
11230      | _ ->
11231          pr "  (Obj.magic t : %s)\n" name
11232 (*
11233          List.iter (
11234            function
11235            | (Optional (Attribute (fname, [field])), pa) ->
11236                pr "  %s_%s =\n" name fname;
11237                pr "    %s x;\n" pa
11238            | (Optional (Element (fname, [field])), pa) ->
11239                pr "  %s_%s =\n" name fname;
11240                pr "    (let x = optional_child %S x in\n" fname;
11241                pr "     %s x);\n" pa
11242            | (field, pa) ->
11243                let fname = name_of_field field in
11244                pr "  %s_%s =\n" name fname;
11245                pr "    (let x = child %S x in\n" fname;
11246                pr "     %s x);\n" pa
11247          ) (List.combine fields pas);
11248          pr "}\n"
11249 *)
11250     );
11251     sprintf "parse_%s" name
11252   in
11253
11254   generate_parsers xs
11255
11256 (* Generate ocaml/guestfs_inspector.mli. *)
11257 let generate_ocaml_inspector_mli () =
11258   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11259
11260   pr "\
11261 (** This is an OCaml language binding to the external [virt-inspector]
11262     program.
11263
11264     For more information, please read the man page [virt-inspector(1)].
11265 *)
11266
11267 ";
11268
11269   generate_types grammar;
11270   pr "(** The nested information returned from the {!inspect} function. *)\n";
11271   pr "\n";
11272
11273   pr "\
11274 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11275 (** To inspect a libvirt domain called [name], pass a singleton
11276     list: [inspect [name]].  When using libvirt only, you may
11277     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11278
11279     To inspect a disk image or images, pass a list of the filenames
11280     of the disk images: [inspect filenames]
11281
11282     This function inspects the given guest or disk images and
11283     returns a list of operating system(s) found and a large amount
11284     of information about them.  In the vast majority of cases,
11285     a virtual machine only contains a single operating system.
11286
11287     If the optional [~xml] parameter is given, then this function
11288     skips running the external virt-inspector program and just
11289     parses the given XML directly (which is expected to be XML
11290     produced from a previous run of virt-inspector).  The list of
11291     names and connect URI are ignored in this case.
11292
11293     This function can throw a wide variety of exceptions, for example
11294     if the external virt-inspector program cannot be found, or if
11295     it doesn't generate valid XML.
11296 *)
11297 "
11298
11299 (* Generate ocaml/guestfs_inspector.ml. *)
11300 let generate_ocaml_inspector_ml () =
11301   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11302
11303   pr "open Unix\n";
11304   pr "\n";
11305
11306   generate_types grammar;
11307   pr "\n";
11308
11309   pr "\
11310 (* Misc functions which are used by the parser code below. *)
11311 let first_child = function
11312   | Xml.Element (_, _, c::_) -> c
11313   | Xml.Element (name, _, []) ->
11314       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11315   | Xml.PCData str ->
11316       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11317
11318 let string_child_or_empty = function
11319   | Xml.Element (_, _, [Xml.PCData s]) -> s
11320   | Xml.Element (_, _, []) -> \"\"
11321   | Xml.Element (x, _, _) ->
11322       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11323                 x ^ \" instead\")
11324   | Xml.PCData str ->
11325       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11326
11327 let optional_child name xml =
11328   let children = Xml.children xml in
11329   try
11330     Some (List.find (function
11331                      | Xml.Element (n, _, _) when n = name -> true
11332                      | _ -> false) children)
11333   with
11334     Not_found -> None
11335
11336 let child name xml =
11337   match optional_child name xml with
11338   | Some c -> c
11339   | None ->
11340       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11341
11342 let attribute name xml =
11343   try Xml.attrib xml name
11344   with Xml.No_attribute _ ->
11345     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11346
11347 ";
11348
11349   generate_parsers grammar;
11350   pr "\n";
11351
11352   pr "\
11353 (* Run external virt-inspector, then use parser to parse the XML. *)
11354 let inspect ?connect ?xml names =
11355   let xml =
11356     match xml with
11357     | None ->
11358         if names = [] then invalid_arg \"inspect: no names given\";
11359         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11360           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11361           names in
11362         let cmd = List.map Filename.quote cmd in
11363         let cmd = String.concat \" \" cmd in
11364         let chan = open_process_in cmd in
11365         let xml = Xml.parse_in chan in
11366         (match close_process_in chan with
11367          | WEXITED 0 -> ()
11368          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11369          | WSIGNALED i | WSTOPPED i ->
11370              failwith (\"external virt-inspector command died or stopped on sig \" ^
11371                        string_of_int i)
11372         );
11373         xml
11374     | Some doc ->
11375         Xml.parse_string doc in
11376   parse_operatingsystems xml
11377 "
11378
11379 (* This is used to generate the src/MAX_PROC_NR file which
11380  * contains the maximum procedure number, a surrogate for the
11381  * ABI version number.  See src/Makefile.am for the details.
11382  *)
11383 and generate_max_proc_nr () =
11384   let proc_nrs = List.map (
11385     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11386   ) daemon_functions in
11387
11388   let max_proc_nr = List.fold_left max 0 proc_nrs in
11389
11390   pr "%d\n" max_proc_nr
11391
11392 let output_to filename k =
11393   let filename_new = filename ^ ".new" in
11394   chan := open_out filename_new;
11395   k ();
11396   close_out !chan;
11397   chan := Pervasives.stdout;
11398
11399   (* Is the new file different from the current file? *)
11400   if Sys.file_exists filename && files_equal filename filename_new then
11401     unlink filename_new                 (* same, so skip it *)
11402   else (
11403     (* different, overwrite old one *)
11404     (try chmod filename 0o644 with Unix_error _ -> ());
11405     rename filename_new filename;
11406     chmod filename 0o444;
11407     printf "written %s\n%!" filename;
11408   )
11409
11410 let perror msg = function
11411   | Unix_error (err, _, _) ->
11412       eprintf "%s: %s\n" msg (error_message err)
11413   | exn ->
11414       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11415
11416 (* Main program. *)
11417 let () =
11418   let lock_fd =
11419     try openfile "HACKING" [O_RDWR] 0
11420     with
11421     | Unix_error (ENOENT, _, _) ->
11422         eprintf "\
11423 You are probably running this from the wrong directory.
11424 Run it from the top source directory using the command
11425   src/generator.ml
11426 ";
11427         exit 1
11428     | exn ->
11429         perror "open: HACKING" exn;
11430         exit 1 in
11431
11432   (* Acquire a lock so parallel builds won't try to run the generator
11433    * twice at the same time.  Subsequent builds will wait for the first
11434    * one to finish.  Note the lock is released implicitly when the
11435    * program exits.
11436    *)
11437   (try lockf lock_fd F_LOCK 1
11438    with exn ->
11439      perror "lock: HACKING" exn;
11440      exit 1);
11441
11442   check_functions ();
11443
11444   output_to "src/guestfs_protocol.x" generate_xdr;
11445   output_to "src/guestfs-structs.h" generate_structs_h;
11446   output_to "src/guestfs-actions.h" generate_actions_h;
11447   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11448   output_to "src/guestfs-actions.c" generate_client_actions;
11449   output_to "src/guestfs-bindtests.c" generate_bindtests;
11450   output_to "src/guestfs-structs.pod" generate_structs_pod;
11451   output_to "src/guestfs-actions.pod" generate_actions_pod;
11452   output_to "src/guestfs-availability.pod" generate_availability_pod;
11453   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11454   output_to "src/libguestfs.syms" generate_linker_script;
11455   output_to "daemon/actions.h" generate_daemon_actions_h;
11456   output_to "daemon/stubs.c" generate_daemon_actions;
11457   output_to "daemon/names.c" generate_daemon_names;
11458   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11459   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11460   output_to "capitests/tests.c" generate_tests;
11461   output_to "fish/cmds.c" generate_fish_cmds;
11462   output_to "fish/completion.c" generate_fish_completion;
11463   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11464   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11465   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11466   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11467   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11468   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11469   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11470   output_to "perl/Guestfs.xs" generate_perl_xs;
11471   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11472   output_to "perl/bindtests.pl" generate_perl_bindtests;
11473   output_to "python/guestfs-py.c" generate_python_c;
11474   output_to "python/guestfs.py" generate_python_py;
11475   output_to "python/bindtests.py" generate_python_bindtests;
11476   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11477   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11478   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11479
11480   List.iter (
11481     fun (typ, jtyp) ->
11482       let cols = cols_of_struct typ in
11483       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11484       output_to filename (generate_java_struct jtyp cols);
11485   ) java_structs;
11486
11487   output_to "java/Makefile.inc" generate_java_makefile_inc;
11488   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11489   output_to "java/Bindtests.java" generate_java_bindtests;
11490   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11491   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11492   output_to "csharp/Libguestfs.cs" generate_csharp;
11493
11494   (* Always generate this file last, and unconditionally.  It's used
11495    * by the Makefile to know when we must re-run the generator.
11496    *)
11497   let chan = open_out "src/stamp-generator" in
11498   fprintf chan "1\n";
11499   close_out chan;
11500
11501   printf "generated %d lines of code\n" !lines