grub-install: Enable grub-install tests and create explicit device.map file.
[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     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
811
812 I<Note:> Don't use this call to test for availability
813 of features.  In enterprise distributions we backport
814 features from later versions into earlier versions,
815 making this an unreliable way to test for features.
816 Use C<guestfs_available> instead.");
817
818   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
819    [InitNone, Always, TestOutputTrue (
820       [["set_selinux"; "true"];
821        ["get_selinux"]])],
822    "set SELinux enabled or disabled at appliance boot",
823    "\
824 This sets the selinux flag that is passed to the appliance
825 at boot time.  The default is C<selinux=0> (disabled).
826
827 Note that if SELinux is enabled, it is always in
828 Permissive mode (C<enforcing=0>).
829
830 For more information on the architecture of libguestfs,
831 see L<guestfs(3)>.");
832
833   ("get_selinux", (RBool "selinux", []), -1, [],
834    [],
835    "get SELinux enabled flag",
836    "\
837 This returns the current setting of the selinux flag which
838 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
839
840 For more information on the architecture of libguestfs,
841 see L<guestfs(3)>.");
842
843   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
844    [InitNone, Always, TestOutputFalse (
845       [["set_trace"; "false"];
846        ["get_trace"]])],
847    "enable or disable command traces",
848    "\
849 If the command trace flag is set to 1, then commands are
850 printed on stdout before they are executed in a format
851 which is very similar to the one used by guestfish.  In
852 other words, you can run a program with this enabled, and
853 you will get out a script which you can feed to guestfish
854 to perform the same set of actions.
855
856 If you want to trace C API calls into libguestfs (and
857 other libraries) then possibly a better way is to use
858 the external ltrace(1) command.
859
860 Command traces are disabled unless the environment variable
861 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
862
863   ("get_trace", (RBool "trace", []), -1, [],
864    [],
865    "get command trace enabled flag",
866    "\
867 Return the command trace flag.");
868
869   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
870    [InitNone, Always, TestOutputFalse (
871       [["set_direct"; "false"];
872        ["get_direct"]])],
873    "enable or disable direct appliance mode",
874    "\
875 If the direct appliance mode flag is enabled, then stdin and
876 stdout are passed directly through to the appliance once it
877 is launched.
878
879 One consequence of this is that log messages aren't caught
880 by the library and handled by C<guestfs_set_log_message_callback>,
881 but go straight to stdout.
882
883 You probably don't want to use this unless you know what you
884 are doing.
885
886 The default is disabled.");
887
888   ("get_direct", (RBool "direct", []), -1, [],
889    [],
890    "get direct appliance mode flag",
891    "\
892 Return the direct appliance mode flag.");
893
894   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
895    [InitNone, Always, TestOutputTrue (
896       [["set_recovery_proc"; "true"];
897        ["get_recovery_proc"]])],
898    "enable or disable the recovery process",
899    "\
900 If this is called with the parameter C<false> then
901 C<guestfs_launch> does not create a recovery process.  The
902 purpose of the recovery process is to stop runaway qemu
903 processes in the case where the main program aborts abruptly.
904
905 This only has any effect if called before C<guestfs_launch>,
906 and the default is true.
907
908 About the only time when you would want to disable this is
909 if the main process will fork itself into the background
910 (\"daemonize\" itself).  In this case the recovery process
911 thinks that the main program has disappeared and so kills
912 qemu, which is not very helpful.");
913
914   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
915    [],
916    "get recovery process enabled flag",
917    "\
918 Return the recovery process enabled flag.");
919
920   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
928    [],
929    "add a drive read-only specifying the QEMU block emulation to use",
930    "\
931 This is the same as C<guestfs_add_drive_ro> but it allows you
932 to specify the QEMU interface emulation to use at run time.");
933
934 ]
935
936 (* daemon_functions are any functions which cause some action
937  * to take place in the daemon.
938  *)
939
940 let daemon_functions = [
941   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
942    [InitEmpty, Always, TestOutput (
943       [["part_disk"; "/dev/sda"; "mbr"];
944        ["mkfs"; "ext2"; "/dev/sda1"];
945        ["mount"; "/dev/sda1"; "/"];
946        ["write"; "/new"; "new file contents"];
947        ["cat"; "/new"]], "new file contents")],
948    "mount a guest disk at a position in the filesystem",
949    "\
950 Mount a guest disk at a position in the filesystem.  Block devices
951 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
952 the guest.  If those block devices contain partitions, they will have
953 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
954 names can be used.
955
956 The rules are the same as for L<mount(2)>:  A filesystem must
957 first be mounted on C</> before others can be mounted.  Other
958 filesystems can only be mounted on directories which already
959 exist.
960
961 The mounted filesystem is writable, if we have sufficient permissions
962 on the underlying device.
963
964 B<Important note:>
965 When you use this call, the filesystem options C<sync> and C<noatime>
966 are set implicitly.  This was originally done because we thought it
967 would improve reliability, but it turns out that I<-o sync> has a
968 very large negative performance impact and negligible effect on
969 reliability.  Therefore we recommend that you avoid using
970 C<guestfs_mount> in any code that needs performance, and instead
971 use C<guestfs_mount_options> (use an empty string for the first
972 parameter if you don't want any options).");
973
974   ("sync", (RErr, []), 2, [],
975    [ InitEmpty, Always, TestRun [["sync"]]],
976    "sync disks, writes are flushed through to the disk image",
977    "\
978 This syncs the disk, so that any writes are flushed through to the
979 underlying disk image.
980
981 You should always call this if you have modified a disk image, before
982 closing the handle.");
983
984   ("touch", (RErr, [Pathname "path"]), 3, [],
985    [InitBasicFS, Always, TestOutputTrue (
986       [["touch"; "/new"];
987        ["exists"; "/new"]])],
988    "update file timestamps or create a new file",
989    "\
990 Touch acts like the L<touch(1)> command.  It can be used to
991 update the timestamps on a file, or, if the file does not exist,
992 to create a new zero-length file.");
993
994   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
995    [InitISOFS, Always, TestOutput (
996       [["cat"; "/known-2"]], "abcdef\n")],
997    "list the contents of a file",
998    "\
999 Return the contents of the file named C<path>.
1000
1001 Note that this function cannot correctly handle binary files
1002 (specifically, files containing C<\\0> character which is treated
1003 as end of string).  For those you need to use the C<guestfs_read_file>
1004 or C<guestfs_download> functions which have a more complex interface.");
1005
1006   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1007    [], (* XXX Tricky to test because it depends on the exact format
1008         * of the 'ls -l' command, which changes between F10 and F11.
1009         *)
1010    "list the files in a directory (long format)",
1011    "\
1012 List the files in C<directory> (relative to the root directory,
1013 there is no cwd) in the format of 'ls -la'.
1014
1015 This command is mostly useful for interactive sessions.  It
1016 is I<not> intended that you try to parse the output string.");
1017
1018   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1019    [InitBasicFS, Always, TestOutputList (
1020       [["touch"; "/new"];
1021        ["touch"; "/newer"];
1022        ["touch"; "/newest"];
1023        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1024    "list the files in a directory",
1025    "\
1026 List the files in C<directory> (relative to the root directory,
1027 there is no cwd).  The '.' and '..' entries are not returned, but
1028 hidden files are shown.
1029
1030 This command is mostly useful for interactive sessions.  Programs
1031 should probably use C<guestfs_readdir> instead.");
1032
1033   ("list_devices", (RStringList "devices", []), 7, [],
1034    [InitEmpty, Always, TestOutputListOfDevices (
1035       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1036    "list the block devices",
1037    "\
1038 List all the block devices.
1039
1040 The full block device names are returned, eg. C</dev/sda>");
1041
1042   ("list_partitions", (RStringList "partitions", []), 8, [],
1043    [InitBasicFS, Always, TestOutputListOfDevices (
1044       [["list_partitions"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048    "list the partitions",
1049    "\
1050 List all the partitions detected on all block devices.
1051
1052 The full partition device names are returned, eg. C</dev/sda1>
1053
1054 This does not return logical volumes.  For that you will need to
1055 call C<guestfs_lvs>.");
1056
1057   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1058    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1059       [["pvs"]], ["/dev/sda1"]);
1060     InitEmpty, Always, TestOutputListOfDevices (
1061       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1062        ["pvcreate"; "/dev/sda1"];
1063        ["pvcreate"; "/dev/sda2"];
1064        ["pvcreate"; "/dev/sda3"];
1065        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1066    "list the LVM physical volumes (PVs)",
1067    "\
1068 List all the physical volumes detected.  This is the equivalent
1069 of the L<pvs(8)> command.
1070
1071 This returns a list of just the device names that contain
1072 PVs (eg. C</dev/sda2>).
1073
1074 See also C<guestfs_pvs_full>.");
1075
1076   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1077    [InitBasicFSonLVM, Always, TestOutputList (
1078       [["vgs"]], ["VG"]);
1079     InitEmpty, Always, TestOutputList (
1080       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1081        ["pvcreate"; "/dev/sda1"];
1082        ["pvcreate"; "/dev/sda2"];
1083        ["pvcreate"; "/dev/sda3"];
1084        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1085        ["vgcreate"; "VG2"; "/dev/sda3"];
1086        ["vgs"]], ["VG1"; "VG2"])],
1087    "list the LVM volume groups (VGs)",
1088    "\
1089 List all the volumes groups detected.  This is the equivalent
1090 of the L<vgs(8)> command.
1091
1092 This returns a list of just the volume group names that were
1093 detected (eg. C<VolGroup00>).
1094
1095 See also C<guestfs_vgs_full>.");
1096
1097   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1098    [InitBasicFSonLVM, Always, TestOutputList (
1099       [["lvs"]], ["/dev/VG/LV"]);
1100     InitEmpty, Always, TestOutputList (
1101       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1102        ["pvcreate"; "/dev/sda1"];
1103        ["pvcreate"; "/dev/sda2"];
1104        ["pvcreate"; "/dev/sda3"];
1105        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1106        ["vgcreate"; "VG2"; "/dev/sda3"];
1107        ["lvcreate"; "LV1"; "VG1"; "50"];
1108        ["lvcreate"; "LV2"; "VG1"; "50"];
1109        ["lvcreate"; "LV3"; "VG2"; "50"];
1110        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1111    "list the LVM logical volumes (LVs)",
1112    "\
1113 List all the logical volumes detected.  This is the equivalent
1114 of the L<lvs(8)> command.
1115
1116 This returns a list of the logical volume device names
1117 (eg. C</dev/VolGroup00/LogVol00>).
1118
1119 See also C<guestfs_lvs_full>.");
1120
1121   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM physical volumes (PVs)",
1124    "\
1125 List all the physical volumes detected.  This is the equivalent
1126 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM volume groups (VGs)",
1131    "\
1132 List all the volumes groups detected.  This is the equivalent
1133 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1136    [], (* XXX how to test? *)
1137    "list the LVM logical volumes (LVs)",
1138    "\
1139 List all the logical volumes detected.  This is the equivalent
1140 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1141
1142   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1143    [InitISOFS, Always, TestOutputList (
1144       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1145     InitISOFS, Always, TestOutputList (
1146       [["read_lines"; "/empty"]], [])],
1147    "read file as lines",
1148    "\
1149 Return the contents of the file named C<path>.
1150
1151 The file contents are returned as a list of lines.  Trailing
1152 C<LF> and C<CRLF> character sequences are I<not> returned.
1153
1154 Note that this function cannot correctly handle binary files
1155 (specifically, files containing C<\\0> character which is treated
1156 as end of line).  For those you need to use the C<guestfs_read_file>
1157 function which has a more complex interface.");
1158
1159   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1160    [], (* XXX Augeas code needs tests. *)
1161    "create a new Augeas handle",
1162    "\
1163 Create a new Augeas handle for editing configuration files.
1164 If there was any previous Augeas handle associated with this
1165 guestfs session, then it is closed.
1166
1167 You must call this before using any other C<guestfs_aug_*>
1168 commands.
1169
1170 C<root> is the filesystem root.  C<root> must not be NULL,
1171 use C</> instead.
1172
1173 The flags are the same as the flags defined in
1174 E<lt>augeas.hE<gt>, the logical I<or> of the following
1175 integers:
1176
1177 =over 4
1178
1179 =item C<AUG_SAVE_BACKUP> = 1
1180
1181 Keep the original file with a C<.augsave> extension.
1182
1183 =item C<AUG_SAVE_NEWFILE> = 2
1184
1185 Save changes into a file with extension C<.augnew>, and
1186 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1187
1188 =item C<AUG_TYPE_CHECK> = 4
1189
1190 Typecheck lenses (can be expensive).
1191
1192 =item C<AUG_NO_STDINC> = 8
1193
1194 Do not use standard load path for modules.
1195
1196 =item C<AUG_SAVE_NOOP> = 16
1197
1198 Make save a no-op, just record what would have been changed.
1199
1200 =item C<AUG_NO_LOAD> = 32
1201
1202 Do not load the tree in C<guestfs_aug_init>.
1203
1204 =back
1205
1206 To close the handle, you can call C<guestfs_aug_close>.
1207
1208 To find out more about Augeas, see L<http://augeas.net/>.");
1209
1210   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1211    [], (* XXX Augeas code needs tests. *)
1212    "close the current Augeas handle",
1213    "\
1214 Close the current Augeas handle and free up any resources
1215 used by it.  After calling this, you have to call
1216 C<guestfs_aug_init> again before you can use any other
1217 Augeas functions.");
1218
1219   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "define an Augeas variable",
1222    "\
1223 Defines an Augeas variable C<name> whose value is the result
1224 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1225 undefined.
1226
1227 On success this returns the number of nodes in C<expr>, or
1228 C<0> if C<expr> evaluates to something which is not a nodeset.");
1229
1230   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "define an Augeas node",
1233    "\
1234 Defines a variable C<name> whose value is the result of
1235 evaluating C<expr>.
1236
1237 If C<expr> evaluates to an empty nodeset, a node is created,
1238 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1239 C<name> will be the nodeset containing that single node.
1240
1241 On success this returns a pair containing the
1242 number of nodes in the nodeset, and a boolean flag
1243 if a node was created.");
1244
1245   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "look up the value of an Augeas path",
1248    "\
1249 Look up the value associated with C<path>.  If C<path>
1250 matches exactly one node, the C<value> is returned.");
1251
1252   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "set Augeas path to value",
1255    "\
1256 Set the value associated with C<path> to C<val>.
1257
1258 In the Augeas API, it is possible to clear a node by setting
1259 the value to NULL.  Due to an oversight in the libguestfs API
1260 you cannot do that with this call.  Instead you must use the
1261 C<guestfs_aug_clear> call.");
1262
1263   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "insert a sibling Augeas node",
1266    "\
1267 Create a new sibling C<label> for C<path>, inserting it into
1268 the tree before or after C<path> (depending on the boolean
1269 flag C<before>).
1270
1271 C<path> must match exactly one existing node in the tree, and
1272 C<label> must be a label, ie. not contain C</>, C<*> or end
1273 with a bracketed index C<[N]>.");
1274
1275   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "remove an Augeas path",
1278    "\
1279 Remove C<path> and all of its children.
1280
1281 On success this returns the number of entries which were removed.");
1282
1283   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1284    [], (* XXX Augeas code needs tests. *)
1285    "move Augeas node",
1286    "\
1287 Move the node C<src> to C<dest>.  C<src> must match exactly
1288 one node.  C<dest> is overwritten if it exists.");
1289
1290   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "return Augeas nodes which match augpath",
1293    "\
1294 Returns a list of paths which match the path expression C<path>.
1295 The returned paths are sufficiently qualified so that they match
1296 exactly one node in the current tree.");
1297
1298   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1299    [], (* XXX Augeas code needs tests. *)
1300    "write all pending Augeas changes to disk",
1301    "\
1302 This writes all pending changes to disk.
1303
1304 The flags which were passed to C<guestfs_aug_init> affect exactly
1305 how files are saved.");
1306
1307   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1308    [], (* XXX Augeas code needs tests. *)
1309    "load files into the tree",
1310    "\
1311 Load files into the tree.
1312
1313 See C<aug_load> in the Augeas documentation for the full gory
1314 details.");
1315
1316   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1317    [], (* XXX Augeas code needs tests. *)
1318    "list Augeas nodes under augpath",
1319    "\
1320 This is just a shortcut for listing C<guestfs_aug_match>
1321 C<path/*> and sorting the resulting nodes into alphabetical order.");
1322
1323   ("rm", (RErr, [Pathname "path"]), 29, [],
1324    [InitBasicFS, Always, TestRun
1325       [["touch"; "/new"];
1326        ["rm"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["rm"; "/new"]];
1329     InitBasicFS, Always, TestLastFail
1330       [["mkdir"; "/new"];
1331        ["rm"; "/new"]]],
1332    "remove a file",
1333    "\
1334 Remove the single file C<path>.");
1335
1336   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1337    [InitBasicFS, Always, TestRun
1338       [["mkdir"; "/new"];
1339        ["rmdir"; "/new"]];
1340     InitBasicFS, Always, TestLastFail
1341       [["rmdir"; "/new"]];
1342     InitBasicFS, Always, TestLastFail
1343       [["touch"; "/new"];
1344        ["rmdir"; "/new"]]],
1345    "remove a directory",
1346    "\
1347 Remove the single directory C<path>.");
1348
1349   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1350    [InitBasicFS, Always, TestOutputFalse
1351       [["mkdir"; "/new"];
1352        ["mkdir"; "/new/foo"];
1353        ["touch"; "/new/foo/bar"];
1354        ["rm_rf"; "/new"];
1355        ["exists"; "/new"]]],
1356    "remove a file or directory recursively",
1357    "\
1358 Remove the file or directory C<path>, recursively removing the
1359 contents if its a directory.  This is like the C<rm -rf> shell
1360 command.");
1361
1362   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir"; "/new"];
1365        ["is_dir"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["mkdir"; "/new/foo/bar"]]],
1368    "create a directory",
1369    "\
1370 Create a directory named C<path>.");
1371
1372   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1373    [InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo/bar"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new/foo"]];
1379     InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new"]];
1382     (* Regression tests for RHBZ#503133: *)
1383     InitBasicFS, Always, TestRun
1384       [["mkdir"; "/new"];
1385        ["mkdir_p"; "/new"]];
1386     InitBasicFS, Always, TestLastFail
1387       [["touch"; "/new"];
1388        ["mkdir_p"; "/new"]]],
1389    "create a directory and parents",
1390    "\
1391 Create a directory named C<path>, creating any parent directories
1392 as necessary.  This is like the C<mkdir -p> shell command.");
1393
1394   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1395    [], (* XXX Need stat command to test *)
1396    "change file mode",
1397    "\
1398 Change the mode (permissions) of C<path> to C<mode>.  Only
1399 numeric modes are supported.
1400
1401 I<Note>: When using this command from guestfish, C<mode>
1402 by default would be decimal, unless you prefix it with
1403 C<0> to get octal, ie. use C<0700> not C<700>.
1404
1405 The mode actually set is affected by the umask.");
1406
1407   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1408    [], (* XXX Need stat command to test *)
1409    "change file owner and group",
1410    "\
1411 Change the file owner to C<owner> and group to C<group>.
1412
1413 Only numeric uid and gid are supported.  If you want to use
1414 names, you will need to locate and parse the password file
1415 yourself (Augeas support makes this relatively easy).");
1416
1417   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["exists"; "/empty"]]);
1420     InitISOFS, Always, TestOutputTrue (
1421       [["exists"; "/directory"]])],
1422    "test if file or directory exists",
1423    "\
1424 This returns C<true> if and only if there is a file, directory
1425 (or anything) with the given C<path> name.
1426
1427 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1428
1429   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1430    [InitISOFS, Always, TestOutputTrue (
1431       [["is_file"; "/known-1"]]);
1432     InitISOFS, Always, TestOutputFalse (
1433       [["is_file"; "/directory"]])],
1434    "test if file exists",
1435    "\
1436 This returns C<true> if and only if there is a file
1437 with the given C<path> name.  Note that it returns false for
1438 other objects like directories.
1439
1440 See also C<guestfs_stat>.");
1441
1442   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1443    [InitISOFS, Always, TestOutputFalse (
1444       [["is_dir"; "/known-3"]]);
1445     InitISOFS, Always, TestOutputTrue (
1446       [["is_dir"; "/directory"]])],
1447    "test if file exists",
1448    "\
1449 This returns C<true> if and only if there is a directory
1450 with the given C<path> name.  Note that it returns false for
1451 other objects like files.
1452
1453 See also C<guestfs_stat>.");
1454
1455   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1456    [InitEmpty, Always, TestOutputListOfDevices (
1457       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458        ["pvcreate"; "/dev/sda1"];
1459        ["pvcreate"; "/dev/sda2"];
1460        ["pvcreate"; "/dev/sda3"];
1461        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1462    "create an LVM physical volume",
1463    "\
1464 This creates an LVM physical volume on the named C<device>,
1465 where C<device> should usually be a partition name such
1466 as C</dev/sda1>.");
1467
1468   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1469    [InitEmpty, Always, TestOutputList (
1470       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1471        ["pvcreate"; "/dev/sda1"];
1472        ["pvcreate"; "/dev/sda2"];
1473        ["pvcreate"; "/dev/sda3"];
1474        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1475        ["vgcreate"; "VG2"; "/dev/sda3"];
1476        ["vgs"]], ["VG1"; "VG2"])],
1477    "create an LVM volume group",
1478    "\
1479 This creates an LVM volume group called C<volgroup>
1480 from the non-empty list of physical volumes C<physvols>.");
1481
1482   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1483    [InitEmpty, Always, TestOutputList (
1484       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1485        ["pvcreate"; "/dev/sda1"];
1486        ["pvcreate"; "/dev/sda2"];
1487        ["pvcreate"; "/dev/sda3"];
1488        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1489        ["vgcreate"; "VG2"; "/dev/sda3"];
1490        ["lvcreate"; "LV1"; "VG1"; "50"];
1491        ["lvcreate"; "LV2"; "VG1"; "50"];
1492        ["lvcreate"; "LV3"; "VG2"; "50"];
1493        ["lvcreate"; "LV4"; "VG2"; "50"];
1494        ["lvcreate"; "LV5"; "VG2"; "50"];
1495        ["lvs"]],
1496       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1497        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1498    "create an LVM logical volume",
1499    "\
1500 This creates an LVM logical volume called C<logvol>
1501 on the volume group C<volgroup>, with C<size> megabytes.");
1502
1503   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1504    [InitEmpty, Always, TestOutput (
1505       [["part_disk"; "/dev/sda"; "mbr"];
1506        ["mkfs"; "ext2"; "/dev/sda1"];
1507        ["mount_options"; ""; "/dev/sda1"; "/"];
1508        ["write"; "/new"; "new file contents"];
1509        ["cat"; "/new"]], "new file contents")],
1510    "make a filesystem",
1511    "\
1512 This creates a filesystem on C<device> (usually a partition
1513 or LVM logical volume).  The filesystem type is C<fstype>, for
1514 example C<ext3>.");
1515
1516   ("sfdisk", (RErr, [Device "device";
1517                      Int "cyls"; Int "heads"; Int "sectors";
1518                      StringList "lines"]), 43, [DangerWillRobinson],
1519    [],
1520    "create partitions on a block device",
1521    "\
1522 This is a direct interface to the L<sfdisk(8)> program for creating
1523 partitions on block devices.
1524
1525 C<device> should be a block device, for example C</dev/sda>.
1526
1527 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1528 and sectors on the device, which are passed directly to sfdisk as
1529 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1530 of these, then the corresponding parameter is omitted.  Usually for
1531 'large' disks, you can just pass C<0> for these, but for small
1532 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1533 out the right geometry and you will need to tell it.
1534
1535 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1536 information refer to the L<sfdisk(8)> manpage.
1537
1538 To create a single partition occupying the whole disk, you would
1539 pass C<lines> as a single element list, when the single element being
1540 the string C<,> (comma).
1541
1542 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1543 C<guestfs_part_init>");
1544
1545   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1546    (* Regression test for RHBZ#597135. *)
1547    [InitBasicFS, Always, TestLastFail
1548       [["write_file"; "/new"; "abc"; "10000"]]],
1549    "create a file",
1550    "\
1551 This call creates a file called C<path>.  The contents of the
1552 file is the string C<content> (which can contain any 8 bit data),
1553 with length C<size>.
1554
1555 As a special case, if C<size> is C<0>
1556 then the length is calculated using C<strlen> (so in this case
1557 the content cannot contain embedded ASCII NULs).
1558
1559 I<NB.> Owing to a bug, writing content containing ASCII NUL
1560 characters does I<not> work, even if the length is specified.");
1561
1562   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1563    [InitEmpty, Always, TestOutputListOfDevices (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["mounts"]], ["/dev/sda1"]);
1568     InitEmpty, Always, TestOutputList (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["umount"; "/"];
1573        ["mounts"]], [])],
1574    "unmount a filesystem",
1575    "\
1576 This unmounts the given filesystem.  The filesystem may be
1577 specified either by its mountpoint (path) or the device which
1578 contains the filesystem.");
1579
1580   ("mounts", (RStringList "devices", []), 46, [],
1581    [InitBasicFS, Always, TestOutputListOfDevices (
1582       [["mounts"]], ["/dev/sda1"])],
1583    "show mounted filesystems",
1584    "\
1585 This returns the list of currently mounted filesystems.  It returns
1586 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1587
1588 Some internal mounts are not shown.
1589
1590 See also: C<guestfs_mountpoints>");
1591
1592   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1593    [InitBasicFS, Always, TestOutputList (
1594       [["umount_all"];
1595        ["mounts"]], []);
1596     (* check that umount_all can unmount nested mounts correctly: *)
1597     InitEmpty, Always, TestOutputList (
1598       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1599        ["mkfs"; "ext2"; "/dev/sda1"];
1600        ["mkfs"; "ext2"; "/dev/sda2"];
1601        ["mkfs"; "ext2"; "/dev/sda3"];
1602        ["mount_options"; ""; "/dev/sda1"; "/"];
1603        ["mkdir"; "/mp1"];
1604        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1605        ["mkdir"; "/mp1/mp2"];
1606        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1607        ["mkdir"; "/mp1/mp2/mp3"];
1608        ["umount_all"];
1609        ["mounts"]], [])],
1610    "unmount all filesystems",
1611    "\
1612 This unmounts all mounted filesystems.
1613
1614 Some internal mounts are not unmounted by this call.");
1615
1616   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1617    [],
1618    "remove all LVM LVs, VGs and PVs",
1619    "\
1620 This command removes all LVM logical volumes, volume groups
1621 and physical volumes.");
1622
1623   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1624    [InitISOFS, Always, TestOutput (
1625       [["file"; "/empty"]], "empty");
1626     InitISOFS, Always, TestOutput (
1627       [["file"; "/known-1"]], "ASCII text");
1628     InitISOFS, Always, TestLastFail (
1629       [["file"; "/notexists"]])],
1630    "determine file type",
1631    "\
1632 This call uses the standard L<file(1)> command to determine
1633 the type or contents of the file.  This also works on devices,
1634 for example to find out whether a partition contains a filesystem.
1635
1636 This call will also transparently look inside various types
1637 of compressed file.
1638
1639 The exact command which runs is C<file -zbsL path>.  Note in
1640 particular that the filename is not prepended to the output
1641 (the C<-b> option).");
1642
1643   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1644    [InitBasicFS, Always, TestOutput (
1645       [["upload"; "test-command"; "/test-command"];
1646        ["chmod"; "0o755"; "/test-command"];
1647        ["command"; "/test-command 1"]], "Result1");
1648     InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 2"]], "Result2\n");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 3"]], "\nResult3");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 4"]], "\nResult4\n");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 5"]], "\nResult5\n\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 7"]], "");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 8"]], "\n");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 9"]], "\n\n");
1680     InitBasicFS, Always, TestOutput (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1684     InitBasicFS, Always, TestOutput (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1688     InitBasicFS, Always, TestLastFail (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command"; "/test-command"]])],
1692    "run a command from the guest filesystem",
1693    "\
1694 This call runs a command from the guest filesystem.  The
1695 filesystem must be mounted, and must contain a compatible
1696 operating system (ie. something Linux, with the same
1697 or compatible processor architecture).
1698
1699 The single parameter is an argv-style list of arguments.
1700 The first element is the name of the program to run.
1701 Subsequent elements are parameters.  The list must be
1702 non-empty (ie. must contain a program name).  Note that
1703 the command runs directly, and is I<not> invoked via
1704 the shell (see C<guestfs_sh>).
1705
1706 The return value is anything printed to I<stdout> by
1707 the command.
1708
1709 If the command returns a non-zero exit status, then
1710 this function returns an error message.  The error message
1711 string is the content of I<stderr> from the command.
1712
1713 The C<$PATH> environment variable will contain at least
1714 C</usr/bin> and C</bin>.  If you require a program from
1715 another location, you should provide the full path in the
1716 first parameter.
1717
1718 Shared libraries and data files required by the program
1719 must be available on filesystems which are mounted in the
1720 correct places.  It is the caller's responsibility to ensure
1721 all filesystems that are needed are mounted at the right
1722 locations.");
1723
1724   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1725    [InitBasicFS, Always, TestOutputList (
1726       [["upload"; "test-command"; "/test-command"];
1727        ["chmod"; "0o755"; "/test-command"];
1728        ["command_lines"; "/test-command 1"]], ["Result1"]);
1729     InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 2"]], ["Result2"]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 7"]], []);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 8"]], [""]);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 9"]], ["";""]);
1761     InitBasicFS, Always, TestOutputList (
1762       [["upload"; "test-command"; "/test-command"];
1763        ["chmod"; "0o755"; "/test-command"];
1764        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1765     InitBasicFS, Always, TestOutputList (
1766       [["upload"; "test-command"; "/test-command"];
1767        ["chmod"; "0o755"; "/test-command"];
1768        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1769    "run a command, returning lines",
1770    "\
1771 This is the same as C<guestfs_command>, but splits the
1772 result into a list of lines.
1773
1774 See also: C<guestfs_sh_lines>");
1775
1776   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1777    [InitISOFS, Always, TestOutputStruct (
1778       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1779    "get file information",
1780    "\
1781 Returns file information for the given C<path>.
1782
1783 This is the same as the C<stat(2)> system call.");
1784
1785   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1786    [InitISOFS, Always, TestOutputStruct (
1787       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1788    "get file information for a symbolic link",
1789    "\
1790 Returns file information for the given C<path>.
1791
1792 This is the same as C<guestfs_stat> except that if C<path>
1793 is a symbolic link, then the link is stat-ed, not the file it
1794 refers to.
1795
1796 This is the same as the C<lstat(2)> system call.");
1797
1798   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1799    [InitISOFS, Always, TestOutputStruct (
1800       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1801    "get file system statistics",
1802    "\
1803 Returns file system statistics for any mounted file system.
1804 C<path> should be a file or directory in the mounted file system
1805 (typically it is the mount point itself, but it doesn't need to be).
1806
1807 This is the same as the C<statvfs(2)> system call.");
1808
1809   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1810    [], (* XXX test *)
1811    "get ext2/ext3/ext4 superblock details",
1812    "\
1813 This returns the contents of the ext2, ext3 or ext4 filesystem
1814 superblock on C<device>.
1815
1816 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1817 manpage for more details.  The list of fields returned isn't
1818 clearly defined, and depends on both the version of C<tune2fs>
1819 that libguestfs was built against, and the filesystem itself.");
1820
1821   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1822    [InitEmpty, Always, TestOutputTrue (
1823       [["blockdev_setro"; "/dev/sda"];
1824        ["blockdev_getro"; "/dev/sda"]])],
1825    "set block device to read-only",
1826    "\
1827 Sets the block device named C<device> to read-only.
1828
1829 This uses the L<blockdev(8)> command.");
1830
1831   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1832    [InitEmpty, Always, TestOutputFalse (
1833       [["blockdev_setrw"; "/dev/sda"];
1834        ["blockdev_getro"; "/dev/sda"]])],
1835    "set block device to read-write",
1836    "\
1837 Sets the block device named C<device> to read-write.
1838
1839 This uses the L<blockdev(8)> command.");
1840
1841   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1842    [InitEmpty, Always, TestOutputTrue (
1843       [["blockdev_setro"; "/dev/sda"];
1844        ["blockdev_getro"; "/dev/sda"]])],
1845    "is block device set to read-only",
1846    "\
1847 Returns a boolean indicating if the block device is read-only
1848 (true if read-only, false if not).
1849
1850 This uses the L<blockdev(8)> command.");
1851
1852   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1853    [InitEmpty, Always, TestOutputInt (
1854       [["blockdev_getss"; "/dev/sda"]], 512)],
1855    "get sectorsize of block device",
1856    "\
1857 This returns the size of sectors on a block device.
1858 Usually 512, but can be larger for modern devices.
1859
1860 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1861 for that).
1862
1863 This uses the L<blockdev(8)> command.");
1864
1865   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1866    [InitEmpty, Always, TestOutputInt (
1867       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1868    "get blocksize of block device",
1869    "\
1870 This returns the block size of a device.
1871
1872 (Note this is different from both I<size in blocks> and
1873 I<filesystem block size>).
1874
1875 This uses the L<blockdev(8)> command.");
1876
1877   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1878    [], (* XXX test *)
1879    "set blocksize of block device",
1880    "\
1881 This sets the block size of a device.
1882
1883 (Note this is different from both I<size in blocks> and
1884 I<filesystem block size>).
1885
1886 This uses the L<blockdev(8)> command.");
1887
1888   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1889    [InitEmpty, Always, TestOutputInt (
1890       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1891    "get total size of device in 512-byte sectors",
1892    "\
1893 This returns the size of the device in units of 512-byte sectors
1894 (even if the sectorsize isn't 512 bytes ... weird).
1895
1896 See also C<guestfs_blockdev_getss> for the real sector size of
1897 the device, and C<guestfs_blockdev_getsize64> for the more
1898 useful I<size in bytes>.
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1905    "get total size of device in bytes",
1906    "\
1907 This returns the size of the device in bytes.
1908
1909 See also C<guestfs_blockdev_getsz>.
1910
1911 This uses the L<blockdev(8)> command.");
1912
1913   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1914    [InitEmpty, Always, TestRun
1915       [["blockdev_flushbufs"; "/dev/sda"]]],
1916    "flush device buffers",
1917    "\
1918 This tells the kernel to flush internal buffers associated
1919 with C<device>.
1920
1921 This uses the L<blockdev(8)> command.");
1922
1923   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1924    [InitEmpty, Always, TestRun
1925       [["blockdev_rereadpt"; "/dev/sda"]]],
1926    "reread partition table",
1927    "\
1928 Reread the partition table on C<device>.
1929
1930 This uses the L<blockdev(8)> command.");
1931
1932   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1933    [InitBasicFS, Always, TestOutput (
1934       (* Pick a file from cwd which isn't likely to change. *)
1935       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1936        ["checksum"; "md5"; "/COPYING.LIB"]],
1937       Digest.to_hex (Digest.file "COPYING.LIB"))],
1938    "upload a file from the local machine",
1939    "\
1940 Upload local file C<filename> to C<remotefilename> on the
1941 filesystem.
1942
1943 C<filename> can also be a named pipe.
1944
1945 See also C<guestfs_download>.");
1946
1947   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1948    [InitBasicFS, Always, TestOutput (
1949       (* Pick a file from cwd which isn't likely to change. *)
1950       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1951        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1952        ["upload"; "testdownload.tmp"; "/upload"];
1953        ["checksum"; "md5"; "/upload"]],
1954       Digest.to_hex (Digest.file "COPYING.LIB"))],
1955    "download a file to the local machine",
1956    "\
1957 Download file C<remotefilename> and save it as C<filename>
1958 on the local machine.
1959
1960 C<filename> can also be a named pipe.
1961
1962 See also C<guestfs_upload>, C<guestfs_cat>.");
1963
1964   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1965    [InitISOFS, Always, TestOutput (
1966       [["checksum"; "crc"; "/known-3"]], "2891671662");
1967     InitISOFS, Always, TestLastFail (
1968       [["checksum"; "crc"; "/notexists"]]);
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1979     InitISOFS, Always, TestOutput (
1980       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1981     (* Test for RHBZ#579608, absolute symbolic links. *)
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1984    "compute MD5, SHAx or CRC checksum of file",
1985    "\
1986 This call computes the MD5, SHAx or CRC checksum of the
1987 file named C<path>.
1988
1989 The type of checksum to compute is given by the C<csumtype>
1990 parameter which must have one of the following values:
1991
1992 =over 4
1993
1994 =item C<crc>
1995
1996 Compute the cyclic redundancy check (CRC) specified by POSIX
1997 for the C<cksum> command.
1998
1999 =item C<md5>
2000
2001 Compute the MD5 hash (using the C<md5sum> program).
2002
2003 =item C<sha1>
2004
2005 Compute the SHA1 hash (using the C<sha1sum> program).
2006
2007 =item C<sha224>
2008
2009 Compute the SHA224 hash (using the C<sha224sum> program).
2010
2011 =item C<sha256>
2012
2013 Compute the SHA256 hash (using the C<sha256sum> program).
2014
2015 =item C<sha384>
2016
2017 Compute the SHA384 hash (using the C<sha384sum> program).
2018
2019 =item C<sha512>
2020
2021 Compute the SHA512 hash (using the C<sha512sum> program).
2022
2023 =back
2024
2025 The checksum is returned as a printable string.
2026
2027 To get the checksum for a device, use C<guestfs_checksum_device>.
2028
2029 To get the checksums for many files, use C<guestfs_checksums_out>.");
2030
2031   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2032    [InitBasicFS, Always, TestOutput (
2033       [["tar_in"; "../images/helloworld.tar"; "/"];
2034        ["cat"; "/hello"]], "hello\n")],
2035    "unpack tarfile to directory",
2036    "\
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2039
2040 To upload a compressed tarball, use C<guestfs_tgz_in>
2041 or C<guestfs_txz_in>.");
2042
2043   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2044    [],
2045    "pack directory into tarfile",
2046    "\
2047 This command packs the contents of C<directory> and downloads
2048 it to local file C<tarfile>.
2049
2050 To download a compressed tarball, use C<guestfs_tgz_out>
2051 or C<guestfs_txz_out>.");
2052
2053   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2054    [InitBasicFS, Always, TestOutput (
2055       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056        ["cat"; "/hello"]], "hello\n")],
2057    "unpack compressed tarball to directory",
2058    "\
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2061
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2063
2064   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2065    [],
2066    "pack directory into compressed tarball",
2067    "\
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2070
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2072
2073   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074    [InitBasicFS, Always, TestLastFail (
2075       [["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["touch"; "/new"]]);
2078     InitBasicFS, Always, TestOutput (
2079       [["write"; "/new"; "data"];
2080        ["umount"; "/"];
2081        ["mount_ro"; "/dev/sda1"; "/"];
2082        ["cat"; "/new"]], "data")],
2083    "mount a guest disk, read-only",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2087
2088   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2089    [],
2090    "mount a guest disk with mount options",
2091    "\
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.
2095
2096 If the C<options> parameter is an empty string, then
2097 no options are passed (all options default to whatever
2098 the filesystem uses).");
2099
2100   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2101    [],
2102    "mount a guest disk with mount options and vfstype",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set both the mount options and the vfstype
2106 as for the L<mount(8)> I<-o> and I<-t> flags.");
2107
2108   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2109    [],
2110    "debugging and internals",
2111    "\
2112 The C<guestfs_debug> command exposes some internals of
2113 C<guestfsd> (the guestfs daemon) that runs inside the
2114 qemu subprocess.
2115
2116 There is no comprehensive help for this command.  You have
2117 to look at the file C<daemon/debug.c> in the libguestfs source
2118 to find out what you can do.");
2119
2120   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2121    [InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG/LV1"];
2128        ["lvs"]], ["/dev/VG/LV2"]);
2129     InitEmpty, Always, TestOutputList (
2130       [["part_disk"; "/dev/sda"; "mbr"];
2131        ["pvcreate"; "/dev/sda1"];
2132        ["vgcreate"; "VG"; "/dev/sda1"];
2133        ["lvcreate"; "LV1"; "VG"; "50"];
2134        ["lvcreate"; "LV2"; "VG"; "50"];
2135        ["lvremove"; "/dev/VG"];
2136        ["lvs"]], []);
2137     InitEmpty, Always, TestOutputList (
2138       [["part_disk"; "/dev/sda"; "mbr"];
2139        ["pvcreate"; "/dev/sda1"];
2140        ["vgcreate"; "VG"; "/dev/sda1"];
2141        ["lvcreate"; "LV1"; "VG"; "50"];
2142        ["lvcreate"; "LV2"; "VG"; "50"];
2143        ["lvremove"; "/dev/VG"];
2144        ["vgs"]], ["VG"])],
2145    "remove an LVM logical volume",
2146    "\
2147 Remove an LVM logical volume C<device>, where C<device> is
2148 the path to the LV, such as C</dev/VG/LV>.
2149
2150 You can also remove all LVs in a volume group by specifying
2151 the VG name, C</dev/VG>.");
2152
2153   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2154    [InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["vgremove"; "VG"];
2161        ["lvs"]], []);
2162     InitEmpty, Always, TestOutputList (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["vgs"]], [])],
2170    "remove an LVM volume group",
2171    "\
2172 Remove an LVM volume group C<vgname>, (for example C<VG>).
2173
2174 This also forcibly removes all logical volumes in the volume
2175 group (if any).");
2176
2177   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
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        ["lvs"]], []);
2187     InitEmpty, Always, TestOutputListOfDevices (
2188       [["part_disk"; "/dev/sda"; "mbr"];
2189        ["pvcreate"; "/dev/sda1"];
2190        ["vgcreate"; "VG"; "/dev/sda1"];
2191        ["lvcreate"; "LV1"; "VG"; "50"];
2192        ["lvcreate"; "LV2"; "VG"; "50"];
2193        ["vgremove"; "VG"];
2194        ["pvremove"; "/dev/sda1"];
2195        ["vgs"]], []);
2196     InitEmpty, Always, TestOutputListOfDevices (
2197       [["part_disk"; "/dev/sda"; "mbr"];
2198        ["pvcreate"; "/dev/sda1"];
2199        ["vgcreate"; "VG"; "/dev/sda1"];
2200        ["lvcreate"; "LV1"; "VG"; "50"];
2201        ["lvcreate"; "LV2"; "VG"; "50"];
2202        ["vgremove"; "VG"];
2203        ["pvremove"; "/dev/sda1"];
2204        ["pvs"]], [])],
2205    "remove an LVM physical volume",
2206    "\
2207 This wipes a physical volume C<device> so that LVM will no longer
2208 recognise it.
2209
2210 The implementation uses the C<pvremove> command which refuses to
2211 wipe physical volumes that contain any volume groups, so you have
2212 to remove those first.");
2213
2214   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["set_e2label"; "/dev/sda1"; "testlabel"];
2217        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2218    "set the ext2/3/4 filesystem label",
2219    "\
2220 This sets the ext2/3/4 filesystem label of the filesystem on
2221 C<device> to C<label>.  Filesystem labels are limited to
2222 16 characters.
2223
2224 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2225 to return the existing label on a filesystem.");
2226
2227   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2228    [],
2229    "get the ext2/3/4 filesystem label",
2230    "\
2231 This returns the ext2/3/4 filesystem label of the filesystem on
2232 C<device>.");
2233
2234   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2235    (let uuid = uuidgen () in
2236     [InitBasicFS, Always, TestOutput (
2237        [["set_e2uuid"; "/dev/sda1"; uuid];
2238         ["get_e2uuid"; "/dev/sda1"]], uuid);
2239      InitBasicFS, Always, TestOutput (
2240        [["set_e2uuid"; "/dev/sda1"; "clear"];
2241         ["get_e2uuid"; "/dev/sda1"]], "");
2242      (* We can't predict what UUIDs will be, so just check the commands run. *)
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2245      InitBasicFS, Always, TestRun (
2246        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2247    "set the ext2/3/4 filesystem UUID",
2248    "\
2249 This sets the ext2/3/4 filesystem UUID of the filesystem on
2250 C<device> to C<uuid>.  The format of the UUID and alternatives
2251 such as C<clear>, C<random> and C<time> are described in the
2252 L<tune2fs(8)> manpage.
2253
2254 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2255 to return the existing UUID of a filesystem.");
2256
2257   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2258    (* Regression test for RHBZ#597112. *)
2259    (let uuid = uuidgen () in
2260     [InitBasicFS, Always, TestOutput (
2261        [["mke2journal"; "1024"; "/dev/sdb"];
2262         ["set_e2uuid"; "/dev/sdb"; uuid];
2263         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2264    "get the ext2/3/4 filesystem UUID",
2265    "\
2266 This returns the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device>.");
2268
2269   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2270    [InitBasicFS, Always, TestOutputInt (
2271       [["umount"; "/dev/sda1"];
2272        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2273     InitBasicFS, Always, TestOutputInt (
2274       [["umount"; "/dev/sda1"];
2275        ["zero"; "/dev/sda1"];
2276        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2277    "run the filesystem checker",
2278    "\
2279 This runs the filesystem checker (fsck) on C<device> which
2280 should have filesystem type C<fstype>.
2281
2282 The returned integer is the status.  See L<fsck(8)> for the
2283 list of status codes from C<fsck>.
2284
2285 Notes:
2286
2287 =over 4
2288
2289 =item *
2290
2291 Multiple status codes can be summed together.
2292
2293 =item *
2294
2295 A non-zero return code can mean \"success\", for example if
2296 errors have been corrected on the filesystem.
2297
2298 =item *
2299
2300 Checking or repairing NTFS volumes is not supported
2301 (by linux-ntfs).
2302
2303 =back
2304
2305 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2306
2307   ("zero", (RErr, [Device "device"]), 85, [],
2308    [InitBasicFS, Always, TestOutput (
2309       [["umount"; "/dev/sda1"];
2310        ["zero"; "/dev/sda1"];
2311        ["file"; "/dev/sda1"]], "data")],
2312    "write zeroes to the device",
2313    "\
2314 This command writes zeroes over the first few blocks of C<device>.
2315
2316 How many blocks are zeroed isn't specified (but it's I<not> enough
2317 to securely wipe the device).  It should be sufficient to remove
2318 any partition tables, filesystem superblocks and so on.
2319
2320 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2321
2322   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2323    (* See:
2324     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2325     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2326     *)
2327    [InitBasicFS, Always, TestOutputTrue (
2328       [["mkdir_p"; "/boot/grub"];
2329        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2330        ["grub_install"; "/"; "/dev/vda"];
2331        ["is_dir"; "/boot"]])],
2332    "install GRUB",
2333    "\
2334 This command installs GRUB (the Grand Unified Bootloader) on
2335 C<device>, with the root directory being C<root>.
2336
2337 Note: If grub-install reports the error
2338 \"No suitable drive was found in the generated device map.\"
2339 it may be that you need to create a C</boot/grub/device.map>
2340 file first that contains the mapping between grub device names
2341 and Linux device names.  It is usually sufficient to create
2342 a file containing:
2343
2344  (hd0) /dev/vda
2345
2346 replacing C</dev/vda> with the name of the installation device.");
2347
2348   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2349    [InitBasicFS, Always, TestOutput (
2350       [["write"; "/old"; "file content"];
2351        ["cp"; "/old"; "/new"];
2352        ["cat"; "/new"]], "file content");
2353     InitBasicFS, Always, TestOutputTrue (
2354       [["write"; "/old"; "file content"];
2355        ["cp"; "/old"; "/new"];
2356        ["is_file"; "/old"]]);
2357     InitBasicFS, Always, TestOutput (
2358       [["write"; "/old"; "file content"];
2359        ["mkdir"; "/dir"];
2360        ["cp"; "/old"; "/dir/new"];
2361        ["cat"; "/dir/new"]], "file content")],
2362    "copy a file",
2363    "\
2364 This copies a file from C<src> to C<dest> where C<dest> is
2365 either a destination filename or destination directory.");
2366
2367   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2368    [InitBasicFS, Always, TestOutput (
2369       [["mkdir"; "/olddir"];
2370        ["mkdir"; "/newdir"];
2371        ["write"; "/olddir/file"; "file content"];
2372        ["cp_a"; "/olddir"; "/newdir"];
2373        ["cat"; "/newdir/olddir/file"]], "file content")],
2374    "copy a file or directory recursively",
2375    "\
2376 This copies a file or directory from C<src> to C<dest>
2377 recursively using the C<cp -a> command.");
2378
2379   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2380    [InitBasicFS, Always, TestOutput (
2381       [["write"; "/old"; "file content"];
2382        ["mv"; "/old"; "/new"];
2383        ["cat"; "/new"]], "file content");
2384     InitBasicFS, Always, TestOutputFalse (
2385       [["write"; "/old"; "file content"];
2386        ["mv"; "/old"; "/new"];
2387        ["is_file"; "/old"]])],
2388    "move a file",
2389    "\
2390 This moves a file from C<src> to C<dest> where C<dest> is
2391 either a destination filename or destination directory.");
2392
2393   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2394    [InitEmpty, Always, TestRun (
2395       [["drop_caches"; "3"]])],
2396    "drop kernel page cache, dentries and inodes",
2397    "\
2398 This instructs the guest kernel to drop its page cache,
2399 and/or dentries and inode caches.  The parameter C<whattodrop>
2400 tells the kernel what precisely to drop, see
2401 L<http://linux-mm.org/Drop_Caches>
2402
2403 Setting C<whattodrop> to 3 should drop everything.
2404
2405 This automatically calls L<sync(2)> before the operation,
2406 so that the maximum guest memory is freed.");
2407
2408   ("dmesg", (RString "kmsgs", []), 91, [],
2409    [InitEmpty, Always, TestRun (
2410       [["dmesg"]])],
2411    "return kernel messages",
2412    "\
2413 This returns the kernel messages (C<dmesg> output) from
2414 the guest kernel.  This is sometimes useful for extended
2415 debugging of problems.
2416
2417 Another way to get the same information is to enable
2418 verbose messages with C<guestfs_set_verbose> or by setting
2419 the environment variable C<LIBGUESTFS_DEBUG=1> before
2420 running the program.");
2421
2422   ("ping_daemon", (RErr, []), 92, [],
2423    [InitEmpty, Always, TestRun (
2424       [["ping_daemon"]])],
2425    "ping the guest daemon",
2426    "\
2427 This is a test probe into the guestfs daemon running inside
2428 the qemu subprocess.  Calling this function checks that the
2429 daemon responds to the ping message, without affecting the daemon
2430 or attached block device(s) in any other way.");
2431
2432   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2433    [InitBasicFS, Always, TestOutputTrue (
2434       [["write"; "/file1"; "contents of a file"];
2435        ["cp"; "/file1"; "/file2"];
2436        ["equal"; "/file1"; "/file2"]]);
2437     InitBasicFS, Always, TestOutputFalse (
2438       [["write"; "/file1"; "contents of a file"];
2439        ["write"; "/file2"; "contents of another file"];
2440        ["equal"; "/file1"; "/file2"]]);
2441     InitBasicFS, Always, TestLastFail (
2442       [["equal"; "/file1"; "/file2"]])],
2443    "test if two files have equal contents",
2444    "\
2445 This compares the two files C<file1> and C<file2> and returns
2446 true if their content is exactly equal, or false otherwise.
2447
2448 The external L<cmp(1)> program is used for the comparison.");
2449
2450   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2451    [InitISOFS, Always, TestOutputList (
2452       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2453     InitISOFS, Always, TestOutputList (
2454       [["strings"; "/empty"]], []);
2455     (* Test for RHBZ#579608, absolute symbolic links. *)
2456     InitISOFS, Always, TestRun (
2457       [["strings"; "/abssymlink"]])],
2458    "print the printable strings in a file",
2459    "\
2460 This runs the L<strings(1)> command on a file and returns
2461 the list of printable strings found.");
2462
2463   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2464    [InitISOFS, Always, TestOutputList (
2465       [["strings_e"; "b"; "/known-5"]], []);
2466     InitBasicFS, Always, TestOutputList (
2467       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2468        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2469    "print the printable strings in a file",
2470    "\
2471 This is like the C<guestfs_strings> command, but allows you to
2472 specify the encoding of strings that are looked for in
2473 the source file C<path>.
2474
2475 Allowed encodings are:
2476
2477 =over 4
2478
2479 =item s
2480
2481 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2482 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2483
2484 =item S
2485
2486 Single 8-bit-byte characters.
2487
2488 =item b
2489
2490 16-bit big endian strings such as those encoded in
2491 UTF-16BE or UCS-2BE.
2492
2493 =item l (lower case letter L)
2494
2495 16-bit little endian such as UTF-16LE and UCS-2LE.
2496 This is useful for examining binaries in Windows guests.
2497
2498 =item B
2499
2500 32-bit big endian such as UCS-4BE.
2501
2502 =item L
2503
2504 32-bit little endian such as UCS-4LE.
2505
2506 =back
2507
2508 The returned strings are transcoded to UTF-8.");
2509
2510   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2511    [InitISOFS, Always, TestOutput (
2512       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2513     (* Test for RHBZ#501888c2 regression which caused large hexdump
2514      * commands to segfault.
2515      *)
2516     InitISOFS, Always, TestRun (
2517       [["hexdump"; "/100krandom"]]);
2518     (* Test for RHBZ#579608, absolute symbolic links. *)
2519     InitISOFS, Always, TestRun (
2520       [["hexdump"; "/abssymlink"]])],
2521    "dump a file in hexadecimal",
2522    "\
2523 This runs C<hexdump -C> on the given C<path>.  The result is
2524 the human-readable, canonical hex dump of the file.");
2525
2526   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2527    [InitNone, Always, TestOutput (
2528       [["part_disk"; "/dev/sda"; "mbr"];
2529        ["mkfs"; "ext3"; "/dev/sda1"];
2530        ["mount_options"; ""; "/dev/sda1"; "/"];
2531        ["write"; "/new"; "test file"];
2532        ["umount"; "/dev/sda1"];
2533        ["zerofree"; "/dev/sda1"];
2534        ["mount_options"; ""; "/dev/sda1"; "/"];
2535        ["cat"; "/new"]], "test file")],
2536    "zero unused inodes and disk blocks on ext2/3 filesystem",
2537    "\
2538 This runs the I<zerofree> program on C<device>.  This program
2539 claims to zero unused inodes and disk blocks on an ext2/3
2540 filesystem, thus making it possible to compress the filesystem
2541 more effectively.
2542
2543 You should B<not> run this program if the filesystem is
2544 mounted.
2545
2546 It is possible that using this program can damage the filesystem
2547 or data on the filesystem.");
2548
2549   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2550    [],
2551    "resize an LVM physical volume",
2552    "\
2553 This resizes (expands or shrinks) an existing LVM physical
2554 volume to match the new size of the underlying device.");
2555
2556   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2557                        Int "cyls"; Int "heads"; Int "sectors";
2558                        String "line"]), 99, [DangerWillRobinson],
2559    [],
2560    "modify a single partition on a block device",
2561    "\
2562 This runs L<sfdisk(8)> option to modify just the single
2563 partition C<n> (note: C<n> counts from 1).
2564
2565 For other parameters, see C<guestfs_sfdisk>.  You should usually
2566 pass C<0> for the cyls/heads/sectors parameters.
2567
2568 See also: C<guestfs_part_add>");
2569
2570   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2571    [],
2572    "display the partition table",
2573    "\
2574 This displays the partition table on C<device>, in the
2575 human-readable output of the L<sfdisk(8)> command.  It is
2576 not intended to be parsed.
2577
2578 See also: C<guestfs_part_list>");
2579
2580   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2581    [],
2582    "display the kernel geometry",
2583    "\
2584 This displays the kernel's idea of the geometry of C<device>.
2585
2586 The result is in human-readable format, and not designed to
2587 be parsed.");
2588
2589   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2590    [],
2591    "display the disk geometry from the partition table",
2592    "\
2593 This displays the disk geometry of C<device> read from the
2594 partition table.  Especially in the case where the underlying
2595 block device has been resized, this can be different from the
2596 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2597
2598 The result is in human-readable format, and not designed to
2599 be parsed.");
2600
2601   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2602    [],
2603    "activate or deactivate all volume groups",
2604    "\
2605 This command activates or (if C<activate> is false) deactivates
2606 all logical volumes in all volume groups.
2607 If activated, then they are made known to the
2608 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2609 then those devices disappear.
2610
2611 This command is the same as running C<vgchange -a y|n>");
2612
2613   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2614    [],
2615    "activate or deactivate some volume groups",
2616    "\
2617 This command activates or (if C<activate> is false) deactivates
2618 all logical volumes in the listed volume groups C<volgroups>.
2619 If activated, then they are made known to the
2620 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2621 then those devices disappear.
2622
2623 This command is the same as running C<vgchange -a y|n volgroups...>
2624
2625 Note that if C<volgroups> is an empty list then B<all> volume groups
2626 are activated or deactivated.");
2627
2628   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2629    [InitNone, Always, TestOutput (
2630       [["part_disk"; "/dev/sda"; "mbr"];
2631        ["pvcreate"; "/dev/sda1"];
2632        ["vgcreate"; "VG"; "/dev/sda1"];
2633        ["lvcreate"; "LV"; "VG"; "10"];
2634        ["mkfs"; "ext2"; "/dev/VG/LV"];
2635        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2636        ["write"; "/new"; "test content"];
2637        ["umount"; "/"];
2638        ["lvresize"; "/dev/VG/LV"; "20"];
2639        ["e2fsck_f"; "/dev/VG/LV"];
2640        ["resize2fs"; "/dev/VG/LV"];
2641        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2642        ["cat"; "/new"]], "test content");
2643     InitNone, Always, TestRun (
2644       (* Make an LV smaller to test RHBZ#587484. *)
2645       [["part_disk"; "/dev/sda"; "mbr"];
2646        ["pvcreate"; "/dev/sda1"];
2647        ["vgcreate"; "VG"; "/dev/sda1"];
2648        ["lvcreate"; "LV"; "VG"; "20"];
2649        ["lvresize"; "/dev/VG/LV"; "10"]])],
2650    "resize an LVM logical volume",
2651    "\
2652 This resizes (expands or shrinks) an existing LVM logical
2653 volume to C<mbytes>.  When reducing, data in the reduced part
2654 is lost.");
2655
2656   ("resize2fs", (RErr, [Device "device"]), 106, [],
2657    [], (* lvresize tests this *)
2658    "resize an ext2, ext3 or ext4 filesystem",
2659    "\
2660 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2661 the underlying device.
2662
2663 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2664 on the C<device> before calling this command.  For unknown reasons
2665 C<resize2fs> sometimes gives an error about this and sometimes not.
2666 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2667 calling this function.");
2668
2669   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2670    [InitBasicFS, Always, TestOutputList (
2671       [["find"; "/"]], ["lost+found"]);
2672     InitBasicFS, Always, TestOutputList (
2673       [["touch"; "/a"];
2674        ["mkdir"; "/b"];
2675        ["touch"; "/b/c"];
2676        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2677     InitBasicFS, Always, TestOutputList (
2678       [["mkdir_p"; "/a/b/c"];
2679        ["touch"; "/a/b/c/d"];
2680        ["find"; "/a/b/"]], ["c"; "c/d"])],
2681    "find all files and directories",
2682    "\
2683 This command lists out all files and directories, recursively,
2684 starting at C<directory>.  It is essentially equivalent to
2685 running the shell command C<find directory -print> but some
2686 post-processing happens on the output, described below.
2687
2688 This returns a list of strings I<without any prefix>.  Thus
2689 if the directory structure was:
2690
2691  /tmp/a
2692  /tmp/b
2693  /tmp/c/d
2694
2695 then the returned list from C<guestfs_find> C</tmp> would be
2696 4 elements:
2697
2698  a
2699  b
2700  c
2701  c/d
2702
2703 If C<directory> is not a directory, then this command returns
2704 an error.
2705
2706 The returned list is sorted.
2707
2708 See also C<guestfs_find0>.");
2709
2710   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2711    [], (* lvresize tests this *)
2712    "check an ext2/ext3 filesystem",
2713    "\
2714 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2715 filesystem checker on C<device>, noninteractively (C<-p>),
2716 even if the filesystem appears to be clean (C<-f>).
2717
2718 This command is only needed because of C<guestfs_resize2fs>
2719 (q.v.).  Normally you should use C<guestfs_fsck>.");
2720
2721   ("sleep", (RErr, [Int "secs"]), 109, [],
2722    [InitNone, Always, TestRun (
2723       [["sleep"; "1"]])],
2724    "sleep for some seconds",
2725    "\
2726 Sleep for C<secs> seconds.");
2727
2728   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2729    [InitNone, Always, TestOutputInt (
2730       [["part_disk"; "/dev/sda"; "mbr"];
2731        ["mkfs"; "ntfs"; "/dev/sda1"];
2732        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2733     InitNone, Always, TestOutputInt (
2734       [["part_disk"; "/dev/sda"; "mbr"];
2735        ["mkfs"; "ext2"; "/dev/sda1"];
2736        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2737    "probe NTFS volume",
2738    "\
2739 This command runs the L<ntfs-3g.probe(8)> command which probes
2740 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2741 be mounted read-write, and some cannot be mounted at all).
2742
2743 C<rw> is a boolean flag.  Set it to true if you want to test
2744 if the volume can be mounted read-write.  Set it to false if
2745 you want to test if the volume can be mounted read-only.
2746
2747 The return value is an integer which C<0> if the operation
2748 would succeed, or some non-zero value documented in the
2749 L<ntfs-3g.probe(8)> manual page.");
2750
2751   ("sh", (RString "output", [String "command"]), 111, [],
2752    [], (* XXX needs tests *)
2753    "run a command via the shell",
2754    "\
2755 This call runs a command from the guest filesystem via the
2756 guest's C</bin/sh>.
2757
2758 This is like C<guestfs_command>, but passes the command to:
2759
2760  /bin/sh -c \"command\"
2761
2762 Depending on the guest's shell, this usually results in
2763 wildcards being expanded, shell expressions being interpolated
2764 and so on.
2765
2766 All the provisos about C<guestfs_command> apply to this call.");
2767
2768   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2769    [], (* XXX needs tests *)
2770    "run a command via the shell returning lines",
2771    "\
2772 This is the same as C<guestfs_sh>, but splits the result
2773 into a list of lines.
2774
2775 See also: C<guestfs_command_lines>");
2776
2777   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2778    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2779     * code in stubs.c, since all valid glob patterns must start with "/".
2780     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2781     *)
2782    [InitBasicFS, Always, TestOutputList (
2783       [["mkdir_p"; "/a/b/c"];
2784        ["touch"; "/a/b/c/d"];
2785        ["touch"; "/a/b/c/e"];
2786        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2787     InitBasicFS, Always, TestOutputList (
2788       [["mkdir_p"; "/a/b/c"];
2789        ["touch"; "/a/b/c/d"];
2790        ["touch"; "/a/b/c/e"];
2791        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2792     InitBasicFS, Always, TestOutputList (
2793       [["mkdir_p"; "/a/b/c"];
2794        ["touch"; "/a/b/c/d"];
2795        ["touch"; "/a/b/c/e"];
2796        ["glob_expand"; "/a/*/x/*"]], [])],
2797    "expand a wildcard path",
2798    "\
2799 This command searches for all the pathnames matching
2800 C<pattern> according to the wildcard expansion rules
2801 used by the shell.
2802
2803 If no paths match, then this returns an empty list
2804 (note: not an error).
2805
2806 It is just a wrapper around the C L<glob(3)> function
2807 with flags C<GLOB_MARK|GLOB_BRACE>.
2808 See that manual page for more details.");
2809
2810   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2811    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2812       [["scrub_device"; "/dev/sdc"]])],
2813    "scrub (securely wipe) a device",
2814    "\
2815 This command writes patterns over C<device> to make data retrieval
2816 more difficult.
2817
2818 It is an interface to the L<scrub(1)> program.  See that
2819 manual page for more details.");
2820
2821   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2822    [InitBasicFS, Always, TestRun (
2823       [["write"; "/file"; "content"];
2824        ["scrub_file"; "/file"]])],
2825    "scrub (securely wipe) a file",
2826    "\
2827 This command writes patterns over a file to make data retrieval
2828 more difficult.
2829
2830 The file is I<removed> after scrubbing.
2831
2832 It is an interface to the L<scrub(1)> program.  See that
2833 manual page for more details.");
2834
2835   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2836    [], (* XXX needs testing *)
2837    "scrub (securely wipe) free space",
2838    "\
2839 This command creates the directory C<dir> and then fills it
2840 with files until the filesystem is full, and scrubs the files
2841 as for C<guestfs_scrub_file>, and deletes them.
2842 The intention is to scrub any free space on the partition
2843 containing C<dir>.
2844
2845 It is an interface to the L<scrub(1)> program.  See that
2846 manual page for more details.");
2847
2848   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2849    [InitBasicFS, Always, TestRun (
2850       [["mkdir"; "/tmp"];
2851        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2852    "create a temporary directory",
2853    "\
2854 This command creates a temporary directory.  The
2855 C<template> parameter should be a full pathname for the
2856 temporary directory name with the final six characters being
2857 \"XXXXXX\".
2858
2859 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2860 the second one being suitable for Windows filesystems.
2861
2862 The name of the temporary directory that was created
2863 is returned.
2864
2865 The temporary directory is created with mode 0700
2866 and is owned by root.
2867
2868 The caller is responsible for deleting the temporary
2869 directory and its contents after use.
2870
2871 See also: L<mkdtemp(3)>");
2872
2873   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2874    [InitISOFS, Always, TestOutputInt (
2875       [["wc_l"; "/10klines"]], 10000);
2876     (* Test for RHBZ#579608, absolute symbolic links. *)
2877     InitISOFS, Always, TestOutputInt (
2878       [["wc_l"; "/abssymlink"]], 10000)],
2879    "count lines in a file",
2880    "\
2881 This command counts the lines in a file, using the
2882 C<wc -l> external command.");
2883
2884   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2885    [InitISOFS, Always, TestOutputInt (
2886       [["wc_w"; "/10klines"]], 10000)],
2887    "count words in a file",
2888    "\
2889 This command counts the words in a file, using the
2890 C<wc -w> external command.");
2891
2892   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2893    [InitISOFS, Always, TestOutputInt (
2894       [["wc_c"; "/100kallspaces"]], 102400)],
2895    "count characters in a file",
2896    "\
2897 This command counts the characters in a file, using the
2898 C<wc -c> external command.");
2899
2900   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2901    [InitISOFS, Always, TestOutputList (
2902       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2903     (* Test for RHBZ#579608, absolute symbolic links. *)
2904     InitISOFS, Always, TestOutputList (
2905       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2906    "return first 10 lines of a file",
2907    "\
2908 This command returns up to the first 10 lines of a file as
2909 a list of strings.");
2910
2911   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2912    [InitISOFS, Always, TestOutputList (
2913       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2914     InitISOFS, Always, TestOutputList (
2915       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["head_n"; "0"; "/10klines"]], [])],
2918    "return first N lines of a file",
2919    "\
2920 If the parameter C<nrlines> is a positive number, this returns the first
2921 C<nrlines> lines of the file C<path>.
2922
2923 If the parameter C<nrlines> is a negative number, this returns lines
2924 from the file C<path>, excluding the last C<nrlines> lines.
2925
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2927
2928   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2929    [InitISOFS, Always, TestOutputList (
2930       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2931    "return last 10 lines of a file",
2932    "\
2933 This command returns up to the last 10 lines of a file as
2934 a list of strings.");
2935
2936   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2937    [InitISOFS, Always, TestOutputList (
2938       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2939     InitISOFS, Always, TestOutputList (
2940       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2941     InitISOFS, Always, TestOutputList (
2942       [["tail_n"; "0"; "/10klines"]], [])],
2943    "return last N lines of a file",
2944    "\
2945 If the parameter C<nrlines> is a positive number, this returns the last
2946 C<nrlines> lines of the file C<path>.
2947
2948 If the parameter C<nrlines> is a negative number, this returns lines
2949 from the file C<path>, starting with the C<-nrlines>th line.
2950
2951 If the parameter C<nrlines> is zero, this returns an empty list.");
2952
2953   ("df", (RString "output", []), 125, [],
2954    [], (* XXX Tricky to test because it depends on the exact format
2955         * of the 'df' command and other imponderables.
2956         *)
2957    "report file system disk space usage",
2958    "\
2959 This command runs the C<df> command to report disk space used.
2960
2961 This command is mostly useful for interactive sessions.  It
2962 is I<not> intended that you try to parse the output string.
2963 Use C<statvfs> from programs.");
2964
2965   ("df_h", (RString "output", []), 126, [],
2966    [], (* XXX Tricky to test because it depends on the exact format
2967         * of the 'df' command and other imponderables.
2968         *)
2969    "report file system disk space usage (human readable)",
2970    "\
2971 This command runs the C<df -h> command to report disk space used
2972 in human-readable format.
2973
2974 This command is mostly useful for interactive sessions.  It
2975 is I<not> intended that you try to parse the output string.
2976 Use C<statvfs> from programs.");
2977
2978   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2979    [InitISOFS, Always, TestOutputInt (
2980       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2981    "estimate file space usage",
2982    "\
2983 This command runs the C<du -s> command to estimate file space
2984 usage for C<path>.
2985
2986 C<path> can be a file or a directory.  If C<path> is a directory
2987 then the estimate includes the contents of the directory and all
2988 subdirectories (recursively).
2989
2990 The result is the estimated size in I<kilobytes>
2991 (ie. units of 1024 bytes).");
2992
2993   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2994    [InitISOFS, Always, TestOutputList (
2995       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2996    "list files in an initrd",
2997    "\
2998 This command lists out files contained in an initrd.
2999
3000 The files are listed without any initial C</> character.  The
3001 files are listed in the order they appear (not necessarily
3002 alphabetical).  Directory names are listed as separate items.
3003
3004 Old Linux kernels (2.4 and earlier) used a compressed ext2
3005 filesystem as initrd.  We I<only> support the newer initramfs
3006 format (compressed cpio files).");
3007
3008   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3009    [],
3010    "mount a file using the loop device",
3011    "\
3012 This command lets you mount C<file> (a filesystem image
3013 in a file) on a mount point.  It is entirely equivalent to
3014 the command C<mount -o loop file mountpoint>.");
3015
3016   ("mkswap", (RErr, [Device "device"]), 130, [],
3017    [InitEmpty, Always, TestRun (
3018       [["part_disk"; "/dev/sda"; "mbr"];
3019        ["mkswap"; "/dev/sda1"]])],
3020    "create a swap partition",
3021    "\
3022 Create a swap partition on C<device>.");
3023
3024   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3025    [InitEmpty, Always, TestRun (
3026       [["part_disk"; "/dev/sda"; "mbr"];
3027        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3028    "create a swap partition with a label",
3029    "\
3030 Create a swap partition on C<device> with label C<label>.
3031
3032 Note that you cannot attach a swap label to a block device
3033 (eg. C</dev/sda>), just to a partition.  This appears to be
3034 a limitation of the kernel or swap tools.");
3035
3036   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3037    (let uuid = uuidgen () in
3038     [InitEmpty, Always, TestRun (
3039        [["part_disk"; "/dev/sda"; "mbr"];
3040         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3041    "create a swap partition with an explicit UUID",
3042    "\
3043 Create a swap partition on C<device> with UUID C<uuid>.");
3044
3045   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3046    [InitBasicFS, Always, TestOutputStruct (
3047       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3048        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3049        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3050     InitBasicFS, Always, TestOutputStruct (
3051       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3052        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3053    "make block, character or FIFO devices",
3054    "\
3055 This call creates block or character special devices, or
3056 named pipes (FIFOs).
3057
3058 The C<mode> parameter should be the mode, using the standard
3059 constants.  C<devmajor> and C<devminor> are the
3060 device major and minor numbers, only used when creating block
3061 and character special devices.
3062
3063 Note that, just like L<mknod(2)>, the mode must be bitwise
3064 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3065 just creates a regular file).  These constants are
3066 available in the standard Linux header files, or you can use
3067 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3068 which are wrappers around this command which bitwise OR
3069 in the appropriate constant for you.
3070
3071 The mode actually set is affected by the umask.");
3072
3073   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3074    [InitBasicFS, Always, TestOutputStruct (
3075       [["mkfifo"; "0o777"; "/node"];
3076        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3077    "make FIFO (named pipe)",
3078    "\
3079 This call creates a FIFO (named pipe) called C<path> with
3080 mode C<mode>.  It is just a convenient wrapper around
3081 C<guestfs_mknod>.
3082
3083 The mode actually set is affected by the umask.");
3084
3085   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3086    [InitBasicFS, Always, TestOutputStruct (
3087       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3088        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3089    "make block device node",
3090    "\
3091 This call creates a block device node called C<path> with
3092 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3093 It is just a convenient wrapper around C<guestfs_mknod>.
3094
3095 The mode actually set is affected by the umask.");
3096
3097   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3098    [InitBasicFS, Always, TestOutputStruct (
3099       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3100        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3101    "make char device node",
3102    "\
3103 This call creates a char device node called C<path> with
3104 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3105 It is just a convenient wrapper around C<guestfs_mknod>.
3106
3107 The mode actually set is affected by the umask.");
3108
3109   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3110    [InitEmpty, Always, TestOutputInt (
3111       [["umask"; "0o22"]], 0o22)],
3112    "set file mode creation mask (umask)",
3113    "\
3114 This function sets the mask used for creating new files and
3115 device nodes to C<mask & 0777>.
3116
3117 Typical umask values would be C<022> which creates new files
3118 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3119 C<002> which creates new files with permissions like
3120 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3121
3122 The default umask is C<022>.  This is important because it
3123 means that directories and device nodes will be created with
3124 C<0644> or C<0755> mode even if you specify C<0777>.
3125
3126 See also C<guestfs_get_umask>,
3127 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3128
3129 This call returns the previous umask.");
3130
3131   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3132    [],
3133    "read directories entries",
3134    "\
3135 This returns the list of directory entries in directory C<dir>.
3136
3137 All entries in the directory are returned, including C<.> and
3138 C<..>.  The entries are I<not> sorted, but returned in the same
3139 order as the underlying filesystem.
3140
3141 Also this call returns basic file type information about each
3142 file.  The C<ftyp> field will contain one of the following characters:
3143
3144 =over 4
3145
3146 =item 'b'
3147
3148 Block special
3149
3150 =item 'c'
3151
3152 Char special
3153
3154 =item 'd'
3155
3156 Directory
3157
3158 =item 'f'
3159
3160 FIFO (named pipe)
3161
3162 =item 'l'
3163
3164 Symbolic link
3165
3166 =item 'r'
3167
3168 Regular file
3169
3170 =item 's'
3171
3172 Socket
3173
3174 =item 'u'
3175
3176 Unknown file type
3177
3178 =item '?'
3179
3180 The L<readdir(3)> call returned a C<d_type> field with an
3181 unexpected value
3182
3183 =back
3184
3185 This function is primarily intended for use by programs.  To
3186 get a simple list of names, use C<guestfs_ls>.  To get a printable
3187 directory for human consumption, use C<guestfs_ll>.");
3188
3189   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3190    [],
3191    "create partitions on a block device",
3192    "\
3193 This is a simplified interface to the C<guestfs_sfdisk>
3194 command, where partition sizes are specified in megabytes
3195 only (rounded to the nearest cylinder) and you don't need
3196 to specify the cyls, heads and sectors parameters which
3197 were rarely if ever used anyway.
3198
3199 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3200 and C<guestfs_part_disk>");
3201
3202   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3203    [],
3204    "determine file type inside a compressed file",
3205    "\
3206 This command runs C<file> after first decompressing C<path>
3207 using C<method>.
3208
3209 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3210
3211 Since 1.0.63, use C<guestfs_file> instead which can now
3212 process compressed files.");
3213
3214   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3215    [],
3216    "list extended attributes of a file or directory",
3217    "\
3218 This call lists the extended attributes of the file or directory
3219 C<path>.
3220
3221 At the system call level, this is a combination of the
3222 L<listxattr(2)> and L<getxattr(2)> calls.
3223
3224 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3225
3226   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3227    [],
3228    "list extended attributes of a file or directory",
3229    "\
3230 This is the same as C<guestfs_getxattrs>, but if C<path>
3231 is a symbolic link, then it returns the extended attributes
3232 of the link itself.");
3233
3234   ("setxattr", (RErr, [String "xattr";
3235                        String "val"; Int "vallen"; (* will be BufferIn *)
3236                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3237    [],
3238    "set extended attribute of a file or directory",
3239    "\
3240 This call sets the extended attribute named C<xattr>
3241 of the file C<path> to the value C<val> (of length C<vallen>).
3242 The value is arbitrary 8 bit data.
3243
3244 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3245
3246   ("lsetxattr", (RErr, [String "xattr";
3247                         String "val"; Int "vallen"; (* will be BufferIn *)
3248                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3249    [],
3250    "set extended attribute of a file or directory",
3251    "\
3252 This is the same as C<guestfs_setxattr>, but if C<path>
3253 is a symbolic link, then it sets an extended attribute
3254 of the link itself.");
3255
3256   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3257    [],
3258    "remove extended attribute of a file or directory",
3259    "\
3260 This call removes the extended attribute named C<xattr>
3261 of the file C<path>.
3262
3263 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3264
3265   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3266    [],
3267    "remove extended attribute of a file or directory",
3268    "\
3269 This is the same as C<guestfs_removexattr>, but if C<path>
3270 is a symbolic link, then it removes an extended attribute
3271 of the link itself.");
3272
3273   ("mountpoints", (RHashtable "mps", []), 147, [],
3274    [],
3275    "show mountpoints",
3276    "\
3277 This call is similar to C<guestfs_mounts>.  That call returns
3278 a list of devices.  This one returns a hash table (map) of
3279 device name to directory where the device is mounted.");
3280
3281   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3282    (* This is a special case: while you would expect a parameter
3283     * of type "Pathname", that doesn't work, because it implies
3284     * NEED_ROOT in the generated calling code in stubs.c, and
3285     * this function cannot use NEED_ROOT.
3286     *)
3287    [],
3288    "create a mountpoint",
3289    "\
3290 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3291 specialized calls that can be used to create extra mountpoints
3292 before mounting the first filesystem.
3293
3294 These calls are I<only> necessary in some very limited circumstances,
3295 mainly the case where you want to mount a mix of unrelated and/or
3296 read-only filesystems together.
3297
3298 For example, live CDs often contain a \"Russian doll\" nest of
3299 filesystems, an ISO outer layer, with a squashfs image inside, with
3300 an ext2/3 image inside that.  You can unpack this as follows
3301 in guestfish:
3302
3303  add-ro Fedora-11-i686-Live.iso
3304  run
3305  mkmountpoint /cd
3306  mkmountpoint /squash
3307  mkmountpoint /ext3
3308  mount /dev/sda /cd
3309  mount-loop /cd/LiveOS/squashfs.img /squash
3310  mount-loop /squash/LiveOS/ext3fs.img /ext3
3311
3312 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3313
3314   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3315    [],
3316    "remove a mountpoint",
3317    "\
3318 This calls removes a mountpoint that was previously created
3319 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3320 for full details.");
3321
3322   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputBuffer (
3324       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3325     (* Test various near large, large and too large files (RHBZ#589039). *)
3326     InitBasicFS, Always, TestLastFail (
3327       [["touch"; "/a"];
3328        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3329        ["read_file"; "/a"]]);
3330     InitBasicFS, Always, TestLastFail (
3331       [["touch"; "/a"];
3332        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3333        ["read_file"; "/a"]]);
3334     InitBasicFS, Always, TestLastFail (
3335       [["touch"; "/a"];
3336        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3337        ["read_file"; "/a"]])],
3338    "read a file",
3339    "\
3340 This calls returns the contents of the file C<path> as a
3341 buffer.
3342
3343 Unlike C<guestfs_cat>, this function can correctly
3344 handle files that contain embedded ASCII NUL characters.
3345 However unlike C<guestfs_download>, this function is limited
3346 in the total size of file that can be handled.");
3347
3348   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3351     InitISOFS, Always, TestOutputList (
3352       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3353     (* Test for RHBZ#579608, absolute symbolic links. *)
3354     InitISOFS, Always, TestOutputList (
3355       [["grep"; "nomatch"; "/abssymlink"]], [])],
3356    "return lines matching a pattern",
3357    "\
3358 This calls the external C<grep> program and returns the
3359 matching lines.");
3360
3361   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3362    [InitISOFS, Always, TestOutputList (
3363       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3364    "return lines matching a pattern",
3365    "\
3366 This calls the external C<egrep> program and returns the
3367 matching lines.");
3368
3369   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3370    [InitISOFS, Always, TestOutputList (
3371       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3372    "return lines matching a pattern",
3373    "\
3374 This calls the external C<fgrep> program and returns the
3375 matching lines.");
3376
3377   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3378    [InitISOFS, Always, TestOutputList (
3379       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3380    "return lines matching a pattern",
3381    "\
3382 This calls the external C<grep -i> program and returns the
3383 matching lines.");
3384
3385   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3386    [InitISOFS, Always, TestOutputList (
3387       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3388    "return lines matching a pattern",
3389    "\
3390 This calls the external C<egrep -i> program and returns the
3391 matching lines.");
3392
3393   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3394    [InitISOFS, Always, TestOutputList (
3395       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3396    "return lines matching a pattern",
3397    "\
3398 This calls the external C<fgrep -i> program and returns the
3399 matching lines.");
3400
3401   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3402    [InitISOFS, Always, TestOutputList (
3403       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3404    "return lines matching a pattern",
3405    "\
3406 This calls the external C<zgrep> program and returns the
3407 matching lines.");
3408
3409   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3410    [InitISOFS, Always, TestOutputList (
3411       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3412    "return lines matching a pattern",
3413    "\
3414 This calls the external C<zegrep> program and returns the
3415 matching lines.");
3416
3417   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3418    [InitISOFS, Always, TestOutputList (
3419       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3420    "return lines matching a pattern",
3421    "\
3422 This calls the external C<zfgrep> program and returns the
3423 matching lines.");
3424
3425   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3426    [InitISOFS, Always, TestOutputList (
3427       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3428    "return lines matching a pattern",
3429    "\
3430 This calls the external C<zgrep -i> program and returns the
3431 matching lines.");
3432
3433   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3434    [InitISOFS, Always, TestOutputList (
3435       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3436    "return lines matching a pattern",
3437    "\
3438 This calls the external C<zegrep -i> program and returns the
3439 matching lines.");
3440
3441   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3442    [InitISOFS, Always, TestOutputList (
3443       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3444    "return lines matching a pattern",
3445    "\
3446 This calls the external C<zfgrep -i> program and returns the
3447 matching lines.");
3448
3449   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3450    [InitISOFS, Always, TestOutput (
3451       [["realpath"; "/../directory"]], "/directory")],
3452    "canonicalized absolute pathname",
3453    "\
3454 Return the canonicalized absolute pathname of C<path>.  The
3455 returned path has no C<.>, C<..> or symbolic link path elements.");
3456
3457   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3458    [InitBasicFS, Always, TestOutputStruct (
3459       [["touch"; "/a"];
3460        ["ln"; "/a"; "/b"];
3461        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3462    "create a hard link",
3463    "\
3464 This command creates a hard link using the C<ln> command.");
3465
3466   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3467    [InitBasicFS, Always, TestOutputStruct (
3468       [["touch"; "/a"];
3469        ["touch"; "/b"];
3470        ["ln_f"; "/a"; "/b"];
3471        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3472    "create a hard link",
3473    "\
3474 This command creates a hard link using the C<ln -f> command.
3475 The C<-f> option removes the link (C<linkname>) if it exists already.");
3476
3477   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3478    [InitBasicFS, Always, TestOutputStruct (
3479       [["touch"; "/a"];
3480        ["ln_s"; "a"; "/b"];
3481        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3482    "create a symbolic link",
3483    "\
3484 This command creates a symbolic link using the C<ln -s> command.");
3485
3486   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3487    [InitBasicFS, Always, TestOutput (
3488       [["mkdir_p"; "/a/b"];
3489        ["touch"; "/a/b/c"];
3490        ["ln_sf"; "../d"; "/a/b/c"];
3491        ["readlink"; "/a/b/c"]], "../d")],
3492    "create a symbolic link",
3493    "\
3494 This command creates a symbolic link using the C<ln -sf> command,
3495 The C<-f> option removes the link (C<linkname>) if it exists already.");
3496
3497   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3498    [] (* XXX tested above *),
3499    "read the target of a symbolic link",
3500    "\
3501 This command reads the target of a symbolic link.");
3502
3503   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3504    [InitBasicFS, Always, TestOutputStruct (
3505       [["fallocate"; "/a"; "1000000"];
3506        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3507    "preallocate a file in the guest filesystem",
3508    "\
3509 This command preallocates a file (containing zero bytes) named
3510 C<path> of size C<len> bytes.  If the file exists already, it
3511 is overwritten.
3512
3513 Do not confuse this with the guestfish-specific
3514 C<alloc> command which allocates a file in the host and
3515 attaches it as a device.");
3516
3517   ("swapon_device", (RErr, [Device "device"]), 170, [],
3518    [InitPartition, Always, TestRun (
3519       [["mkswap"; "/dev/sda1"];
3520        ["swapon_device"; "/dev/sda1"];
3521        ["swapoff_device"; "/dev/sda1"]])],
3522    "enable swap on device",
3523    "\
3524 This command enables the libguestfs appliance to use the
3525 swap device or partition named C<device>.  The increased
3526 memory is made available for all commands, for example
3527 those run using C<guestfs_command> or C<guestfs_sh>.
3528
3529 Note that you should not swap to existing guest swap
3530 partitions unless you know what you are doing.  They may
3531 contain hibernation information, or other information that
3532 the guest doesn't want you to trash.  You also risk leaking
3533 information about the host to the guest this way.  Instead,
3534 attach a new host device to the guest and swap on that.");
3535
3536   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3537    [], (* XXX tested by swapon_device *)
3538    "disable swap on device",
3539    "\
3540 This command disables the libguestfs appliance swap
3541 device or partition named C<device>.
3542 See C<guestfs_swapon_device>.");
3543
3544   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3545    [InitBasicFS, Always, TestRun (
3546       [["fallocate"; "/swap"; "8388608"];
3547        ["mkswap_file"; "/swap"];
3548        ["swapon_file"; "/swap"];
3549        ["swapoff_file"; "/swap"]])],
3550    "enable swap on file",
3551    "\
3552 This command enables swap to a file.
3553 See C<guestfs_swapon_device> for other notes.");
3554
3555   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3556    [], (* XXX tested by swapon_file *)
3557    "disable swap on file",
3558    "\
3559 This command disables the libguestfs appliance swap on file.");
3560
3561   ("swapon_label", (RErr, [String "label"]), 174, [],
3562    [InitEmpty, Always, TestRun (
3563       [["part_disk"; "/dev/sdb"; "mbr"];
3564        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3565        ["swapon_label"; "swapit"];
3566        ["swapoff_label"; "swapit"];
3567        ["zero"; "/dev/sdb"];
3568        ["blockdev_rereadpt"; "/dev/sdb"]])],
3569    "enable swap on labeled swap partition",
3570    "\
3571 This command enables swap to a labeled swap partition.
3572 See C<guestfs_swapon_device> for other notes.");
3573
3574   ("swapoff_label", (RErr, [String "label"]), 175, [],
3575    [], (* XXX tested by swapon_label *)
3576    "disable swap on labeled swap partition",
3577    "\
3578 This command disables the libguestfs appliance swap on
3579 labeled swap partition.");
3580
3581   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3582    (let uuid = uuidgen () in
3583     [InitEmpty, Always, TestRun (
3584        [["mkswap_U"; uuid; "/dev/sdb"];
3585         ["swapon_uuid"; uuid];
3586         ["swapoff_uuid"; uuid]])]),
3587    "enable swap on swap partition by UUID",
3588    "\
3589 This command enables swap to a swap partition with the given UUID.
3590 See C<guestfs_swapon_device> for other notes.");
3591
3592   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3593    [], (* XXX tested by swapon_uuid *)
3594    "disable swap on swap partition by UUID",
3595    "\
3596 This command disables the libguestfs appliance swap partition
3597 with the given UUID.");
3598
3599   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3600    [InitBasicFS, Always, TestRun (
3601       [["fallocate"; "/swap"; "8388608"];
3602        ["mkswap_file"; "/swap"]])],
3603    "create a swap file",
3604    "\
3605 Create a swap file.
3606
3607 This command just writes a swap file signature to an existing
3608 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3609
3610   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3611    [InitISOFS, Always, TestRun (
3612       [["inotify_init"; "0"]])],
3613    "create an inotify handle",
3614    "\
3615 This command creates a new inotify handle.
3616 The inotify subsystem can be used to notify events which happen to
3617 objects in the guest filesystem.
3618
3619 C<maxevents> is the maximum number of events which will be
3620 queued up between calls to C<guestfs_inotify_read> or
3621 C<guestfs_inotify_files>.
3622 If this is passed as C<0>, then the kernel (or previously set)
3623 default is used.  For Linux 2.6.29 the default was 16384 events.
3624 Beyond this limit, the kernel throws away events, but records
3625 the fact that it threw them away by setting a flag
3626 C<IN_Q_OVERFLOW> in the returned structure list (see
3627 C<guestfs_inotify_read>).
3628
3629 Before any events are generated, you have to add some
3630 watches to the internal watch list.  See:
3631 C<guestfs_inotify_add_watch>,
3632 C<guestfs_inotify_rm_watch> and
3633 C<guestfs_inotify_watch_all>.
3634
3635 Queued up events should be read periodically by calling
3636 C<guestfs_inotify_read>
3637 (or C<guestfs_inotify_files> which is just a helpful
3638 wrapper around C<guestfs_inotify_read>).  If you don't
3639 read the events out often enough then you risk the internal
3640 queue overflowing.
3641
3642 The handle should be closed after use by calling
3643 C<guestfs_inotify_close>.  This also removes any
3644 watches automatically.
3645
3646 See also L<inotify(7)> for an overview of the inotify interface
3647 as exposed by the Linux kernel, which is roughly what we expose
3648 via libguestfs.  Note that there is one global inotify handle
3649 per libguestfs instance.");
3650
3651   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3652    [InitBasicFS, Always, TestOutputList (
3653       [["inotify_init"; "0"];
3654        ["inotify_add_watch"; "/"; "1073741823"];
3655        ["touch"; "/a"];
3656        ["touch"; "/b"];
3657        ["inotify_files"]], ["a"; "b"])],
3658    "add an inotify watch",
3659    "\
3660 Watch C<path> for the events listed in C<mask>.
3661
3662 Note that if C<path> is a directory then events within that
3663 directory are watched, but this does I<not> happen recursively
3664 (in subdirectories).
3665
3666 Note for non-C or non-Linux callers: the inotify events are
3667 defined by the Linux kernel ABI and are listed in
3668 C</usr/include/sys/inotify.h>.");
3669
3670   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3671    [],
3672    "remove an inotify watch",
3673    "\
3674 Remove a previously defined inotify watch.
3675 See C<guestfs_inotify_add_watch>.");
3676
3677   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3678    [],
3679    "return list of inotify events",
3680    "\
3681 Return the complete queue of events that have happened
3682 since the previous read call.
3683
3684 If no events have happened, this returns an empty list.
3685
3686 I<Note>: In order to make sure that all events have been
3687 read, you must call this function repeatedly until it
3688 returns an empty list.  The reason is that the call will
3689 read events up to the maximum appliance-to-host message
3690 size and leave remaining events in the queue.");
3691
3692   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3693    [],
3694    "return list of watched files that had events",
3695    "\
3696 This function is a helpful wrapper around C<guestfs_inotify_read>
3697 which just returns a list of pathnames of objects that were
3698 touched.  The returned pathnames are sorted and deduplicated.");
3699
3700   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3701    [],
3702    "close the inotify handle",
3703    "\
3704 This closes the inotify handle which was previously
3705 opened by inotify_init.  It removes all watches, throws
3706 away any pending events, and deallocates all resources.");
3707
3708   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3709    [],
3710    "set SELinux security context",
3711    "\
3712 This sets the SELinux security context of the daemon
3713 to the string C<context>.
3714
3715 See the documentation about SELINUX in L<guestfs(3)>.");
3716
3717   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3718    [],
3719    "get SELinux security context",
3720    "\
3721 This gets the SELinux security context of the daemon.
3722
3723 See the documentation about SELINUX in L<guestfs(3)>,
3724 and C<guestfs_setcon>");
3725
3726   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3727    [InitEmpty, Always, TestOutput (
3728       [["part_disk"; "/dev/sda"; "mbr"];
3729        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3730        ["mount_options"; ""; "/dev/sda1"; "/"];
3731        ["write"; "/new"; "new file contents"];
3732        ["cat"; "/new"]], "new file contents")],
3733    "make a filesystem with block size",
3734    "\
3735 This call is similar to C<guestfs_mkfs>, but it allows you to
3736 control the block size of the resulting filesystem.  Supported
3737 block sizes depend on the filesystem type, but typically they
3738 are C<1024>, C<2048> or C<4096> only.");
3739
3740   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3741    [InitEmpty, Always, TestOutput (
3742       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3743        ["mke2journal"; "4096"; "/dev/sda1"];
3744        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3745        ["mount_options"; ""; "/dev/sda2"; "/"];
3746        ["write"; "/new"; "new file contents"];
3747        ["cat"; "/new"]], "new file contents")],
3748    "make ext2/3/4 external journal",
3749    "\
3750 This creates an ext2 external journal on C<device>.  It is equivalent
3751 to the command:
3752
3753  mke2fs -O journal_dev -b blocksize device");
3754
3755   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3756    [InitEmpty, Always, TestOutput (
3757       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3758        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3759        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3760        ["mount_options"; ""; "/dev/sda2"; "/"];
3761        ["write"; "/new"; "new file contents"];
3762        ["cat"; "/new"]], "new file contents")],
3763    "make ext2/3/4 external journal with label",
3764    "\
3765 This creates an ext2 external journal on C<device> with label C<label>.");
3766
3767   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3768    (let uuid = uuidgen () in
3769     [InitEmpty, Always, TestOutput (
3770        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3771         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3772         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3773         ["mount_options"; ""; "/dev/sda2"; "/"];
3774         ["write"; "/new"; "new file contents"];
3775         ["cat"; "/new"]], "new file contents")]),
3776    "make ext2/3/4 external journal with UUID",
3777    "\
3778 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3779
3780   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3781    [],
3782    "make ext2/3/4 filesystem with external journal",
3783    "\
3784 This creates an ext2/3/4 filesystem on C<device> with
3785 an external journal on C<journal>.  It is equivalent
3786 to the command:
3787
3788  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3789
3790 See also C<guestfs_mke2journal>.");
3791
3792   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3793    [],
3794    "make ext2/3/4 filesystem with external journal",
3795    "\
3796 This creates an ext2/3/4 filesystem on C<device> with
3797 an external journal on the journal labeled C<label>.
3798
3799 See also C<guestfs_mke2journal_L>.");
3800
3801   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3802    [],
3803    "make ext2/3/4 filesystem with external journal",
3804    "\
3805 This creates an ext2/3/4 filesystem on C<device> with
3806 an external journal on the journal with UUID C<uuid>.
3807
3808 See also C<guestfs_mke2journal_U>.");
3809
3810   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3811    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3812    "load a kernel module",
3813    "\
3814 This loads a kernel module in the appliance.
3815
3816 The kernel module must have been whitelisted when libguestfs
3817 was built (see C<appliance/kmod.whitelist.in> in the source).");
3818
3819   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3820    [InitNone, Always, TestOutput (
3821       [["echo_daemon"; "This is a test"]], "This is a test"
3822     )],
3823    "echo arguments back to the client",
3824    "\
3825 This command concatenates the list of C<words> passed with single spaces
3826 between them and returns the resulting string.
3827
3828 You can use this command to test the connection through to the daemon.
3829
3830 See also C<guestfs_ping_daemon>.");
3831
3832   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3833    [], (* There is a regression test for this. *)
3834    "find all files and directories, returning NUL-separated list",
3835    "\
3836 This command lists out all files and directories, recursively,
3837 starting at C<directory>, placing the resulting list in the
3838 external file called C<files>.
3839
3840 This command works the same way as C<guestfs_find> with the
3841 following exceptions:
3842
3843 =over 4
3844
3845 =item *
3846
3847 The resulting list is written to an external file.
3848
3849 =item *
3850
3851 Items (filenames) in the result are separated
3852 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3853
3854 =item *
3855
3856 This command is not limited in the number of names that it
3857 can return.
3858
3859 =item *
3860
3861 The result list is not sorted.
3862
3863 =back");
3864
3865   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3866    [InitISOFS, Always, TestOutput (
3867       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3868     InitISOFS, Always, TestOutput (
3869       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3870     InitISOFS, Always, TestOutput (
3871       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3872     InitISOFS, Always, TestLastFail (
3873       [["case_sensitive_path"; "/Known-1/"]]);
3874     InitBasicFS, Always, TestOutput (
3875       [["mkdir"; "/a"];
3876        ["mkdir"; "/a/bbb"];
3877        ["touch"; "/a/bbb/c"];
3878        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3879     InitBasicFS, Always, TestOutput (
3880       [["mkdir"; "/a"];
3881        ["mkdir"; "/a/bbb"];
3882        ["touch"; "/a/bbb/c"];
3883        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3884     InitBasicFS, Always, TestLastFail (
3885       [["mkdir"; "/a"];
3886        ["mkdir"; "/a/bbb"];
3887        ["touch"; "/a/bbb/c"];
3888        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3889    "return true path on case-insensitive filesystem",
3890    "\
3891 This can be used to resolve case insensitive paths on
3892 a filesystem which is case sensitive.  The use case is
3893 to resolve paths which you have read from Windows configuration
3894 files or the Windows Registry, to the true path.
3895
3896 The command handles a peculiarity of the Linux ntfs-3g
3897 filesystem driver (and probably others), which is that although
3898 the underlying filesystem is case-insensitive, the driver
3899 exports the filesystem to Linux as case-sensitive.
3900
3901 One consequence of this is that special directories such
3902 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3903 (or other things) depending on the precise details of how
3904 they were created.  In Windows itself this would not be
3905 a problem.
3906
3907 Bug or feature?  You decide:
3908 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3909
3910 This function resolves the true case of each element in the
3911 path and returns the case-sensitive path.
3912
3913 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3914 might return C<\"/WINDOWS/system32\"> (the exact return value
3915 would depend on details of how the directories were originally
3916 created under Windows).
3917
3918 I<Note>:
3919 This function does not handle drive names, backslashes etc.
3920
3921 See also C<guestfs_realpath>.");
3922
3923   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3924    [InitBasicFS, Always, TestOutput (
3925       [["vfs_type"; "/dev/sda1"]], "ext2")],
3926    "get the Linux VFS type corresponding to a mounted device",
3927    "\
3928 This command gets the filesystem type corresponding to
3929 the filesystem on C<device>.
3930
3931 For most filesystems, the result is the name of the Linux
3932 VFS module which would be used to mount this filesystem
3933 if you mounted it without specifying the filesystem type.
3934 For example a string such as C<ext3> or C<ntfs>.");
3935
3936   ("truncate", (RErr, [Pathname "path"]), 199, [],
3937    [InitBasicFS, Always, TestOutputStruct (
3938       [["write"; "/test"; "some stuff so size is not zero"];
3939        ["truncate"; "/test"];
3940        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3941    "truncate a file to zero size",
3942    "\
3943 This command truncates C<path> to a zero-length file.  The
3944 file must exist already.");
3945
3946   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3947    [InitBasicFS, Always, TestOutputStruct (
3948       [["touch"; "/test"];
3949        ["truncate_size"; "/test"; "1000"];
3950        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3951    "truncate a file to a particular size",
3952    "\
3953 This command truncates C<path> to size C<size> bytes.  The file
3954 must exist already.
3955
3956 If the current file size is less than C<size> then
3957 the file is extended to the required size with zero bytes.
3958 This creates a sparse file (ie. disk blocks are not allocated
3959 for the file until you write to it).  To create a non-sparse
3960 file of zeroes, use C<guestfs_fallocate64> instead.");
3961
3962   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3963    [InitBasicFS, Always, TestOutputStruct (
3964       [["touch"; "/test"];
3965        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3966        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3967    "set timestamp of a file with nanosecond precision",
3968    "\
3969 This command sets the timestamps of a file with nanosecond
3970 precision.
3971
3972 C<atsecs, atnsecs> are the last access time (atime) in secs and
3973 nanoseconds from the epoch.
3974
3975 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3976 secs and nanoseconds from the epoch.
3977
3978 If the C<*nsecs> field contains the special value C<-1> then
3979 the corresponding timestamp is set to the current time.  (The
3980 C<*secs> field is ignored in this case).
3981
3982 If the C<*nsecs> field contains the special value C<-2> then
3983 the corresponding timestamp is left unchanged.  (The
3984 C<*secs> field is ignored in this case).");
3985
3986   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3987    [InitBasicFS, Always, TestOutputStruct (
3988       [["mkdir_mode"; "/test"; "0o111"];
3989        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3990    "create a directory with a particular mode",
3991    "\
3992 This command creates a directory, setting the initial permissions
3993 of the directory to C<mode>.
3994
3995 For common Linux filesystems, the actual mode which is set will
3996 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3997 interpret the mode in other ways.
3998
3999 See also C<guestfs_mkdir>, C<guestfs_umask>");
4000
4001   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4002    [], (* XXX *)
4003    "change file owner and group",
4004    "\
4005 Change the file owner to C<owner> and group to C<group>.
4006 This is like C<guestfs_chown> but if C<path> is a symlink then
4007 the link itself is changed, not the target.
4008
4009 Only numeric uid and gid are supported.  If you want to use
4010 names, you will need to locate and parse the password file
4011 yourself (Augeas support makes this relatively easy).");
4012
4013   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4014    [], (* XXX *)
4015    "lstat on multiple files",
4016    "\
4017 This call allows you to perform the C<guestfs_lstat> operation
4018 on multiple files, where all files are in the directory C<path>.
4019 C<names> is the list of files from this directory.
4020
4021 On return you get a list of stat structs, with a one-to-one
4022 correspondence to the C<names> list.  If any name did not exist
4023 or could not be lstat'd, then the C<ino> field of that structure
4024 is set to C<-1>.
4025
4026 This call is intended for programs that want to efficiently
4027 list a directory contents without making many round-trips.
4028 See also C<guestfs_lxattrlist> for a similarly efficient call
4029 for getting extended attributes.  Very long directory listings
4030 might cause the protocol message size to be exceeded, causing
4031 this call to fail.  The caller must split up such requests
4032 into smaller groups of names.");
4033
4034   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4035    [], (* XXX *)
4036    "lgetxattr on multiple files",
4037    "\
4038 This call allows you to get the extended attributes
4039 of multiple files, where all files are in the directory C<path>.
4040 C<names> is the list of files from this directory.
4041
4042 On return you get a flat list of xattr structs which must be
4043 interpreted sequentially.  The first xattr struct always has a zero-length
4044 C<attrname>.  C<attrval> in this struct is zero-length
4045 to indicate there was an error doing C<lgetxattr> for this
4046 file, I<or> is a C string which is a decimal number
4047 (the number of following attributes for this file, which could
4048 be C<\"0\">).  Then after the first xattr struct are the
4049 zero or more attributes for the first named file.
4050 This repeats for the second and subsequent files.
4051
4052 This call is intended for programs that want to efficiently
4053 list a directory contents without making many round-trips.
4054 See also C<guestfs_lstatlist> for a similarly efficient call
4055 for getting standard stats.  Very long directory listings
4056 might cause the protocol message size to be exceeded, causing
4057 this call to fail.  The caller must split up such requests
4058 into smaller groups of names.");
4059
4060   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4061    [], (* XXX *)
4062    "readlink on multiple files",
4063    "\
4064 This call allows you to do a C<readlink> operation
4065 on multiple files, where all files are in the directory C<path>.
4066 C<names> is the list of files from this directory.
4067
4068 On return you get a list of strings, with a one-to-one
4069 correspondence to the C<names> list.  Each string is the
4070 value of the symbolic link.
4071
4072 If the C<readlink(2)> operation fails on any name, then
4073 the corresponding result string is the empty string C<\"\">.
4074 However the whole operation is completed even if there
4075 were C<readlink(2)> errors, and so you can call this
4076 function with names where you don't know if they are
4077 symbolic links already (albeit slightly less efficient).
4078
4079 This call is intended for programs that want to efficiently
4080 list a directory contents without making many round-trips.
4081 Very long directory listings might cause the protocol
4082 message size to be exceeded, causing
4083 this call to fail.  The caller must split up such requests
4084 into smaller groups of names.");
4085
4086   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4087    [InitISOFS, Always, TestOutputBuffer (
4088       [["pread"; "/known-4"; "1"; "3"]], "\n");
4089     InitISOFS, Always, TestOutputBuffer (
4090       [["pread"; "/empty"; "0"; "100"]], "")],
4091    "read part of a file",
4092    "\
4093 This command lets you read part of a file.  It reads C<count>
4094 bytes of the file, starting at C<offset>, from file C<path>.
4095
4096 This may read fewer bytes than requested.  For further details
4097 see the L<pread(2)> system call.
4098
4099 See also C<guestfs_pwrite>.");
4100
4101   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4102    [InitEmpty, Always, TestRun (
4103       [["part_init"; "/dev/sda"; "gpt"]])],
4104    "create an empty partition table",
4105    "\
4106 This creates an empty partition table on C<device> of one of the
4107 partition types listed below.  Usually C<parttype> should be
4108 either C<msdos> or C<gpt> (for large disks).
4109
4110 Initially there are no partitions.  Following this, you should
4111 call C<guestfs_part_add> for each partition required.
4112
4113 Possible values for C<parttype> are:
4114
4115 =over 4
4116
4117 =item B<efi> | B<gpt>
4118
4119 Intel EFI / GPT partition table.
4120
4121 This is recommended for >= 2 TB partitions that will be accessed
4122 from Linux and Intel-based Mac OS X.  It also has limited backwards
4123 compatibility with the C<mbr> format.
4124
4125 =item B<mbr> | B<msdos>
4126
4127 The standard PC \"Master Boot Record\" (MBR) format used
4128 by MS-DOS and Windows.  This partition type will B<only> work
4129 for device sizes up to 2 TB.  For large disks we recommend
4130 using C<gpt>.
4131
4132 =back
4133
4134 Other partition table types that may work but are not
4135 supported include:
4136
4137 =over 4
4138
4139 =item B<aix>
4140
4141 AIX disk labels.
4142
4143 =item B<amiga> | B<rdb>
4144
4145 Amiga \"Rigid Disk Block\" format.
4146
4147 =item B<bsd>
4148
4149 BSD disk labels.
4150
4151 =item B<dasd>
4152
4153 DASD, used on IBM mainframes.
4154
4155 =item B<dvh>
4156
4157 MIPS/SGI volumes.
4158
4159 =item B<mac>
4160
4161 Old Mac partition format.  Modern Macs use C<gpt>.
4162
4163 =item B<pc98>
4164
4165 NEC PC-98 format, common in Japan apparently.
4166
4167 =item B<sun>
4168
4169 Sun disk labels.
4170
4171 =back");
4172
4173   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4174    [InitEmpty, Always, TestRun (
4175       [["part_init"; "/dev/sda"; "mbr"];
4176        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4177     InitEmpty, Always, TestRun (
4178       [["part_init"; "/dev/sda"; "gpt"];
4179        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4180        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4181     InitEmpty, Always, TestRun (
4182       [["part_init"; "/dev/sda"; "mbr"];
4183        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4184        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4185        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4186        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4187    "add a partition to the device",
4188    "\
4189 This command adds a partition to C<device>.  If there is no partition
4190 table on the device, call C<guestfs_part_init> first.
4191
4192 The C<prlogex> parameter is the type of partition.  Normally you
4193 should pass C<p> or C<primary> here, but MBR partition tables also
4194 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4195 types.
4196
4197 C<startsect> and C<endsect> are the start and end of the partition
4198 in I<sectors>.  C<endsect> may be negative, which means it counts
4199 backwards from the end of the disk (C<-1> is the last sector).
4200
4201 Creating a partition which covers the whole disk is not so easy.
4202 Use C<guestfs_part_disk> to do that.");
4203
4204   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4205    [InitEmpty, Always, TestRun (
4206       [["part_disk"; "/dev/sda"; "mbr"]]);
4207     InitEmpty, Always, TestRun (
4208       [["part_disk"; "/dev/sda"; "gpt"]])],
4209    "partition whole disk with a single primary partition",
4210    "\
4211 This command is simply a combination of C<guestfs_part_init>
4212 followed by C<guestfs_part_add> to create a single primary partition
4213 covering the whole disk.
4214
4215 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4216 but other possible values are described in C<guestfs_part_init>.");
4217
4218   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4219    [InitEmpty, Always, TestRun (
4220       [["part_disk"; "/dev/sda"; "mbr"];
4221        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4222    "make a partition bootable",
4223    "\
4224 This sets the bootable flag on partition numbered C<partnum> on
4225 device C<device>.  Note that partitions are numbered from 1.
4226
4227 The bootable flag is used by some operating systems (notably
4228 Windows) to determine which partition to boot from.  It is by
4229 no means universally recognized.");
4230
4231   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4232    [InitEmpty, Always, TestRun (
4233       [["part_disk"; "/dev/sda"; "gpt"];
4234        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4235    "set partition name",
4236    "\
4237 This sets the partition name on partition numbered C<partnum> on
4238 device C<device>.  Note that partitions are numbered from 1.
4239
4240 The partition name can only be set on certain types of partition
4241 table.  This works on C<gpt> but not on C<mbr> partitions.");
4242
4243   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4244    [], (* XXX Add a regression test for this. *)
4245    "list partitions on a device",
4246    "\
4247 This command parses the partition table on C<device> and
4248 returns the list of partitions found.
4249
4250 The fields in the returned structure are:
4251
4252 =over 4
4253
4254 =item B<part_num>
4255
4256 Partition number, counting from 1.
4257
4258 =item B<part_start>
4259
4260 Start of the partition I<in bytes>.  To get sectors you have to
4261 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4262
4263 =item B<part_end>
4264
4265 End of the partition in bytes.
4266
4267 =item B<part_size>
4268
4269 Size of the partition in bytes.
4270
4271 =back");
4272
4273   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4274    [InitEmpty, Always, TestOutput (
4275       [["part_disk"; "/dev/sda"; "gpt"];
4276        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4277    "get the partition table type",
4278    "\
4279 This command examines the partition table on C<device> and
4280 returns the partition table type (format) being used.
4281
4282 Common return values include: C<msdos> (a DOS/Windows style MBR
4283 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4284 values are possible, although unusual.  See C<guestfs_part_init>
4285 for a full list.");
4286
4287   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4288    [InitBasicFS, Always, TestOutputBuffer (
4289       [["fill"; "0x63"; "10"; "/test"];
4290        ["read_file"; "/test"]], "cccccccccc")],
4291    "fill a file with octets",
4292    "\
4293 This command creates a new file called C<path>.  The initial
4294 content of the file is C<len> octets of C<c>, where C<c>
4295 must be a number in the range C<[0..255]>.
4296
4297 To fill a file with zero bytes (sparsely), it is
4298 much more efficient to use C<guestfs_truncate_size>.
4299 To create a file with a pattern of repeating bytes
4300 use C<guestfs_fill_pattern>.");
4301
4302   ("available", (RErr, [StringList "groups"]), 216, [],
4303    [InitNone, Always, TestRun [["available"; ""]]],
4304    "test availability of some parts of the API",
4305    "\
4306 This command is used to check the availability of some
4307 groups of functionality in the appliance, which not all builds of
4308 the libguestfs appliance will be able to provide.
4309
4310 The libguestfs groups, and the functions that those
4311 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4312 You can also fetch this list at runtime by calling
4313 C<guestfs_available_all_groups>.
4314
4315 The argument C<groups> is a list of group names, eg:
4316 C<[\"inotify\", \"augeas\"]> would check for the availability of
4317 the Linux inotify functions and Augeas (configuration file
4318 editing) functions.
4319
4320 The command returns no error if I<all> requested groups are available.
4321
4322 It fails with an error if one or more of the requested
4323 groups is unavailable in the appliance.
4324
4325 If an unknown group name is included in the
4326 list of groups then an error is always returned.
4327
4328 I<Notes:>
4329
4330 =over 4
4331
4332 =item *
4333
4334 You must call C<guestfs_launch> before calling this function.
4335
4336 The reason is because we don't know what groups are
4337 supported by the appliance/daemon until it is running and can
4338 be queried.
4339
4340 =item *
4341
4342 If a group of functions is available, this does not necessarily
4343 mean that they will work.  You still have to check for errors
4344 when calling individual API functions even if they are
4345 available.
4346
4347 =item *
4348
4349 It is usually the job of distro packagers to build
4350 complete functionality into the libguestfs appliance.
4351 Upstream libguestfs, if built from source with all
4352 requirements satisfied, will support everything.
4353
4354 =item *
4355
4356 This call was added in version C<1.0.80>.  In previous
4357 versions of libguestfs all you could do would be to speculatively
4358 execute a command to find out if the daemon implemented it.
4359 See also C<guestfs_version>.
4360
4361 =back");
4362
4363   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4364    [InitBasicFS, Always, TestOutputBuffer (
4365       [["write"; "/src"; "hello, world"];
4366        ["dd"; "/src"; "/dest"];
4367        ["read_file"; "/dest"]], "hello, world")],
4368    "copy from source to destination using dd",
4369    "\
4370 This command copies from one source device or file C<src>
4371 to another destination device or file C<dest>.  Normally you
4372 would use this to copy to or from a device or partition, for
4373 example to duplicate a filesystem.
4374
4375 If the destination is a device, it must be as large or larger
4376 than the source file or device, otherwise the copy will fail.
4377 This command cannot do partial copies (see C<guestfs_copy_size>).");
4378
4379   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4380    [InitBasicFS, Always, TestOutputInt (
4381       [["write"; "/file"; "hello, world"];
4382        ["filesize"; "/file"]], 12)],
4383    "return the size of the file in bytes",
4384    "\
4385 This command returns the size of C<file> in bytes.
4386
4387 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4388 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4389 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4390
4391   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4392    [InitBasicFSonLVM, Always, TestOutputList (
4393       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4394        ["lvs"]], ["/dev/VG/LV2"])],
4395    "rename an LVM logical volume",
4396    "\
4397 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4398
4399   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4400    [InitBasicFSonLVM, Always, TestOutputList (
4401       [["umount"; "/"];
4402        ["vg_activate"; "false"; "VG"];
4403        ["vgrename"; "VG"; "VG2"];
4404        ["vg_activate"; "true"; "VG2"];
4405        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4406        ["vgs"]], ["VG2"])],
4407    "rename an LVM volume group",
4408    "\
4409 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4410
4411   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4412    [InitISOFS, Always, TestOutputBuffer (
4413       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4414    "list the contents of a single file in an initrd",
4415    "\
4416 This command unpacks the file C<filename> from the initrd file
4417 called C<initrdpath>.  The filename must be given I<without> the
4418 initial C</> character.
4419
4420 For example, in guestfish you could use the following command
4421 to examine the boot script (usually called C</init>)
4422 contained in a Linux initrd or initramfs image:
4423
4424  initrd-cat /boot/initrd-<version>.img init
4425
4426 See also C<guestfs_initrd_list>.");
4427
4428   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4429    [],
4430    "get the UUID of a physical volume",
4431    "\
4432 This command returns the UUID of the LVM PV C<device>.");
4433
4434   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4435    [],
4436    "get the UUID of a volume group",
4437    "\
4438 This command returns the UUID of the LVM VG named C<vgname>.");
4439
4440   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4441    [],
4442    "get the UUID of a logical volume",
4443    "\
4444 This command returns the UUID of the LVM LV C<device>.");
4445
4446   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4447    [],
4448    "get the PV UUIDs containing the volume group",
4449    "\
4450 Given a VG called C<vgname>, this returns the UUIDs of all
4451 the physical volumes that this volume group resides on.
4452
4453 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4454 calls to associate physical volumes and volume groups.
4455
4456 See also C<guestfs_vglvuuids>.");
4457
4458   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4459    [],
4460    "get the LV UUIDs of all LVs in the volume group",
4461    "\
4462 Given a VG called C<vgname>, this returns the UUIDs of all
4463 the logical volumes created in this volume group.
4464
4465 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4466 calls to associate logical volumes and volume groups.
4467
4468 See also C<guestfs_vgpvuuids>.");
4469
4470   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4471    [InitBasicFS, Always, TestOutputBuffer (
4472       [["write"; "/src"; "hello, world"];
4473        ["copy_size"; "/src"; "/dest"; "5"];
4474        ["read_file"; "/dest"]], "hello")],
4475    "copy size bytes from source to destination using dd",
4476    "\
4477 This command copies exactly C<size> bytes from one source device
4478 or file C<src> to another destination device or file C<dest>.
4479
4480 Note this will fail if the source is too short or if the destination
4481 is not large enough.");
4482
4483   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4484    [InitBasicFSonLVM, Always, TestRun (
4485       [["zero_device"; "/dev/VG/LV"]])],
4486    "write zeroes to an entire device",
4487    "\
4488 This command writes zeroes over the entire C<device>.  Compare
4489 with C<guestfs_zero> which just zeroes the first few blocks of
4490 a device.");
4491
4492   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4493    [InitBasicFS, Always, TestOutput (
4494       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4495        ["cat"; "/hello"]], "hello\n")],
4496    "unpack compressed tarball to directory",
4497    "\
4498 This command uploads and unpacks local file C<tarball> (an
4499 I<xz compressed> tar file) into C<directory>.");
4500
4501   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4502    [],
4503    "pack directory into compressed tarball",
4504    "\
4505 This command packs the contents of C<directory> and downloads
4506 it to local file C<tarball> (as an xz compressed tar archive).");
4507
4508   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4509    [],
4510    "resize an NTFS filesystem",
4511    "\
4512 This command resizes an NTFS filesystem, expanding or
4513 shrinking it to the size of the underlying device.
4514 See also L<ntfsresize(8)>.");
4515
4516   ("vgscan", (RErr, []), 232, [],
4517    [InitEmpty, Always, TestRun (
4518       [["vgscan"]])],
4519    "rescan for LVM physical volumes, volume groups and logical volumes",
4520    "\
4521 This rescans all block devices and rebuilds the list of LVM
4522 physical volumes, volume groups and logical volumes.");
4523
4524   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4525    [InitEmpty, Always, TestRun (
4526       [["part_init"; "/dev/sda"; "mbr"];
4527        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4528        ["part_del"; "/dev/sda"; "1"]])],
4529    "delete a partition",
4530    "\
4531 This command deletes the partition numbered C<partnum> on C<device>.
4532
4533 Note that in the case of MBR partitioning, deleting an
4534 extended partition also deletes any logical partitions
4535 it contains.");
4536
4537   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4538    [InitEmpty, Always, TestOutputTrue (
4539       [["part_init"; "/dev/sda"; "mbr"];
4540        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4541        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4542        ["part_get_bootable"; "/dev/sda"; "1"]])],
4543    "return true if a partition is bootable",
4544    "\
4545 This command returns true if the partition C<partnum> on
4546 C<device> has the bootable flag set.
4547
4548 See also C<guestfs_part_set_bootable>.");
4549
4550   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4551    [InitEmpty, Always, TestOutputInt (
4552       [["part_init"; "/dev/sda"; "mbr"];
4553        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4554        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4555        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4556    "get the MBR type byte (ID byte) from a partition",
4557    "\
4558 Returns the MBR type byte (also known as the ID byte) from
4559 the numbered partition C<partnum>.
4560
4561 Note that only MBR (old DOS-style) partitions have type bytes.
4562 You will get undefined results for other partition table
4563 types (see C<guestfs_part_get_parttype>).");
4564
4565   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4566    [], (* tested by part_get_mbr_id *)
4567    "set the MBR type byte (ID byte) of a partition",
4568    "\
4569 Sets the MBR type byte (also known as the ID byte) of
4570 the numbered partition C<partnum> to C<idbyte>.  Note
4571 that the type bytes quoted in most documentation are
4572 in fact hexadecimal numbers, but usually documented
4573 without any leading \"0x\" which might be confusing.
4574
4575 Note that only MBR (old DOS-style) partitions have type bytes.
4576 You will get undefined results for other partition table
4577 types (see C<guestfs_part_get_parttype>).");
4578
4579   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4580    [InitISOFS, Always, TestOutput (
4581       [["checksum_device"; "md5"; "/dev/sdd"]],
4582       (Digest.to_hex (Digest.file "images/test.iso")))],
4583    "compute MD5, SHAx or CRC checksum of the contents of a device",
4584    "\
4585 This call computes the MD5, SHAx or CRC checksum of the
4586 contents of the device named C<device>.  For the types of
4587 checksums supported see the C<guestfs_checksum> command.");
4588
4589   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4590    [InitNone, Always, TestRun (
4591       [["part_disk"; "/dev/sda"; "mbr"];
4592        ["pvcreate"; "/dev/sda1"];
4593        ["vgcreate"; "VG"; "/dev/sda1"];
4594        ["lvcreate"; "LV"; "VG"; "10"];
4595        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4596    "expand an LV to fill free space",
4597    "\
4598 This expands an existing logical volume C<lv> so that it fills
4599 C<pc>% of the remaining free space in the volume group.  Commonly
4600 you would call this with pc = 100 which expands the logical volume
4601 as much as possible, using all remaining free space in the volume
4602 group.");
4603
4604   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4605    [], (* XXX Augeas code needs tests. *)
4606    "clear Augeas path",
4607    "\
4608 Set the value associated with C<path> to C<NULL>.  This
4609 is the same as the L<augtool(1)> C<clear> command.");
4610
4611   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4612    [InitEmpty, Always, TestOutputInt (
4613       [["get_umask"]], 0o22)],
4614    "get the current umask",
4615    "\
4616 Return the current umask.  By default the umask is C<022>
4617 unless it has been set by calling C<guestfs_umask>.");
4618
4619   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4620    [],
4621    "upload a file to the appliance (internal use only)",
4622    "\
4623 The C<guestfs_debug_upload> command uploads a file to
4624 the libguestfs appliance.
4625
4626 There is no comprehensive help for this command.  You have
4627 to look at the file C<daemon/debug.c> in the libguestfs source
4628 to find out what it is for.");
4629
4630   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4631    [InitBasicFS, Always, TestOutput (
4632       [["base64_in"; "../images/hello.b64"; "/hello"];
4633        ["cat"; "/hello"]], "hello\n")],
4634    "upload base64-encoded data to file",
4635    "\
4636 This command uploads base64-encoded data from C<base64file>
4637 to C<filename>.");
4638
4639   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4640    [],
4641    "download file and encode as base64",
4642    "\
4643 This command downloads the contents of C<filename>, writing
4644 it out to local file C<base64file> encoded as base64.");
4645
4646   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4647    [],
4648    "compute MD5, SHAx or CRC checksum of files in a directory",
4649    "\
4650 This command computes the checksums of all regular files in
4651 C<directory> and then emits a list of those checksums to
4652 the local output file C<sumsfile>.
4653
4654 This can be used for verifying the integrity of a virtual
4655 machine.  However to be properly secure you should pay
4656 attention to the output of the checksum command (it uses
4657 the ones from GNU coreutils).  In particular when the
4658 filename is not printable, coreutils uses a special
4659 backslash syntax.  For more information, see the GNU
4660 coreutils info file.");
4661
4662   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4663    [InitBasicFS, Always, TestOutputBuffer (
4664       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4665        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4666    "fill a file with a repeating pattern of bytes",
4667    "\
4668 This function is like C<guestfs_fill> except that it creates
4669 a new file of length C<len> containing the repeating pattern
4670 of bytes in C<pattern>.  The pattern is truncated if necessary
4671 to ensure the length of the file is exactly C<len> bytes.");
4672
4673   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4674    [InitBasicFS, Always, TestOutput (
4675       [["write"; "/new"; "new file contents"];
4676        ["cat"; "/new"]], "new file contents");
4677     InitBasicFS, Always, TestOutput (
4678       [["write"; "/new"; "\nnew file contents\n"];
4679        ["cat"; "/new"]], "\nnew file contents\n");
4680     InitBasicFS, Always, TestOutput (
4681       [["write"; "/new"; "\n\n"];
4682        ["cat"; "/new"]], "\n\n");
4683     InitBasicFS, Always, TestOutput (
4684       [["write"; "/new"; ""];
4685        ["cat"; "/new"]], "");
4686     InitBasicFS, Always, TestOutput (
4687       [["write"; "/new"; "\n\n\n"];
4688        ["cat"; "/new"]], "\n\n\n");
4689     InitBasicFS, Always, TestOutput (
4690       [["write"; "/new"; "\n"];
4691        ["cat"; "/new"]], "\n")],
4692    "create a new file",
4693    "\
4694 This call creates a file called C<path>.  The content of the
4695 file is the string C<content> (which can contain any 8 bit data).");
4696
4697   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4698    [InitBasicFS, Always, TestOutput (
4699       [["write"; "/new"; "new file contents"];
4700        ["pwrite"; "/new"; "data"; "4"];
4701        ["cat"; "/new"]], "new data contents");
4702     InitBasicFS, Always, TestOutput (
4703       [["write"; "/new"; "new file contents"];
4704        ["pwrite"; "/new"; "is extended"; "9"];
4705        ["cat"; "/new"]], "new file is extended");
4706     InitBasicFS, Always, TestOutput (
4707       [["write"; "/new"; "new file contents"];
4708        ["pwrite"; "/new"; ""; "4"];
4709        ["cat"; "/new"]], "new file contents")],
4710    "write to part of a file",
4711    "\
4712 This command writes to part of a file.  It writes the data
4713 buffer C<content> to the file C<path> starting at offset C<offset>.
4714
4715 This command implements the L<pwrite(2)> system call, and like
4716 that system call it may not write the full data requested.  The
4717 return value is the number of bytes that were actually written
4718 to the file.  This could even be 0, although short writes are
4719 unlikely for regular files in ordinary circumstances.
4720
4721 See also C<guestfs_pread>.");
4722
4723   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4724    [],
4725    "resize an ext2, ext3 or ext4 filesystem (with size)",
4726    "\
4727 This command is the same as C<guestfs_resize2fs> except that it
4728 allows you to specify the new size (in bytes) explicitly.");
4729
4730   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4731    [],
4732    "resize an LVM physical volume (with size)",
4733    "\
4734 This command is the same as C<guestfs_pvresize> except that it
4735 allows you to specify the new size (in bytes) explicitly.");
4736
4737   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4738    [],
4739    "resize an NTFS filesystem (with size)",
4740    "\
4741 This command is the same as C<guestfs_ntfsresize> except that it
4742 allows you to specify the new size (in bytes) explicitly.");
4743
4744   ("available_all_groups", (RStringList "groups", []), 251, [],
4745    [InitNone, Always, TestRun [["available_all_groups"]]],
4746    "return a list of all optional groups",
4747    "\
4748 This command returns a list of all optional groups that this
4749 daemon knows about.  Note this returns both supported and unsupported
4750 groups.  To find out which ones the daemon can actually support
4751 you have to call C<guestfs_available> on each member of the
4752 returned list.
4753
4754 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4755
4756   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4757    [InitBasicFS, Always, TestOutputStruct (
4758       [["fallocate64"; "/a"; "1000000"];
4759        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4760    "preallocate a file in the guest filesystem",
4761    "\
4762 This command preallocates a file (containing zero bytes) named
4763 C<path> of size C<len> bytes.  If the file exists already, it
4764 is overwritten.
4765
4766 Note that this call allocates disk blocks for the file.
4767 To create a sparse file use C<guestfs_truncate_size> instead.
4768
4769 The deprecated call C<guestfs_fallocate> does the same,
4770 but owing to an oversight it only allowed 30 bit lengths
4771 to be specified, effectively limiting the maximum size
4772 of files created through that call to 1GB.
4773
4774 Do not confuse this with the guestfish-specific
4775 C<alloc> and C<sparse> commands which create
4776 a file in the host and attach it as a device.");
4777
4778   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4779    [InitBasicFS, Always, TestOutput (
4780        [["set_e2label"; "/dev/sda1"; "LTEST"];
4781         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4782    "get the filesystem label",
4783    "\
4784 This returns the filesystem label of the filesystem on
4785 C<device>.
4786
4787 If the filesystem is unlabeled, this returns the empty string.");
4788
4789   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4790    (let uuid = uuidgen () in
4791     [InitBasicFS, Always, TestOutput (
4792        [["set_e2uuid"; "/dev/sda1"; uuid];
4793         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4794    "get the filesystem UUID",
4795    "\
4796 This returns the filesystem UUID of the filesystem on
4797 C<device>.
4798
4799 If the filesystem does not have a UUID, this returns the empty string.");
4800
4801 ]
4802
4803 let all_functions = non_daemon_functions @ daemon_functions
4804
4805 (* In some places we want the functions to be displayed sorted
4806  * alphabetically, so this is useful:
4807  *)
4808 let all_functions_sorted =
4809   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4810                compare n1 n2) all_functions
4811
4812 (* This is used to generate the src/MAX_PROC_NR file which
4813  * contains the maximum procedure number, a surrogate for the
4814  * ABI version number.  See src/Makefile.am for the details.
4815  *)
4816 let max_proc_nr =
4817   let proc_nrs = List.map (
4818     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4819   ) daemon_functions in
4820   List.fold_left max 0 proc_nrs
4821
4822 (* Field types for structures. *)
4823 type field =
4824   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4825   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4826   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4827   | FUInt32
4828   | FInt32
4829   | FUInt64
4830   | FInt64
4831   | FBytes                      (* Any int measure that counts bytes. *)
4832   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4833   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4834
4835 (* Because we generate extra parsing code for LVM command line tools,
4836  * we have to pull out the LVM columns separately here.
4837  *)
4838 let lvm_pv_cols = [
4839   "pv_name", FString;
4840   "pv_uuid", FUUID;
4841   "pv_fmt", FString;
4842   "pv_size", FBytes;
4843   "dev_size", FBytes;
4844   "pv_free", FBytes;
4845   "pv_used", FBytes;
4846   "pv_attr", FString (* XXX *);
4847   "pv_pe_count", FInt64;
4848   "pv_pe_alloc_count", FInt64;
4849   "pv_tags", FString;
4850   "pe_start", FBytes;
4851   "pv_mda_count", FInt64;
4852   "pv_mda_free", FBytes;
4853   (* Not in Fedora 10:
4854      "pv_mda_size", FBytes;
4855   *)
4856 ]
4857 let lvm_vg_cols = [
4858   "vg_name", FString;
4859   "vg_uuid", FUUID;
4860   "vg_fmt", FString;
4861   "vg_attr", FString (* XXX *);
4862   "vg_size", FBytes;
4863   "vg_free", FBytes;
4864   "vg_sysid", FString;
4865   "vg_extent_size", FBytes;
4866   "vg_extent_count", FInt64;
4867   "vg_free_count", FInt64;
4868   "max_lv", FInt64;
4869   "max_pv", FInt64;
4870   "pv_count", FInt64;
4871   "lv_count", FInt64;
4872   "snap_count", FInt64;
4873   "vg_seqno", FInt64;
4874   "vg_tags", FString;
4875   "vg_mda_count", FInt64;
4876   "vg_mda_free", FBytes;
4877   (* Not in Fedora 10:
4878      "vg_mda_size", FBytes;
4879   *)
4880 ]
4881 let lvm_lv_cols = [
4882   "lv_name", FString;
4883   "lv_uuid", FUUID;
4884   "lv_attr", FString (* XXX *);
4885   "lv_major", FInt64;
4886   "lv_minor", FInt64;
4887   "lv_kernel_major", FInt64;
4888   "lv_kernel_minor", FInt64;
4889   "lv_size", FBytes;
4890   "seg_count", FInt64;
4891   "origin", FString;
4892   "snap_percent", FOptPercent;
4893   "copy_percent", FOptPercent;
4894   "move_pv", FString;
4895   "lv_tags", FString;
4896   "mirror_log", FString;
4897   "modules", FString;
4898 ]
4899
4900 (* Names and fields in all structures (in RStruct and RStructList)
4901  * that we support.
4902  *)
4903 let structs = [
4904   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4905    * not use this struct in any new code.
4906    *)
4907   "int_bool", [
4908     "i", FInt32;                (* for historical compatibility *)
4909     "b", FInt32;                (* for historical compatibility *)
4910   ];
4911
4912   (* LVM PVs, VGs, LVs. *)
4913   "lvm_pv", lvm_pv_cols;
4914   "lvm_vg", lvm_vg_cols;
4915   "lvm_lv", lvm_lv_cols;
4916
4917   (* Column names and types from stat structures.
4918    * NB. Can't use things like 'st_atime' because glibc header files
4919    * define some of these as macros.  Ugh.
4920    *)
4921   "stat", [
4922     "dev", FInt64;
4923     "ino", FInt64;
4924     "mode", FInt64;
4925     "nlink", FInt64;
4926     "uid", FInt64;
4927     "gid", FInt64;
4928     "rdev", FInt64;
4929     "size", FInt64;
4930     "blksize", FInt64;
4931     "blocks", FInt64;
4932     "atime", FInt64;
4933     "mtime", FInt64;
4934     "ctime", FInt64;
4935   ];
4936   "statvfs", [
4937     "bsize", FInt64;
4938     "frsize", FInt64;
4939     "blocks", FInt64;
4940     "bfree", FInt64;
4941     "bavail", FInt64;
4942     "files", FInt64;
4943     "ffree", FInt64;
4944     "favail", FInt64;
4945     "fsid", FInt64;
4946     "flag", FInt64;
4947     "namemax", FInt64;
4948   ];
4949
4950   (* Column names in dirent structure. *)
4951   "dirent", [
4952     "ino", FInt64;
4953     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4954     "ftyp", FChar;
4955     "name", FString;
4956   ];
4957
4958   (* Version numbers. *)
4959   "version", [
4960     "major", FInt64;
4961     "minor", FInt64;
4962     "release", FInt64;
4963     "extra", FString;
4964   ];
4965
4966   (* Extended attribute. *)
4967   "xattr", [
4968     "attrname", FString;
4969     "attrval", FBuffer;
4970   ];
4971
4972   (* Inotify events. *)
4973   "inotify_event", [
4974     "in_wd", FInt64;
4975     "in_mask", FUInt32;
4976     "in_cookie", FUInt32;
4977     "in_name", FString;
4978   ];
4979
4980   (* Partition table entry. *)
4981   "partition", [
4982     "part_num", FInt32;
4983     "part_start", FBytes;
4984     "part_end", FBytes;
4985     "part_size", FBytes;
4986   ];
4987 ] (* end of structs *)
4988
4989 (* Ugh, Java has to be different ..
4990  * These names are also used by the Haskell bindings.
4991  *)
4992 let java_structs = [
4993   "int_bool", "IntBool";
4994   "lvm_pv", "PV";
4995   "lvm_vg", "VG";
4996   "lvm_lv", "LV";
4997   "stat", "Stat";
4998   "statvfs", "StatVFS";
4999   "dirent", "Dirent";
5000   "version", "Version";
5001   "xattr", "XAttr";
5002   "inotify_event", "INotifyEvent";
5003   "partition", "Partition";
5004 ]
5005
5006 (* What structs are actually returned. *)
5007 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5008
5009 (* Returns a list of RStruct/RStructList structs that are returned
5010  * by any function.  Each element of returned list is a pair:
5011  *
5012  * (structname, RStructOnly)
5013  *    == there exists function which returns RStruct (_, structname)
5014  * (structname, RStructListOnly)
5015  *    == there exists function which returns RStructList (_, structname)
5016  * (structname, RStructAndList)
5017  *    == there are functions returning both RStruct (_, structname)
5018  *                                      and RStructList (_, structname)
5019  *)
5020 let rstructs_used_by functions =
5021   (* ||| is a "logical OR" for rstructs_used_t *)
5022   let (|||) a b =
5023     match a, b with
5024     | RStructAndList, _
5025     | _, RStructAndList -> RStructAndList
5026     | RStructOnly, RStructListOnly
5027     | RStructListOnly, RStructOnly -> RStructAndList
5028     | RStructOnly, RStructOnly -> RStructOnly
5029     | RStructListOnly, RStructListOnly -> RStructListOnly
5030   in
5031
5032   let h = Hashtbl.create 13 in
5033
5034   (* if elem->oldv exists, update entry using ||| operator,
5035    * else just add elem->newv to the hash
5036    *)
5037   let update elem newv =
5038     try  let oldv = Hashtbl.find h elem in
5039          Hashtbl.replace h elem (newv ||| oldv)
5040     with Not_found -> Hashtbl.add h elem newv
5041   in
5042
5043   List.iter (
5044     fun (_, style, _, _, _, _, _) ->
5045       match fst style with
5046       | RStruct (_, structname) -> update structname RStructOnly
5047       | RStructList (_, structname) -> update structname RStructListOnly
5048       | _ -> ()
5049   ) functions;
5050
5051   (* return key->values as a list of (key,value) *)
5052   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5053
5054 (* Used for testing language bindings. *)
5055 type callt =
5056   | CallString of string
5057   | CallOptString of string option
5058   | CallStringList of string list
5059   | CallInt of int
5060   | CallInt64 of int64
5061   | CallBool of bool
5062   | CallBuffer of string
5063
5064 (* Used to memoize the result of pod2text. *)
5065 let pod2text_memo_filename = "src/.pod2text.data"
5066 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5067   try
5068     let chan = open_in pod2text_memo_filename in
5069     let v = input_value chan in
5070     close_in chan;
5071     v
5072   with
5073     _ -> Hashtbl.create 13
5074 let pod2text_memo_updated () =
5075   let chan = open_out pod2text_memo_filename in
5076   output_value chan pod2text_memo;
5077   close_out chan
5078
5079 (* Useful functions.
5080  * Note we don't want to use any external OCaml libraries which
5081  * makes this a bit harder than it should be.
5082  *)
5083 module StringMap = Map.Make (String)
5084
5085 let failwithf fs = ksprintf failwith fs
5086
5087 let unique = let i = ref 0 in fun () -> incr i; !i
5088
5089 let replace_char s c1 c2 =
5090   let s2 = String.copy s in
5091   let r = ref false in
5092   for i = 0 to String.length s2 - 1 do
5093     if String.unsafe_get s2 i = c1 then (
5094       String.unsafe_set s2 i c2;
5095       r := true
5096     )
5097   done;
5098   if not !r then s else s2
5099
5100 let isspace c =
5101   c = ' '
5102   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5103
5104 let triml ?(test = isspace) str =
5105   let i = ref 0 in
5106   let n = ref (String.length str) in
5107   while !n > 0 && test str.[!i]; do
5108     decr n;
5109     incr i
5110   done;
5111   if !i = 0 then str
5112   else String.sub str !i !n
5113
5114 let trimr ?(test = isspace) str =
5115   let n = ref (String.length str) in
5116   while !n > 0 && test str.[!n-1]; do
5117     decr n
5118   done;
5119   if !n = String.length str then str
5120   else String.sub str 0 !n
5121
5122 let trim ?(test = isspace) str =
5123   trimr ~test (triml ~test str)
5124
5125 let rec find s sub =
5126   let len = String.length s in
5127   let sublen = String.length sub in
5128   let rec loop i =
5129     if i <= len-sublen then (
5130       let rec loop2 j =
5131         if j < sublen then (
5132           if s.[i+j] = sub.[j] then loop2 (j+1)
5133           else -1
5134         ) else
5135           i (* found *)
5136       in
5137       let r = loop2 0 in
5138       if r = -1 then loop (i+1) else r
5139     ) else
5140       -1 (* not found *)
5141   in
5142   loop 0
5143
5144 let rec replace_str s s1 s2 =
5145   let len = String.length s in
5146   let sublen = String.length s1 in
5147   let i = find s s1 in
5148   if i = -1 then s
5149   else (
5150     let s' = String.sub s 0 i in
5151     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5152     s' ^ s2 ^ replace_str s'' s1 s2
5153   )
5154
5155 let rec string_split sep str =
5156   let len = String.length str in
5157   let seplen = String.length sep in
5158   let i = find str sep in
5159   if i = -1 then [str]
5160   else (
5161     let s' = String.sub str 0 i in
5162     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5163     s' :: string_split sep s''
5164   )
5165
5166 let files_equal n1 n2 =
5167   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5168   match Sys.command cmd with
5169   | 0 -> true
5170   | 1 -> false
5171   | i -> failwithf "%s: failed with error code %d" cmd i
5172
5173 let rec filter_map f = function
5174   | [] -> []
5175   | x :: xs ->
5176       match f x with
5177       | Some y -> y :: filter_map f xs
5178       | None -> filter_map f xs
5179
5180 let rec find_map f = function
5181   | [] -> raise Not_found
5182   | x :: xs ->
5183       match f x with
5184       | Some y -> y
5185       | None -> find_map f xs
5186
5187 let iteri f xs =
5188   let rec loop i = function
5189     | [] -> ()
5190     | x :: xs -> f i x; loop (i+1) xs
5191   in
5192   loop 0 xs
5193
5194 let mapi f xs =
5195   let rec loop i = function
5196     | [] -> []
5197     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5198   in
5199   loop 0 xs
5200
5201 let count_chars c str =
5202   let count = ref 0 in
5203   for i = 0 to String.length str - 1 do
5204     if c = String.unsafe_get str i then incr count
5205   done;
5206   !count
5207
5208 let explode str =
5209   let r = ref [] in
5210   for i = 0 to String.length str - 1 do
5211     let c = String.unsafe_get str i in
5212     r := c :: !r;
5213   done;
5214   List.rev !r
5215
5216 let map_chars f str =
5217   List.map f (explode str)
5218
5219 let name_of_argt = function
5220   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5221   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5222   | FileIn n | FileOut n | BufferIn n -> n
5223
5224 let java_name_of_struct typ =
5225   try List.assoc typ java_structs
5226   with Not_found ->
5227     failwithf
5228       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5229
5230 let cols_of_struct typ =
5231   try List.assoc typ structs
5232   with Not_found ->
5233     failwithf "cols_of_struct: unknown struct %s" typ
5234
5235 let seq_of_test = function
5236   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5237   | TestOutputListOfDevices (s, _)
5238   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5239   | TestOutputTrue s | TestOutputFalse s
5240   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5241   | TestOutputStruct (s, _)
5242   | TestLastFail s -> s
5243
5244 (* Handling for function flags. *)
5245 let protocol_limit_warning =
5246   "Because of the message protocol, there is a transfer limit
5247 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5248
5249 let danger_will_robinson =
5250   "B<This command is dangerous.  Without careful use you
5251 can easily destroy all your data>."
5252
5253 let deprecation_notice flags =
5254   try
5255     let alt =
5256       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5257     let txt =
5258       sprintf "This function is deprecated.
5259 In new code, use the C<%s> call instead.
5260
5261 Deprecated functions will not be removed from the API, but the
5262 fact that they are deprecated indicates that there are problems
5263 with correct use of these functions." alt in
5264     Some txt
5265   with
5266     Not_found -> None
5267
5268 (* Create list of optional groups. *)
5269 let optgroups =
5270   let h = Hashtbl.create 13 in
5271   List.iter (
5272     fun (name, _, _, flags, _, _, _) ->
5273       List.iter (
5274         function
5275         | Optional group ->
5276             let names = try Hashtbl.find h group with Not_found -> [] in
5277             Hashtbl.replace h group (name :: names)
5278         | _ -> ()
5279       ) flags
5280   ) daemon_functions;
5281   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5282   let groups =
5283     List.map (
5284       fun group -> group, List.sort compare (Hashtbl.find h group)
5285     ) groups in
5286   List.sort (fun x y -> compare (fst x) (fst y)) groups
5287
5288 (* Check function names etc. for consistency. *)
5289 let check_functions () =
5290   let contains_uppercase str =
5291     let len = String.length str in
5292     let rec loop i =
5293       if i >= len then false
5294       else (
5295         let c = str.[i] in
5296         if c >= 'A' && c <= 'Z' then true
5297         else loop (i+1)
5298       )
5299     in
5300     loop 0
5301   in
5302
5303   (* Check function names. *)
5304   List.iter (
5305     fun (name, _, _, _, _, _, _) ->
5306       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5307         failwithf "function name %s does not need 'guestfs' prefix" name;
5308       if name = "" then
5309         failwithf "function name is empty";
5310       if name.[0] < 'a' || name.[0] > 'z' then
5311         failwithf "function name %s must start with lowercase a-z" name;
5312       if String.contains name '-' then
5313         failwithf "function name %s should not contain '-', use '_' instead."
5314           name
5315   ) all_functions;
5316
5317   (* Check function parameter/return names. *)
5318   List.iter (
5319     fun (name, style, _, _, _, _, _) ->
5320       let check_arg_ret_name n =
5321         if contains_uppercase n then
5322           failwithf "%s param/ret %s should not contain uppercase chars"
5323             name n;
5324         if String.contains n '-' || String.contains n '_' then
5325           failwithf "%s param/ret %s should not contain '-' or '_'"
5326             name n;
5327         if n = "value" then
5328           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;
5329         if n = "int" || n = "char" || n = "short" || n = "long" then
5330           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5331         if n = "i" || n = "n" then
5332           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5333         if n = "argv" || n = "args" then
5334           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5335
5336         (* List Haskell, OCaml and C keywords here.
5337          * http://www.haskell.org/haskellwiki/Keywords
5338          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5339          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5340          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5341          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5342          * Omitting _-containing words, since they're handled above.
5343          * Omitting the OCaml reserved word, "val", is ok,
5344          * and saves us from renaming several parameters.
5345          *)
5346         let reserved = [
5347           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5348           "char"; "class"; "const"; "constraint"; "continue"; "data";
5349           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5350           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5351           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5352           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5353           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5354           "interface";
5355           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5356           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5357           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5358           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5359           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5360           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5361           "volatile"; "when"; "where"; "while";
5362           ] in
5363         if List.mem n reserved then
5364           failwithf "%s has param/ret using reserved word %s" name n;
5365       in
5366
5367       (match fst style with
5368        | RErr -> ()
5369        | RInt n | RInt64 n | RBool n
5370        | RConstString n | RConstOptString n | RString n
5371        | RStringList n | RStruct (n, _) | RStructList (n, _)
5372        | RHashtable n | RBufferOut n ->
5373            check_arg_ret_name n
5374       );
5375       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5376   ) all_functions;
5377
5378   (* Check short descriptions. *)
5379   List.iter (
5380     fun (name, _, _, _, _, shortdesc, _) ->
5381       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5382         failwithf "short description of %s should begin with lowercase." name;
5383       let c = shortdesc.[String.length shortdesc-1] in
5384       if c = '\n' || c = '.' then
5385         failwithf "short description of %s should not end with . or \\n." name
5386   ) all_functions;
5387
5388   (* Check long descriptions. *)
5389   List.iter (
5390     fun (name, _, _, _, _, _, longdesc) ->
5391       if longdesc.[String.length longdesc-1] = '\n' then
5392         failwithf "long description of %s should not end with \\n." name
5393   ) all_functions;
5394
5395   (* Check proc_nrs. *)
5396   List.iter (
5397     fun (name, _, proc_nr, _, _, _, _) ->
5398       if proc_nr <= 0 then
5399         failwithf "daemon function %s should have proc_nr > 0" name
5400   ) daemon_functions;
5401
5402   List.iter (
5403     fun (name, _, proc_nr, _, _, _, _) ->
5404       if proc_nr <> -1 then
5405         failwithf "non-daemon function %s should have proc_nr -1" name
5406   ) non_daemon_functions;
5407
5408   let proc_nrs =
5409     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5410       daemon_functions in
5411   let proc_nrs =
5412     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5413   let rec loop = function
5414     | [] -> ()
5415     | [_] -> ()
5416     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5417         loop rest
5418     | (name1,nr1) :: (name2,nr2) :: _ ->
5419         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5420           name1 name2 nr1 nr2
5421   in
5422   loop proc_nrs;
5423
5424   (* Check tests. *)
5425   List.iter (
5426     function
5427       (* Ignore functions that have no tests.  We generate a
5428        * warning when the user does 'make check' instead.
5429        *)
5430     | name, _, _, _, [], _, _ -> ()
5431     | name, _, _, _, tests, _, _ ->
5432         let funcs =
5433           List.map (
5434             fun (_, _, test) ->
5435               match seq_of_test test with
5436               | [] ->
5437                   failwithf "%s has a test containing an empty sequence" name
5438               | cmds -> List.map List.hd cmds
5439           ) tests in
5440         let funcs = List.flatten funcs in
5441
5442         let tested = List.mem name funcs in
5443
5444         if not tested then
5445           failwithf "function %s has tests but does not test itself" name
5446   ) all_functions
5447
5448 (* 'pr' prints to the current output file. *)
5449 let chan = ref Pervasives.stdout
5450 let lines = ref 0
5451 let pr fs =
5452   ksprintf
5453     (fun str ->
5454        let i = count_chars '\n' str in
5455        lines := !lines + i;
5456        output_string !chan str
5457     ) fs
5458
5459 let copyright_years =
5460   let this_year = 1900 + (localtime (time ())).tm_year in
5461   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5462
5463 (* Generate a header block in a number of standard styles. *)
5464 type comment_style =
5465     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5466 type license = GPLv2plus | LGPLv2plus
5467
5468 let generate_header ?(extra_inputs = []) comment license =
5469   let inputs = "src/generator.ml" :: extra_inputs in
5470   let c = match comment with
5471     | CStyle ->         pr "/* "; " *"
5472     | CPlusPlusStyle -> pr "// "; "//"
5473     | HashStyle ->      pr "# ";  "#"
5474     | OCamlStyle ->     pr "(* "; " *"
5475     | HaskellStyle ->   pr "{- "; "  " in
5476   pr "libguestfs generated file\n";
5477   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5478   List.iter (pr "%s   %s\n" c) inputs;
5479   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5480   pr "%s\n" c;
5481   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5482   pr "%s\n" c;
5483   (match license with
5484    | GPLv2plus ->
5485        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5486        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5487        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5488        pr "%s (at your option) any later version.\n" c;
5489        pr "%s\n" c;
5490        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5491        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5492        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5493        pr "%s GNU General Public License for more details.\n" c;
5494        pr "%s\n" c;
5495        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5496        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5497        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5498
5499    | LGPLv2plus ->
5500        pr "%s This library is free software; you can redistribute it and/or\n" c;
5501        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5502        pr "%s License as published by the Free Software Foundation; either\n" c;
5503        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5504        pr "%s\n" c;
5505        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5506        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5507        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5508        pr "%s Lesser General Public License for more details.\n" c;
5509        pr "%s\n" c;
5510        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5511        pr "%s License along with this library; if not, write to the Free Software\n" c;
5512        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5513   );
5514   (match comment with
5515    | CStyle -> pr " */\n"
5516    | CPlusPlusStyle
5517    | HashStyle -> ()
5518    | OCamlStyle -> pr " *)\n"
5519    | HaskellStyle -> pr "-}\n"
5520   );
5521   pr "\n"
5522
5523 (* Start of main code generation functions below this line. *)
5524
5525 (* Generate the pod documentation for the C API. *)
5526 let rec generate_actions_pod () =
5527   List.iter (
5528     fun (shortname, style, _, flags, _, _, longdesc) ->
5529       if not (List.mem NotInDocs flags) then (
5530         let name = "guestfs_" ^ shortname in
5531         pr "=head2 %s\n\n" name;
5532         pr " ";
5533         generate_prototype ~extern:false ~handle:"g" name style;
5534         pr "\n\n";
5535         pr "%s\n\n" longdesc;
5536         (match fst style with
5537          | RErr ->
5538              pr "This function returns 0 on success or -1 on error.\n\n"
5539          | RInt _ ->
5540              pr "On error this function returns -1.\n\n"
5541          | RInt64 _ ->
5542              pr "On error this function returns -1.\n\n"
5543          | RBool _ ->
5544              pr "This function returns a C truth value on success or -1 on error.\n\n"
5545          | RConstString _ ->
5546              pr "This function returns a string, or NULL on error.
5547 The string is owned by the guest handle and must I<not> be freed.\n\n"
5548          | RConstOptString _ ->
5549              pr "This function returns a string which may be NULL.
5550 There is way to return an error from this function.
5551 The string is owned by the guest handle and must I<not> be freed.\n\n"
5552          | RString _ ->
5553              pr "This function returns a string, or NULL on error.
5554 I<The caller must free the returned string after use>.\n\n"
5555          | RStringList _ ->
5556              pr "This function returns a NULL-terminated array of strings
5557 (like L<environ(3)>), or NULL if there was an error.
5558 I<The caller must free the strings and the array after use>.\n\n"
5559          | RStruct (_, typ) ->
5560              pr "This function returns a C<struct guestfs_%s *>,
5561 or NULL if there was an error.
5562 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5563          | RStructList (_, typ) ->
5564              pr "This function returns a C<struct guestfs_%s_list *>
5565 (see E<lt>guestfs-structs.hE<gt>),
5566 or NULL if there was an error.
5567 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5568          | RHashtable _ ->
5569              pr "This function returns a NULL-terminated array of
5570 strings, or NULL if there was an error.
5571 The array of strings will always have length C<2n+1>, where
5572 C<n> keys and values alternate, followed by the trailing NULL entry.
5573 I<The caller must free the strings and the array after use>.\n\n"
5574          | RBufferOut _ ->
5575              pr "This function returns a buffer, or NULL on error.
5576 The size of the returned buffer is written to C<*size_r>.
5577 I<The caller must free the returned buffer after use>.\n\n"
5578         );
5579         if List.mem ProtocolLimitWarning flags then
5580           pr "%s\n\n" protocol_limit_warning;
5581         if List.mem DangerWillRobinson flags then
5582           pr "%s\n\n" danger_will_robinson;
5583         match deprecation_notice flags with
5584         | None -> ()
5585         | Some txt -> pr "%s\n\n" txt
5586       )
5587   ) all_functions_sorted
5588
5589 and generate_structs_pod () =
5590   (* Structs documentation. *)
5591   List.iter (
5592     fun (typ, cols) ->
5593       pr "=head2 guestfs_%s\n" typ;
5594       pr "\n";
5595       pr " struct guestfs_%s {\n" typ;
5596       List.iter (
5597         function
5598         | name, FChar -> pr "   char %s;\n" name
5599         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5600         | name, FInt32 -> pr "   int32_t %s;\n" name
5601         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5602         | name, FInt64 -> pr "   int64_t %s;\n" name
5603         | name, FString -> pr "   char *%s;\n" name
5604         | name, FBuffer ->
5605             pr "   /* The next two fields describe a byte array. */\n";
5606             pr "   uint32_t %s_len;\n" name;
5607             pr "   char *%s;\n" name
5608         | name, FUUID ->
5609             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5610             pr "   char %s[32];\n" name
5611         | name, FOptPercent ->
5612             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5613             pr "   float %s;\n" name
5614       ) cols;
5615       pr " };\n";
5616       pr " \n";
5617       pr " struct guestfs_%s_list {\n" typ;
5618       pr "   uint32_t len; /* Number of elements in list. */\n";
5619       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5620       pr " };\n";
5621       pr " \n";
5622       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5623       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5624         typ typ;
5625       pr "\n"
5626   ) structs
5627
5628 and generate_availability_pod () =
5629   (* Availability documentation. *)
5630   pr "=over 4\n";
5631   pr "\n";
5632   List.iter (
5633     fun (group, functions) ->
5634       pr "=item B<%s>\n" group;
5635       pr "\n";
5636       pr "The following functions:\n";
5637       List.iter (pr "L</guestfs_%s>\n") functions;
5638       pr "\n"
5639   ) optgroups;
5640   pr "=back\n";
5641   pr "\n"
5642
5643 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5644  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5645  *
5646  * We have to use an underscore instead of a dash because otherwise
5647  * rpcgen generates incorrect code.
5648  *
5649  * This header is NOT exported to clients, but see also generate_structs_h.
5650  *)
5651 and generate_xdr () =
5652   generate_header CStyle LGPLv2plus;
5653
5654   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5655   pr "typedef string str<>;\n";
5656   pr "\n";
5657
5658   (* Internal structures. *)
5659   List.iter (
5660     function
5661     | typ, cols ->
5662         pr "struct guestfs_int_%s {\n" typ;
5663         List.iter (function
5664                    | name, FChar -> pr "  char %s;\n" name
5665                    | name, FString -> pr "  string %s<>;\n" name
5666                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5667                    | name, FUUID -> pr "  opaque %s[32];\n" name
5668                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5669                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5670                    | name, FOptPercent -> pr "  float %s;\n" name
5671                   ) cols;
5672         pr "};\n";
5673         pr "\n";
5674         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5675         pr "\n";
5676   ) structs;
5677
5678   List.iter (
5679     fun (shortname, style, _, _, _, _, _) ->
5680       let name = "guestfs_" ^ shortname in
5681
5682       (match snd style with
5683        | [] -> ()
5684        | args ->
5685            pr "struct %s_args {\n" name;
5686            List.iter (
5687              function
5688              | Pathname n | Device n | Dev_or_Path n | String n ->
5689                  pr "  string %s<>;\n" n
5690              | OptString n -> pr "  str *%s;\n" n
5691              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5692              | Bool n -> pr "  bool %s;\n" n
5693              | Int n -> pr "  int %s;\n" n
5694              | Int64 n -> pr "  hyper %s;\n" n
5695              | BufferIn n ->
5696                  pr "  opaque %s<>;\n" n
5697              | FileIn _ | FileOut _ -> ()
5698            ) args;
5699            pr "};\n\n"
5700       );
5701       (match fst style with
5702        | RErr -> ()
5703        | RInt n ->
5704            pr "struct %s_ret {\n" name;
5705            pr "  int %s;\n" n;
5706            pr "};\n\n"
5707        | RInt64 n ->
5708            pr "struct %s_ret {\n" name;
5709            pr "  hyper %s;\n" n;
5710            pr "};\n\n"
5711        | RBool n ->
5712            pr "struct %s_ret {\n" name;
5713            pr "  bool %s;\n" n;
5714            pr "};\n\n"
5715        | RConstString _ | RConstOptString _ ->
5716            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5717        | RString n ->
5718            pr "struct %s_ret {\n" name;
5719            pr "  string %s<>;\n" n;
5720            pr "};\n\n"
5721        | RStringList n ->
5722            pr "struct %s_ret {\n" name;
5723            pr "  str %s<>;\n" n;
5724            pr "};\n\n"
5725        | RStruct (n, typ) ->
5726            pr "struct %s_ret {\n" name;
5727            pr "  guestfs_int_%s %s;\n" typ n;
5728            pr "};\n\n"
5729        | RStructList (n, typ) ->
5730            pr "struct %s_ret {\n" name;
5731            pr "  guestfs_int_%s_list %s;\n" typ n;
5732            pr "};\n\n"
5733        | RHashtable n ->
5734            pr "struct %s_ret {\n" name;
5735            pr "  str %s<>;\n" n;
5736            pr "};\n\n"
5737        | RBufferOut n ->
5738            pr "struct %s_ret {\n" name;
5739            pr "  opaque %s<>;\n" n;
5740            pr "};\n\n"
5741       );
5742   ) daemon_functions;
5743
5744   (* Table of procedure numbers. *)
5745   pr "enum guestfs_procedure {\n";
5746   List.iter (
5747     fun (shortname, _, proc_nr, _, _, _, _) ->
5748       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5749   ) daemon_functions;
5750   pr "  GUESTFS_PROC_NR_PROCS\n";
5751   pr "};\n";
5752   pr "\n";
5753
5754   (* Having to choose a maximum message size is annoying for several
5755    * reasons (it limits what we can do in the API), but it (a) makes
5756    * the protocol a lot simpler, and (b) provides a bound on the size
5757    * of the daemon which operates in limited memory space.
5758    *)
5759   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5760   pr "\n";
5761
5762   (* Message header, etc. *)
5763   pr "\
5764 /* The communication protocol is now documented in the guestfs(3)
5765  * manpage.
5766  */
5767
5768 const GUESTFS_PROGRAM = 0x2000F5F5;
5769 const GUESTFS_PROTOCOL_VERSION = 1;
5770
5771 /* These constants must be larger than any possible message length. */
5772 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5773 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5774
5775 enum guestfs_message_direction {
5776   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5777   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5778 };
5779
5780 enum guestfs_message_status {
5781   GUESTFS_STATUS_OK = 0,
5782   GUESTFS_STATUS_ERROR = 1
5783 };
5784
5785 const GUESTFS_ERROR_LEN = 256;
5786
5787 struct guestfs_message_error {
5788   string error_message<GUESTFS_ERROR_LEN>;
5789 };
5790
5791 struct guestfs_message_header {
5792   unsigned prog;                     /* GUESTFS_PROGRAM */
5793   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5794   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5795   guestfs_message_direction direction;
5796   unsigned serial;                   /* message serial number */
5797   guestfs_message_status status;
5798 };
5799
5800 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5801
5802 struct guestfs_chunk {
5803   int cancel;                        /* if non-zero, transfer is cancelled */
5804   /* data size is 0 bytes if the transfer has finished successfully */
5805   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5806 };
5807 "
5808
5809 (* Generate the guestfs-structs.h file. *)
5810 and generate_structs_h () =
5811   generate_header CStyle LGPLv2plus;
5812
5813   (* This is a public exported header file containing various
5814    * structures.  The structures are carefully written to have
5815    * exactly the same in-memory format as the XDR structures that
5816    * we use on the wire to the daemon.  The reason for creating
5817    * copies of these structures here is just so we don't have to
5818    * export the whole of guestfs_protocol.h (which includes much
5819    * unrelated and XDR-dependent stuff that we don't want to be
5820    * public, or required by clients).
5821    *
5822    * To reiterate, we will pass these structures to and from the
5823    * client with a simple assignment or memcpy, so the format
5824    * must be identical to what rpcgen / the RFC defines.
5825    *)
5826
5827   (* Public structures. *)
5828   List.iter (
5829     fun (typ, cols) ->
5830       pr "struct guestfs_%s {\n" typ;
5831       List.iter (
5832         function
5833         | name, FChar -> pr "  char %s;\n" name
5834         | name, FString -> pr "  char *%s;\n" name
5835         | name, FBuffer ->
5836             pr "  uint32_t %s_len;\n" name;
5837             pr "  char *%s;\n" name
5838         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5839         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5840         | name, FInt32 -> pr "  int32_t %s;\n" name
5841         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5842         | name, FInt64 -> pr "  int64_t %s;\n" name
5843         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5844       ) cols;
5845       pr "};\n";
5846       pr "\n";
5847       pr "struct guestfs_%s_list {\n" typ;
5848       pr "  uint32_t len;\n";
5849       pr "  struct guestfs_%s *val;\n" typ;
5850       pr "};\n";
5851       pr "\n";
5852       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5853       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5854       pr "\n"
5855   ) structs
5856
5857 (* Generate the guestfs-actions.h file. *)
5858 and generate_actions_h () =
5859   generate_header CStyle LGPLv2plus;
5860   List.iter (
5861     fun (shortname, style, _, _, _, _, _) ->
5862       let name = "guestfs_" ^ shortname in
5863       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5864         name style
5865   ) all_functions
5866
5867 (* Generate the guestfs-internal-actions.h file. *)
5868 and generate_internal_actions_h () =
5869   generate_header CStyle LGPLv2plus;
5870   List.iter (
5871     fun (shortname, style, _, _, _, _, _) ->
5872       let name = "guestfs__" ^ shortname in
5873       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5874         name style
5875   ) non_daemon_functions
5876
5877 (* Generate the client-side dispatch stubs. *)
5878 and generate_client_actions () =
5879   generate_header CStyle LGPLv2plus;
5880
5881   pr "\
5882 #include <stdio.h>
5883 #include <stdlib.h>
5884 #include <stdint.h>
5885 #include <string.h>
5886 #include <inttypes.h>
5887
5888 #include \"guestfs.h\"
5889 #include \"guestfs-internal.h\"
5890 #include \"guestfs-internal-actions.h\"
5891 #include \"guestfs_protocol.h\"
5892
5893 #define error guestfs_error
5894 //#define perrorf guestfs_perrorf
5895 #define safe_malloc guestfs_safe_malloc
5896 #define safe_realloc guestfs_safe_realloc
5897 //#define safe_strdup guestfs_safe_strdup
5898 #define safe_memdup guestfs_safe_memdup
5899
5900 /* Check the return message from a call for validity. */
5901 static int
5902 check_reply_header (guestfs_h *g,
5903                     const struct guestfs_message_header *hdr,
5904                     unsigned int proc_nr, unsigned int serial)
5905 {
5906   if (hdr->prog != GUESTFS_PROGRAM) {
5907     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5908     return -1;
5909   }
5910   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5911     error (g, \"wrong protocol version (%%d/%%d)\",
5912            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5913     return -1;
5914   }
5915   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5916     error (g, \"unexpected message direction (%%d/%%d)\",
5917            hdr->direction, GUESTFS_DIRECTION_REPLY);
5918     return -1;
5919   }
5920   if (hdr->proc != proc_nr) {
5921     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5922     return -1;
5923   }
5924   if (hdr->serial != serial) {
5925     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5926     return -1;
5927   }
5928
5929   return 0;
5930 }
5931
5932 /* Check we are in the right state to run a high-level action. */
5933 static int
5934 check_state (guestfs_h *g, const char *caller)
5935 {
5936   if (!guestfs__is_ready (g)) {
5937     if (guestfs__is_config (g) || guestfs__is_launching (g))
5938       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5939         caller);
5940     else
5941       error (g, \"%%s called from the wrong state, %%d != READY\",
5942         caller, guestfs__get_state (g));
5943     return -1;
5944   }
5945   return 0;
5946 }
5947
5948 ";
5949
5950   let error_code_of = function
5951     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5952     | RConstString _ | RConstOptString _
5953     | RString _ | RStringList _
5954     | RStruct _ | RStructList _
5955     | RHashtable _ | RBufferOut _ -> "NULL"
5956   in
5957
5958   (* Generate code to check String-like parameters are not passed in
5959    * as NULL (returning an error if they are).
5960    *)
5961   let check_null_strings shortname style =
5962     let pr_newline = ref false in
5963     List.iter (
5964       function
5965       (* parameters which should not be NULL *)
5966       | String n
5967       | Device n
5968       | Pathname n
5969       | Dev_or_Path n
5970       | FileIn n
5971       | FileOut n
5972       | BufferIn n
5973       | StringList n
5974       | DeviceList n ->
5975           pr "  if (%s == NULL) {\n" n;
5976           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5977           pr "           \"%s\", \"%s\");\n" shortname n;
5978           pr "    return %s;\n" (error_code_of (fst style));
5979           pr "  }\n";
5980           pr_newline := true
5981
5982       (* can be NULL *)
5983       | OptString _
5984
5985       (* not applicable *)
5986       | Bool _
5987       | Int _
5988       | Int64 _ -> ()
5989     ) (snd style);
5990
5991     if !pr_newline then pr "\n";
5992   in
5993
5994   (* Generate code to generate guestfish call traces. *)
5995   let trace_call shortname style =
5996     pr "  if (guestfs__get_trace (g)) {\n";
5997
5998     let needs_i =
5999       List.exists (function
6000                    | StringList _ | DeviceList _ -> true
6001                    | _ -> false) (snd style) in
6002     if needs_i then (
6003       pr "    int i;\n";
6004       pr "\n"
6005     );
6006
6007     pr "    printf (\"%s\");\n" shortname;
6008     List.iter (
6009       function
6010       | String n                        (* strings *)
6011       | Device n
6012       | Pathname n
6013       | Dev_or_Path n
6014       | FileIn n
6015       | FileOut n
6016       | BufferIn n ->
6017           (* guestfish doesn't support string escaping, so neither do we *)
6018           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6019       | OptString n ->                  (* string option *)
6020           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6021           pr "    else printf (\" null\");\n"
6022       | StringList n
6023       | DeviceList n ->                 (* string list *)
6024           pr "    putchar (' ');\n";
6025           pr "    putchar ('\"');\n";
6026           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6027           pr "      if (i > 0) putchar (' ');\n";
6028           pr "      fputs (%s[i], stdout);\n" n;
6029           pr "    }\n";
6030           pr "    putchar ('\"');\n";
6031       | Bool n ->                       (* boolean *)
6032           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6033       | Int n ->                        (* int *)
6034           pr "    printf (\" %%d\", %s);\n" n
6035       | Int64 n ->
6036           pr "    printf (\" %%\" PRIi64, %s);\n" n
6037     ) (snd style);
6038     pr "    putchar ('\\n');\n";
6039     pr "  }\n";
6040     pr "\n";
6041   in
6042
6043   (* For non-daemon functions, generate a wrapper around each function. *)
6044   List.iter (
6045     fun (shortname, style, _, _, _, _, _) ->
6046       let name = "guestfs_" ^ shortname in
6047
6048       generate_prototype ~extern:false ~semicolon:false ~newline:true
6049         ~handle:"g" name style;
6050       pr "{\n";
6051       check_null_strings shortname style;
6052       trace_call shortname style;
6053       pr "  return guestfs__%s " shortname;
6054       generate_c_call_args ~handle:"g" style;
6055       pr ";\n";
6056       pr "}\n";
6057       pr "\n"
6058   ) non_daemon_functions;
6059
6060   (* Client-side stubs for each function. *)
6061   List.iter (
6062     fun (shortname, style, _, _, _, _, _) ->
6063       let name = "guestfs_" ^ shortname in
6064       let error_code = error_code_of (fst style) in
6065
6066       (* Generate the action stub. *)
6067       generate_prototype ~extern:false ~semicolon:false ~newline:true
6068         ~handle:"g" name style;
6069
6070       pr "{\n";
6071
6072       (match snd style with
6073        | [] -> ()
6074        | _ -> pr "  struct %s_args args;\n" name
6075       );
6076
6077       pr "  guestfs_message_header hdr;\n";
6078       pr "  guestfs_message_error err;\n";
6079       let has_ret =
6080         match fst style with
6081         | RErr -> false
6082         | RConstString _ | RConstOptString _ ->
6083             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6084         | RInt _ | RInt64 _
6085         | RBool _ | RString _ | RStringList _
6086         | RStruct _ | RStructList _
6087         | RHashtable _ | RBufferOut _ ->
6088             pr "  struct %s_ret ret;\n" name;
6089             true in
6090
6091       pr "  int serial;\n";
6092       pr "  int r;\n";
6093       pr "\n";
6094       check_null_strings shortname style;
6095       trace_call shortname style;
6096       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6097         shortname error_code;
6098       pr "  guestfs___set_busy (g);\n";
6099       pr "\n";
6100
6101       (* Send the main header and arguments. *)
6102       (match snd style with
6103        | [] ->
6104            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6105              (String.uppercase shortname)
6106        | args ->
6107            List.iter (
6108              function
6109              | Pathname n | Device n | Dev_or_Path n | String n ->
6110                  pr "  args.%s = (char *) %s;\n" n n
6111              | OptString n ->
6112                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6113              | StringList n | DeviceList n ->
6114                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6115                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6116              | Bool n ->
6117                  pr "  args.%s = %s;\n" n n
6118              | Int n ->
6119                  pr "  args.%s = %s;\n" n n
6120              | Int64 n ->
6121                  pr "  args.%s = %s;\n" n n
6122              | FileIn _ | FileOut _ -> ()
6123              | BufferIn n ->
6124                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6125                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6126                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6127                    shortname;
6128                  pr "    guestfs___end_busy (g);\n";
6129                  pr "    return %s;\n" error_code;
6130                  pr "  }\n";
6131                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6132                  pr "  args.%s.%s_len = %s_size;\n" n n n
6133            ) args;
6134            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6135              (String.uppercase shortname);
6136            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6137              name;
6138       );
6139       pr "  if (serial == -1) {\n";
6140       pr "    guestfs___end_busy (g);\n";
6141       pr "    return %s;\n" error_code;
6142       pr "  }\n";
6143       pr "\n";
6144
6145       (* Send any additional files (FileIn) requested. *)
6146       let need_read_reply_label = ref false in
6147       List.iter (
6148         function
6149         | FileIn n ->
6150             pr "  r = guestfs___send_file (g, %s);\n" n;
6151             pr "  if (r == -1) {\n";
6152             pr "    guestfs___end_busy (g);\n";
6153             pr "    return %s;\n" error_code;
6154             pr "  }\n";
6155             pr "  if (r == -2) /* daemon cancelled */\n";
6156             pr "    goto read_reply;\n";
6157             need_read_reply_label := true;
6158             pr "\n";
6159         | _ -> ()
6160       ) (snd style);
6161
6162       (* Wait for the reply from the remote end. *)
6163       if !need_read_reply_label then pr " read_reply:\n";
6164       pr "  memset (&hdr, 0, sizeof hdr);\n";
6165       pr "  memset (&err, 0, sizeof err);\n";
6166       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6167       pr "\n";
6168       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6169       if not has_ret then
6170         pr "NULL, NULL"
6171       else
6172         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6173       pr ");\n";
6174
6175       pr "  if (r == -1) {\n";
6176       pr "    guestfs___end_busy (g);\n";
6177       pr "    return %s;\n" error_code;
6178       pr "  }\n";
6179       pr "\n";
6180
6181       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6182         (String.uppercase shortname);
6183       pr "    guestfs___end_busy (g);\n";
6184       pr "    return %s;\n" error_code;
6185       pr "  }\n";
6186       pr "\n";
6187
6188       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6189       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6190       pr "    free (err.error_message);\n";
6191       pr "    guestfs___end_busy (g);\n";
6192       pr "    return %s;\n" error_code;
6193       pr "  }\n";
6194       pr "\n";
6195
6196       (* Expecting to receive further files (FileOut)? *)
6197       List.iter (
6198         function
6199         | FileOut n ->
6200             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6201             pr "    guestfs___end_busy (g);\n";
6202             pr "    return %s;\n" error_code;
6203             pr "  }\n";
6204             pr "\n";
6205         | _ -> ()
6206       ) (snd style);
6207
6208       pr "  guestfs___end_busy (g);\n";
6209
6210       (match fst style with
6211        | RErr -> pr "  return 0;\n"
6212        | RInt n | RInt64 n | RBool n ->
6213            pr "  return ret.%s;\n" n
6214        | RConstString _ | RConstOptString _ ->
6215            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6216        | RString n ->
6217            pr "  return ret.%s; /* caller will free */\n" n
6218        | RStringList n | RHashtable n ->
6219            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6220            pr "  ret.%s.%s_val =\n" n n;
6221            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6222            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6223              n n;
6224            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6225            pr "  return ret.%s.%s_val;\n" n n
6226        | RStruct (n, _) ->
6227            pr "  /* caller will free this */\n";
6228            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6229        | RStructList (n, _) ->
6230            pr "  /* caller will free this */\n";
6231            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6232        | RBufferOut n ->
6233            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6234            pr "   * _val might be NULL here.  To make the API saner for\n";
6235            pr "   * callers, we turn this case into a unique pointer (using\n";
6236            pr "   * malloc(1)).\n";
6237            pr "   */\n";
6238            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6239            pr "    *size_r = ret.%s.%s_len;\n" n n;
6240            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6241            pr "  } else {\n";
6242            pr "    free (ret.%s.%s_val);\n" n n;
6243            pr "    char *p = safe_malloc (g, 1);\n";
6244            pr "    *size_r = ret.%s.%s_len;\n" n n;
6245            pr "    return p;\n";
6246            pr "  }\n";
6247       );
6248
6249       pr "}\n\n"
6250   ) daemon_functions;
6251
6252   (* Functions to free structures. *)
6253   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6254   pr " * structure format is identical to the XDR format.  See note in\n";
6255   pr " * generator.ml.\n";
6256   pr " */\n";
6257   pr "\n";
6258
6259   List.iter (
6260     fun (typ, _) ->
6261       pr "void\n";
6262       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6263       pr "{\n";
6264       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6265       pr "  free (x);\n";
6266       pr "}\n";
6267       pr "\n";
6268
6269       pr "void\n";
6270       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6271       pr "{\n";
6272       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6273       pr "  free (x);\n";
6274       pr "}\n";
6275       pr "\n";
6276
6277   ) structs;
6278
6279 (* Generate daemon/actions.h. *)
6280 and generate_daemon_actions_h () =
6281   generate_header CStyle GPLv2plus;
6282
6283   pr "#include \"../src/guestfs_protocol.h\"\n";
6284   pr "\n";
6285
6286   List.iter (
6287     fun (name, style, _, _, _, _, _) ->
6288       generate_prototype
6289         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6290         name style;
6291   ) daemon_functions
6292
6293 (* Generate the linker script which controls the visibility of
6294  * symbols in the public ABI and ensures no other symbols get
6295  * exported accidentally.
6296  *)
6297 and generate_linker_script () =
6298   generate_header HashStyle GPLv2plus;
6299
6300   let globals = [
6301     "guestfs_create";
6302     "guestfs_close";
6303     "guestfs_get_error_handler";
6304     "guestfs_get_out_of_memory_handler";
6305     "guestfs_last_error";
6306     "guestfs_set_error_handler";
6307     "guestfs_set_launch_done_callback";
6308     "guestfs_set_log_message_callback";
6309     "guestfs_set_out_of_memory_handler";
6310     "guestfs_set_subprocess_quit_callback";
6311
6312     (* Unofficial parts of the API: the bindings code use these
6313      * functions, so it is useful to export them.
6314      *)
6315     "guestfs_safe_calloc";
6316     "guestfs_safe_malloc";
6317   ] in
6318   let functions =
6319     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6320       all_functions in
6321   let structs =
6322     List.concat (
6323       List.map (fun (typ, _) ->
6324                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6325         structs
6326     ) in
6327   let globals = List.sort compare (globals @ functions @ structs) in
6328
6329   pr "{\n";
6330   pr "    global:\n";
6331   List.iter (pr "        %s;\n") globals;
6332   pr "\n";
6333
6334   pr "    local:\n";
6335   pr "        *;\n";
6336   pr "};\n"
6337
6338 (* Generate the server-side stubs. *)
6339 and generate_daemon_actions () =
6340   generate_header CStyle GPLv2plus;
6341
6342   pr "#include <config.h>\n";
6343   pr "\n";
6344   pr "#include <stdio.h>\n";
6345   pr "#include <stdlib.h>\n";
6346   pr "#include <string.h>\n";
6347   pr "#include <inttypes.h>\n";
6348   pr "#include <rpc/types.h>\n";
6349   pr "#include <rpc/xdr.h>\n";
6350   pr "\n";
6351   pr "#include \"daemon.h\"\n";
6352   pr "#include \"c-ctype.h\"\n";
6353   pr "#include \"../src/guestfs_protocol.h\"\n";
6354   pr "#include \"actions.h\"\n";
6355   pr "\n";
6356
6357   List.iter (
6358     fun (name, style, _, _, _, _, _) ->
6359       (* Generate server-side stubs. *)
6360       pr "static void %s_stub (XDR *xdr_in)\n" name;
6361       pr "{\n";
6362       let error_code =
6363         match fst style with
6364         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6365         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6366         | RBool _ -> pr "  int r;\n"; "-1"
6367         | RConstString _ | RConstOptString _ ->
6368             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6369         | RString _ -> pr "  char *r;\n"; "NULL"
6370         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6371         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6372         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6373         | RBufferOut _ ->
6374             pr "  size_t size = 1;\n";
6375             pr "  char *r;\n";
6376             "NULL" in
6377
6378       (match snd style with
6379        | [] -> ()
6380        | args ->
6381            pr "  struct guestfs_%s_args args;\n" name;
6382            List.iter (
6383              function
6384              | Device n | Dev_or_Path n
6385              | Pathname n
6386              | String n -> ()
6387              | OptString n -> pr "  char *%s;\n" n
6388              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6389              | Bool n -> pr "  int %s;\n" n
6390              | Int n -> pr "  int %s;\n" n
6391              | Int64 n -> pr "  int64_t %s;\n" n
6392              | FileIn _ | FileOut _ -> ()
6393              | BufferIn n ->
6394                  pr "  const char *%s;\n" n;
6395                  pr "  size_t %s_size;\n" n
6396            ) args
6397       );
6398       pr "\n";
6399
6400       let is_filein =
6401         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6402
6403       (match snd style with
6404        | [] -> ()
6405        | args ->
6406            pr "  memset (&args, 0, sizeof args);\n";
6407            pr "\n";
6408            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6409            if is_filein then
6410              pr "    if (cancel_receive () != -2)\n";
6411            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6412            pr "    goto done;\n";
6413            pr "  }\n";
6414            let pr_args n =
6415              pr "  char *%s = args.%s;\n" n n
6416            in
6417            let pr_list_handling_code n =
6418              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6419              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6420              pr "  if (%s == NULL) {\n" n;
6421              if is_filein then
6422                pr "    if (cancel_receive () != -2)\n";
6423              pr "      reply_with_perror (\"realloc\");\n";
6424              pr "    goto done;\n";
6425              pr "  }\n";
6426              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6427              pr "  args.%s.%s_val = %s;\n" n n n;
6428            in
6429            List.iter (
6430              function
6431              | Pathname n ->
6432                  pr_args n;
6433                  pr "  ABS_PATH (%s, %s, goto done);\n"
6434                    n (if is_filein then "cancel_receive ()" else "0");
6435              | Device n ->
6436                  pr_args n;
6437                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6438                    n (if is_filein then "cancel_receive ()" else "0");
6439              | Dev_or_Path n ->
6440                  pr_args n;
6441                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6442                    n (if is_filein then "cancel_receive ()" else "0");
6443              | String n -> pr_args n
6444              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6445              | StringList n ->
6446                  pr_list_handling_code n;
6447              | DeviceList n ->
6448                  pr_list_handling_code n;
6449                  pr "  /* Ensure that each is a device,\n";
6450                  pr "   * and perform device name translation. */\n";
6451                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6452                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6453                    (if is_filein then "cancel_receive ()" else "0");
6454                  pr "  }\n";
6455              | Bool n -> pr "  %s = args.%s;\n" n n
6456              | Int n -> pr "  %s = args.%s;\n" n n
6457              | Int64 n -> pr "  %s = args.%s;\n" n n
6458              | FileIn _ | FileOut _ -> ()
6459              | BufferIn n ->
6460                  pr "  %s = args.%s.%s_val;\n" n n n;
6461                  pr "  %s_size = args.%s.%s_len;\n" n n n
6462            ) args;
6463            pr "\n"
6464       );
6465
6466       (* this is used at least for do_equal *)
6467       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6468         (* Emit NEED_ROOT just once, even when there are two or
6469            more Pathname args *)
6470         pr "  NEED_ROOT (%s, goto done);\n"
6471           (if is_filein then "cancel_receive ()" else "0");
6472       );
6473
6474       (* Don't want to call the impl with any FileIn or FileOut
6475        * parameters, since these go "outside" the RPC protocol.
6476        *)
6477       let args' =
6478         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6479           (snd style) in
6480       pr "  r = do_%s " name;
6481       generate_c_call_args (fst style, args');
6482       pr ";\n";
6483
6484       (match fst style with
6485        | RErr | RInt _ | RInt64 _ | RBool _
6486        | RConstString _ | RConstOptString _
6487        | RString _ | RStringList _ | RHashtable _
6488        | RStruct (_, _) | RStructList (_, _) ->
6489            pr "  if (r == %s)\n" error_code;
6490            pr "    /* do_%s has already called reply_with_error */\n" name;
6491            pr "    goto done;\n";
6492            pr "\n"
6493        | RBufferOut _ ->
6494            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6495            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6496            pr "   */\n";
6497            pr "  if (size == 1 && r == %s)\n" error_code;
6498            pr "    /* do_%s has already called reply_with_error */\n" name;
6499            pr "    goto done;\n";
6500            pr "\n"
6501       );
6502
6503       (* If there are any FileOut parameters, then the impl must
6504        * send its own reply.
6505        *)
6506       let no_reply =
6507         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6508       if no_reply then
6509         pr "  /* do_%s has already sent a reply */\n" name
6510       else (
6511         match fst style with
6512         | RErr -> pr "  reply (NULL, NULL);\n"
6513         | RInt n | RInt64 n | RBool n ->
6514             pr "  struct guestfs_%s_ret ret;\n" name;
6515             pr "  ret.%s = r;\n" n;
6516             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6517               name
6518         | RConstString _ | RConstOptString _ ->
6519             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6520         | RString n ->
6521             pr "  struct guestfs_%s_ret ret;\n" name;
6522             pr "  ret.%s = r;\n" n;
6523             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6524               name;
6525             pr "  free (r);\n"
6526         | RStringList n | RHashtable n ->
6527             pr "  struct guestfs_%s_ret ret;\n" name;
6528             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6529             pr "  ret.%s.%s_val = r;\n" n n;
6530             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6531               name;
6532             pr "  free_strings (r);\n"
6533         | RStruct (n, _) ->
6534             pr "  struct guestfs_%s_ret ret;\n" name;
6535             pr "  ret.%s = *r;\n" n;
6536             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6537               name;
6538             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6539               name
6540         | RStructList (n, _) ->
6541             pr "  struct guestfs_%s_ret ret;\n" name;
6542             pr "  ret.%s = *r;\n" n;
6543             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6544               name;
6545             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6546               name
6547         | RBufferOut n ->
6548             pr "  struct guestfs_%s_ret ret;\n" name;
6549             pr "  ret.%s.%s_val = r;\n" n n;
6550             pr "  ret.%s.%s_len = size;\n" n n;
6551             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6552               name;
6553             pr "  free (r);\n"
6554       );
6555
6556       (* Free the args. *)
6557       pr "done:\n";
6558       (match snd style with
6559        | [] -> ()
6560        | _ ->
6561            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6562              name
6563       );
6564       pr "  return;\n";
6565       pr "}\n\n";
6566   ) daemon_functions;
6567
6568   (* Dispatch function. *)
6569   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6570   pr "{\n";
6571   pr "  switch (proc_nr) {\n";
6572
6573   List.iter (
6574     fun (name, style, _, _, _, _, _) ->
6575       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6576       pr "      %s_stub (xdr_in);\n" name;
6577       pr "      break;\n"
6578   ) daemon_functions;
6579
6580   pr "    default:\n";
6581   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";
6582   pr "  }\n";
6583   pr "}\n";
6584   pr "\n";
6585
6586   (* LVM columns and tokenization functions. *)
6587   (* XXX This generates crap code.  We should rethink how we
6588    * do this parsing.
6589    *)
6590   List.iter (
6591     function
6592     | typ, cols ->
6593         pr "static const char *lvm_%s_cols = \"%s\";\n"
6594           typ (String.concat "," (List.map fst cols));
6595         pr "\n";
6596
6597         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6598         pr "{\n";
6599         pr "  char *tok, *p, *next;\n";
6600         pr "  int i, j;\n";
6601         pr "\n";
6602         (*
6603           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6604           pr "\n";
6605         *)
6606         pr "  if (!str) {\n";
6607         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6608         pr "    return -1;\n";
6609         pr "  }\n";
6610         pr "  if (!*str || c_isspace (*str)) {\n";
6611         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6612         pr "    return -1;\n";
6613         pr "  }\n";
6614         pr "  tok = str;\n";
6615         List.iter (
6616           fun (name, coltype) ->
6617             pr "  if (!tok) {\n";
6618             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6619             pr "    return -1;\n";
6620             pr "  }\n";
6621             pr "  p = strchrnul (tok, ',');\n";
6622             pr "  if (*p) next = p+1; else next = NULL;\n";
6623             pr "  *p = '\\0';\n";
6624             (match coltype with
6625              | FString ->
6626                  pr "  r->%s = strdup (tok);\n" name;
6627                  pr "  if (r->%s == NULL) {\n" name;
6628                  pr "    perror (\"strdup\");\n";
6629                  pr "    return -1;\n";
6630                  pr "  }\n"
6631              | FUUID ->
6632                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6633                  pr "    if (tok[j] == '\\0') {\n";
6634                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6635                  pr "      return -1;\n";
6636                  pr "    } else if (tok[j] != '-')\n";
6637                  pr "      r->%s[i++] = tok[j];\n" name;
6638                  pr "  }\n";
6639              | FBytes ->
6640                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6641                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6642                  pr "    return -1;\n";
6643                  pr "  }\n";
6644              | FInt64 ->
6645                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6646                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6647                  pr "    return -1;\n";
6648                  pr "  }\n";
6649              | FOptPercent ->
6650                  pr "  if (tok[0] == '\\0')\n";
6651                  pr "    r->%s = -1;\n" name;
6652                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6653                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6654                  pr "    return -1;\n";
6655                  pr "  }\n";
6656              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6657                  assert false (* can never be an LVM column *)
6658             );
6659             pr "  tok = next;\n";
6660         ) cols;
6661
6662         pr "  if (tok != NULL) {\n";
6663         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6664         pr "    return -1;\n";
6665         pr "  }\n";
6666         pr "  return 0;\n";
6667         pr "}\n";
6668         pr "\n";
6669
6670         pr "guestfs_int_lvm_%s_list *\n" typ;
6671         pr "parse_command_line_%ss (void)\n" typ;
6672         pr "{\n";
6673         pr "  char *out, *err;\n";
6674         pr "  char *p, *pend;\n";
6675         pr "  int r, i;\n";
6676         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6677         pr "  void *newp;\n";
6678         pr "\n";
6679         pr "  ret = malloc (sizeof *ret);\n";
6680         pr "  if (!ret) {\n";
6681         pr "    reply_with_perror (\"malloc\");\n";
6682         pr "    return NULL;\n";
6683         pr "  }\n";
6684         pr "\n";
6685         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6686         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6687         pr "\n";
6688         pr "  r = command (&out, &err,\n";
6689         pr "           \"lvm\", \"%ss\",\n" typ;
6690         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6691         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6692         pr "  if (r == -1) {\n";
6693         pr "    reply_with_error (\"%%s\", err);\n";
6694         pr "    free (out);\n";
6695         pr "    free (err);\n";
6696         pr "    free (ret);\n";
6697         pr "    return NULL;\n";
6698         pr "  }\n";
6699         pr "\n";
6700         pr "  free (err);\n";
6701         pr "\n";
6702         pr "  /* Tokenize each line of the output. */\n";
6703         pr "  p = out;\n";
6704         pr "  i = 0;\n";
6705         pr "  while (p) {\n";
6706         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6707         pr "    if (pend) {\n";
6708         pr "      *pend = '\\0';\n";
6709         pr "      pend++;\n";
6710         pr "    }\n";
6711         pr "\n";
6712         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6713         pr "      p++;\n";
6714         pr "\n";
6715         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6716         pr "      p = pend;\n";
6717         pr "      continue;\n";
6718         pr "    }\n";
6719         pr "\n";
6720         pr "    /* Allocate some space to store this next entry. */\n";
6721         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6722         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6723         pr "    if (newp == NULL) {\n";
6724         pr "      reply_with_perror (\"realloc\");\n";
6725         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6726         pr "      free (ret);\n";
6727         pr "      free (out);\n";
6728         pr "      return NULL;\n";
6729         pr "    }\n";
6730         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6731         pr "\n";
6732         pr "    /* Tokenize the next entry. */\n";
6733         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6734         pr "    if (r == -1) {\n";
6735         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6736         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6737         pr "      free (ret);\n";
6738         pr "      free (out);\n";
6739         pr "      return NULL;\n";
6740         pr "    }\n";
6741         pr "\n";
6742         pr "    ++i;\n";
6743         pr "    p = pend;\n";
6744         pr "  }\n";
6745         pr "\n";
6746         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6747         pr "\n";
6748         pr "  free (out);\n";
6749         pr "  return ret;\n";
6750         pr "}\n"
6751
6752   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6753
6754 (* Generate a list of function names, for debugging in the daemon.. *)
6755 and generate_daemon_names () =
6756   generate_header CStyle GPLv2plus;
6757
6758   pr "#include <config.h>\n";
6759   pr "\n";
6760   pr "#include \"daemon.h\"\n";
6761   pr "\n";
6762
6763   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6764   pr "const char *function_names[] = {\n";
6765   List.iter (
6766     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6767   ) daemon_functions;
6768   pr "};\n";
6769
6770 (* Generate the optional groups for the daemon to implement
6771  * guestfs_available.
6772  *)
6773 and generate_daemon_optgroups_c () =
6774   generate_header CStyle GPLv2plus;
6775
6776   pr "#include <config.h>\n";
6777   pr "\n";
6778   pr "#include \"daemon.h\"\n";
6779   pr "#include \"optgroups.h\"\n";
6780   pr "\n";
6781
6782   pr "struct optgroup optgroups[] = {\n";
6783   List.iter (
6784     fun (group, _) ->
6785       pr "  { \"%s\", optgroup_%s_available },\n" group group
6786   ) optgroups;
6787   pr "  { NULL, NULL }\n";
6788   pr "};\n"
6789
6790 and generate_daemon_optgroups_h () =
6791   generate_header CStyle GPLv2plus;
6792
6793   List.iter (
6794     fun (group, _) ->
6795       pr "extern int optgroup_%s_available (void);\n" group
6796   ) optgroups
6797
6798 (* Generate the tests. *)
6799 and generate_tests () =
6800   generate_header CStyle GPLv2plus;
6801
6802   pr "\
6803 #include <stdio.h>
6804 #include <stdlib.h>
6805 #include <string.h>
6806 #include <unistd.h>
6807 #include <sys/types.h>
6808 #include <fcntl.h>
6809
6810 #include \"guestfs.h\"
6811 #include \"guestfs-internal.h\"
6812
6813 static guestfs_h *g;
6814 static int suppress_error = 0;
6815
6816 static void print_error (guestfs_h *g, void *data, const char *msg)
6817 {
6818   if (!suppress_error)
6819     fprintf (stderr, \"%%s\\n\", msg);
6820 }
6821
6822 /* FIXME: nearly identical code appears in fish.c */
6823 static void print_strings (char *const *argv)
6824 {
6825   int argc;
6826
6827   for (argc = 0; argv[argc] != NULL; ++argc)
6828     printf (\"\\t%%s\\n\", argv[argc]);
6829 }
6830
6831 /*
6832 static void print_table (char const *const *argv)
6833 {
6834   int i;
6835
6836   for (i = 0; argv[i] != NULL; i += 2)
6837     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6838 }
6839 */
6840
6841 ";
6842
6843   (* Generate a list of commands which are not tested anywhere. *)
6844   pr "static void no_test_warnings (void)\n";
6845   pr "{\n";
6846
6847   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6848   List.iter (
6849     fun (_, _, _, _, tests, _, _) ->
6850       let tests = filter_map (
6851         function
6852         | (_, (Always|If _|Unless _), test) -> Some test
6853         | (_, Disabled, _) -> None
6854       ) tests in
6855       let seq = List.concat (List.map seq_of_test tests) in
6856       let cmds_tested = List.map List.hd seq in
6857       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6858   ) all_functions;
6859
6860   List.iter (
6861     fun (name, _, _, _, _, _, _) ->
6862       if not (Hashtbl.mem hash name) then
6863         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6864   ) all_functions;
6865
6866   pr "}\n";
6867   pr "\n";
6868
6869   (* Generate the actual tests.  Note that we generate the tests
6870    * in reverse order, deliberately, so that (in general) the
6871    * newest tests run first.  This makes it quicker and easier to
6872    * debug them.
6873    *)
6874   let test_names =
6875     List.map (
6876       fun (name, _, _, flags, tests, _, _) ->
6877         mapi (generate_one_test name flags) tests
6878     ) (List.rev all_functions) in
6879   let test_names = List.concat test_names in
6880   let nr_tests = List.length test_names in
6881
6882   pr "\
6883 int main (int argc, char *argv[])
6884 {
6885   char c = 0;
6886   unsigned long int n_failed = 0;
6887   const char *filename;
6888   int fd;
6889   int nr_tests, test_num = 0;
6890
6891   setbuf (stdout, NULL);
6892
6893   no_test_warnings ();
6894
6895   g = guestfs_create ();
6896   if (g == NULL) {
6897     printf (\"guestfs_create FAILED\\n\");
6898     exit (EXIT_FAILURE);
6899   }
6900
6901   guestfs_set_error_handler (g, print_error, NULL);
6902
6903   guestfs_set_path (g, \"../appliance\");
6904
6905   filename = \"test1.img\";
6906   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6907   if (fd == -1) {
6908     perror (filename);
6909     exit (EXIT_FAILURE);
6910   }
6911   if (lseek (fd, %d, SEEK_SET) == -1) {
6912     perror (\"lseek\");
6913     close (fd);
6914     unlink (filename);
6915     exit (EXIT_FAILURE);
6916   }
6917   if (write (fd, &c, 1) == -1) {
6918     perror (\"write\");
6919     close (fd);
6920     unlink (filename);
6921     exit (EXIT_FAILURE);
6922   }
6923   if (close (fd) == -1) {
6924     perror (filename);
6925     unlink (filename);
6926     exit (EXIT_FAILURE);
6927   }
6928   if (guestfs_add_drive (g, filename) == -1) {
6929     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6930     exit (EXIT_FAILURE);
6931   }
6932
6933   filename = \"test2.img\";
6934   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6935   if (fd == -1) {
6936     perror (filename);
6937     exit (EXIT_FAILURE);
6938   }
6939   if (lseek (fd, %d, SEEK_SET) == -1) {
6940     perror (\"lseek\");
6941     close (fd);
6942     unlink (filename);
6943     exit (EXIT_FAILURE);
6944   }
6945   if (write (fd, &c, 1) == -1) {
6946     perror (\"write\");
6947     close (fd);
6948     unlink (filename);
6949     exit (EXIT_FAILURE);
6950   }
6951   if (close (fd) == -1) {
6952     perror (filename);
6953     unlink (filename);
6954     exit (EXIT_FAILURE);
6955   }
6956   if (guestfs_add_drive (g, filename) == -1) {
6957     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6958     exit (EXIT_FAILURE);
6959   }
6960
6961   filename = \"test3.img\";
6962   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6963   if (fd == -1) {
6964     perror (filename);
6965     exit (EXIT_FAILURE);
6966   }
6967   if (lseek (fd, %d, SEEK_SET) == -1) {
6968     perror (\"lseek\");
6969     close (fd);
6970     unlink (filename);
6971     exit (EXIT_FAILURE);
6972   }
6973   if (write (fd, &c, 1) == -1) {
6974     perror (\"write\");
6975     close (fd);
6976     unlink (filename);
6977     exit (EXIT_FAILURE);
6978   }
6979   if (close (fd) == -1) {
6980     perror (filename);
6981     unlink (filename);
6982     exit (EXIT_FAILURE);
6983   }
6984   if (guestfs_add_drive (g, filename) == -1) {
6985     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6986     exit (EXIT_FAILURE);
6987   }
6988
6989   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6990     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6991     exit (EXIT_FAILURE);
6992   }
6993
6994   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6995   alarm (600);
6996
6997   if (guestfs_launch (g) == -1) {
6998     printf (\"guestfs_launch FAILED\\n\");
6999     exit (EXIT_FAILURE);
7000   }
7001
7002   /* Cancel previous alarm. */
7003   alarm (0);
7004
7005   nr_tests = %d;
7006
7007 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7008
7009   iteri (
7010     fun i test_name ->
7011       pr "  test_num++;\n";
7012       pr "  if (guestfs_get_verbose (g))\n";
7013       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7014       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7015       pr "  if (%s () == -1) {\n" test_name;
7016       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7017       pr "    n_failed++;\n";
7018       pr "  }\n";
7019   ) test_names;
7020   pr "\n";
7021
7022   pr "  guestfs_close (g);\n";
7023   pr "  unlink (\"test1.img\");\n";
7024   pr "  unlink (\"test2.img\");\n";
7025   pr "  unlink (\"test3.img\");\n";
7026   pr "\n";
7027
7028   pr "  if (n_failed > 0) {\n";
7029   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7030   pr "    exit (EXIT_FAILURE);\n";
7031   pr "  }\n";
7032   pr "\n";
7033
7034   pr "  exit (EXIT_SUCCESS);\n";
7035   pr "}\n"
7036
7037 and generate_one_test name flags i (init, prereq, test) =
7038   let test_name = sprintf "test_%s_%d" name i in
7039
7040   pr "\
7041 static int %s_skip (void)
7042 {
7043   const char *str;
7044
7045   str = getenv (\"TEST_ONLY\");
7046   if (str)
7047     return strstr (str, \"%s\") == NULL;
7048   str = getenv (\"SKIP_%s\");
7049   if (str && STREQ (str, \"1\")) return 1;
7050   str = getenv (\"SKIP_TEST_%s\");
7051   if (str && STREQ (str, \"1\")) return 1;
7052   return 0;
7053 }
7054
7055 " test_name name (String.uppercase test_name) (String.uppercase name);
7056
7057   (match prereq with
7058    | Disabled | Always -> ()
7059    | If code | Unless code ->
7060        pr "static int %s_prereq (void)\n" test_name;
7061        pr "{\n";
7062        pr "  %s\n" code;
7063        pr "}\n";
7064        pr "\n";
7065   );
7066
7067   pr "\
7068 static int %s (void)
7069 {
7070   if (%s_skip ()) {
7071     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7072     return 0;
7073   }
7074
7075 " test_name test_name test_name;
7076
7077   (* Optional functions should only be tested if the relevant
7078    * support is available in the daemon.
7079    *)
7080   List.iter (
7081     function
7082     | Optional group ->
7083         pr "  {\n";
7084         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7085         pr "    int r;\n";
7086         pr "    suppress_error = 1;\n";
7087         pr "    r = guestfs_available (g, (char **) groups);\n";
7088         pr "    suppress_error = 0;\n";
7089         pr "    if (r == -1) {\n";
7090         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7091         pr "      return 0;\n";
7092         pr "    }\n";
7093         pr "  }\n";
7094     | _ -> ()
7095   ) flags;
7096
7097   (match prereq with
7098    | Disabled ->
7099        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7100    | If _ ->
7101        pr "  if (! %s_prereq ()) {\n" test_name;
7102        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7103        pr "    return 0;\n";
7104        pr "  }\n";
7105        pr "\n";
7106        generate_one_test_body name i test_name init test;
7107    | Unless _ ->
7108        pr "  if (%s_prereq ()) {\n" test_name;
7109        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7110        pr "    return 0;\n";
7111        pr "  }\n";
7112        pr "\n";
7113        generate_one_test_body name i test_name init test;
7114    | Always ->
7115        generate_one_test_body name i test_name init test
7116   );
7117
7118   pr "  return 0;\n";
7119   pr "}\n";
7120   pr "\n";
7121   test_name
7122
7123 and generate_one_test_body name i test_name init test =
7124   (match init with
7125    | InitNone (* XXX at some point, InitNone and InitEmpty became
7126                * folded together as the same thing.  Really we should
7127                * make InitNone do nothing at all, but the tests may
7128                * need to be checked to make sure this is OK.
7129                *)
7130    | InitEmpty ->
7131        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7132        List.iter (generate_test_command_call test_name)
7133          [["blockdev_setrw"; "/dev/sda"];
7134           ["umount_all"];
7135           ["lvm_remove_all"]]
7136    | InitPartition ->
7137        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7138        List.iter (generate_test_command_call test_name)
7139          [["blockdev_setrw"; "/dev/sda"];
7140           ["umount_all"];
7141           ["lvm_remove_all"];
7142           ["part_disk"; "/dev/sda"; "mbr"]]
7143    | InitBasicFS ->
7144        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7145        List.iter (generate_test_command_call test_name)
7146          [["blockdev_setrw"; "/dev/sda"];
7147           ["umount_all"];
7148           ["lvm_remove_all"];
7149           ["part_disk"; "/dev/sda"; "mbr"];
7150           ["mkfs"; "ext2"; "/dev/sda1"];
7151           ["mount_options"; ""; "/dev/sda1"; "/"]]
7152    | InitBasicFSonLVM ->
7153        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7154          test_name;
7155        List.iter (generate_test_command_call test_name)
7156          [["blockdev_setrw"; "/dev/sda"];
7157           ["umount_all"];
7158           ["lvm_remove_all"];
7159           ["part_disk"; "/dev/sda"; "mbr"];
7160           ["pvcreate"; "/dev/sda1"];
7161           ["vgcreate"; "VG"; "/dev/sda1"];
7162           ["lvcreate"; "LV"; "VG"; "8"];
7163           ["mkfs"; "ext2"; "/dev/VG/LV"];
7164           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7165    | InitISOFS ->
7166        pr "  /* InitISOFS for %s */\n" test_name;
7167        List.iter (generate_test_command_call test_name)
7168          [["blockdev_setrw"; "/dev/sda"];
7169           ["umount_all"];
7170           ["lvm_remove_all"];
7171           ["mount_ro"; "/dev/sdd"; "/"]]
7172   );
7173
7174   let get_seq_last = function
7175     | [] ->
7176         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7177           test_name
7178     | seq ->
7179         let seq = List.rev seq in
7180         List.rev (List.tl seq), List.hd seq
7181   in
7182
7183   match test with
7184   | TestRun seq ->
7185       pr "  /* TestRun for %s (%d) */\n" name i;
7186       List.iter (generate_test_command_call test_name) seq
7187   | TestOutput (seq, expected) ->
7188       pr "  /* TestOutput for %s (%d) */\n" name i;
7189       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7190       let seq, last = get_seq_last seq in
7191       let test () =
7192         pr "    if (STRNEQ (r, expected)) {\n";
7193         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7194         pr "      return -1;\n";
7195         pr "    }\n"
7196       in
7197       List.iter (generate_test_command_call test_name) seq;
7198       generate_test_command_call ~test test_name last
7199   | TestOutputList (seq, expected) ->
7200       pr "  /* TestOutputList for %s (%d) */\n" name i;
7201       let seq, last = get_seq_last seq in
7202       let test () =
7203         iteri (
7204           fun i str ->
7205             pr "    if (!r[%d]) {\n" i;
7206             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7207             pr "      print_strings (r);\n";
7208             pr "      return -1;\n";
7209             pr "    }\n";
7210             pr "    {\n";
7211             pr "      const char *expected = \"%s\";\n" (c_quote str);
7212             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7213             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7214             pr "        return -1;\n";
7215             pr "      }\n";
7216             pr "    }\n"
7217         ) expected;
7218         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7219         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7220           test_name;
7221         pr "      print_strings (r);\n";
7222         pr "      return -1;\n";
7223         pr "    }\n"
7224       in
7225       List.iter (generate_test_command_call test_name) seq;
7226       generate_test_command_call ~test test_name last
7227   | TestOutputListOfDevices (seq, expected) ->
7228       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7229       let seq, last = get_seq_last seq in
7230       let test () =
7231         iteri (
7232           fun i str ->
7233             pr "    if (!r[%d]) {\n" i;
7234             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7235             pr "      print_strings (r);\n";
7236             pr "      return -1;\n";
7237             pr "    }\n";
7238             pr "    {\n";
7239             pr "      const char *expected = \"%s\";\n" (c_quote str);
7240             pr "      r[%d][5] = 's';\n" i;
7241             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7242             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7243             pr "        return -1;\n";
7244             pr "      }\n";
7245             pr "    }\n"
7246         ) expected;
7247         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7248         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7249           test_name;
7250         pr "      print_strings (r);\n";
7251         pr "      return -1;\n";
7252         pr "    }\n"
7253       in
7254       List.iter (generate_test_command_call test_name) seq;
7255       generate_test_command_call ~test test_name last
7256   | TestOutputInt (seq, expected) ->
7257       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7258       let seq, last = get_seq_last seq in
7259       let test () =
7260         pr "    if (r != %d) {\n" expected;
7261         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7262           test_name expected;
7263         pr "               (int) r);\n";
7264         pr "      return -1;\n";
7265         pr "    }\n"
7266       in
7267       List.iter (generate_test_command_call test_name) seq;
7268       generate_test_command_call ~test test_name last
7269   | TestOutputIntOp (seq, op, expected) ->
7270       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7271       let seq, last = get_seq_last seq in
7272       let test () =
7273         pr "    if (! (r %s %d)) {\n" op expected;
7274         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7275           test_name op expected;
7276         pr "               (int) r);\n";
7277         pr "      return -1;\n";
7278         pr "    }\n"
7279       in
7280       List.iter (generate_test_command_call test_name) seq;
7281       generate_test_command_call ~test test_name last
7282   | TestOutputTrue seq ->
7283       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7284       let seq, last = get_seq_last seq in
7285       let test () =
7286         pr "    if (!r) {\n";
7287         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7288           test_name;
7289         pr "      return -1;\n";
7290         pr "    }\n"
7291       in
7292       List.iter (generate_test_command_call test_name) seq;
7293       generate_test_command_call ~test test_name last
7294   | TestOutputFalse seq ->
7295       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7296       let seq, last = get_seq_last seq in
7297       let test () =
7298         pr "    if (r) {\n";
7299         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7300           test_name;
7301         pr "      return -1;\n";
7302         pr "    }\n"
7303       in
7304       List.iter (generate_test_command_call test_name) seq;
7305       generate_test_command_call ~test test_name last
7306   | TestOutputLength (seq, expected) ->
7307       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7308       let seq, last = get_seq_last seq in
7309       let test () =
7310         pr "    int j;\n";
7311         pr "    for (j = 0; j < %d; ++j)\n" expected;
7312         pr "      if (r[j] == NULL) {\n";
7313         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7314           test_name;
7315         pr "        print_strings (r);\n";
7316         pr "        return -1;\n";
7317         pr "      }\n";
7318         pr "    if (r[j] != NULL) {\n";
7319         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7320           test_name;
7321         pr "      print_strings (r);\n";
7322         pr "      return -1;\n";
7323         pr "    }\n"
7324       in
7325       List.iter (generate_test_command_call test_name) seq;
7326       generate_test_command_call ~test test_name last
7327   | TestOutputBuffer (seq, expected) ->
7328       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7329       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7330       let seq, last = get_seq_last seq in
7331       let len = String.length expected in
7332       let test () =
7333         pr "    if (size != %d) {\n" len;
7334         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7335         pr "      return -1;\n";
7336         pr "    }\n";
7337         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7338         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7339         pr "      return -1;\n";
7340         pr "    }\n"
7341       in
7342       List.iter (generate_test_command_call test_name) seq;
7343       generate_test_command_call ~test test_name last
7344   | TestOutputStruct (seq, checks) ->
7345       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7346       let seq, last = get_seq_last seq in
7347       let test () =
7348         List.iter (
7349           function
7350           | CompareWithInt (field, expected) ->
7351               pr "    if (r->%s != %d) {\n" field expected;
7352               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7353                 test_name field expected;
7354               pr "               (int) r->%s);\n" field;
7355               pr "      return -1;\n";
7356               pr "    }\n"
7357           | CompareWithIntOp (field, op, expected) ->
7358               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7359               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7360                 test_name field op expected;
7361               pr "               (int) r->%s);\n" field;
7362               pr "      return -1;\n";
7363               pr "    }\n"
7364           | CompareWithString (field, expected) ->
7365               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7366               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7367                 test_name field expected;
7368               pr "               r->%s);\n" field;
7369               pr "      return -1;\n";
7370               pr "    }\n"
7371           | CompareFieldsIntEq (field1, field2) ->
7372               pr "    if (r->%s != r->%s) {\n" field1 field2;
7373               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7374                 test_name field1 field2;
7375               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7376               pr "      return -1;\n";
7377               pr "    }\n"
7378           | CompareFieldsStrEq (field1, field2) ->
7379               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7380               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7381                 test_name field1 field2;
7382               pr "               r->%s, r->%s);\n" field1 field2;
7383               pr "      return -1;\n";
7384               pr "    }\n"
7385         ) checks
7386       in
7387       List.iter (generate_test_command_call test_name) seq;
7388       generate_test_command_call ~test test_name last
7389   | TestLastFail seq ->
7390       pr "  /* TestLastFail for %s (%d) */\n" name i;
7391       let seq, last = get_seq_last seq in
7392       List.iter (generate_test_command_call test_name) seq;
7393       generate_test_command_call test_name ~expect_error:true last
7394
7395 (* Generate the code to run a command, leaving the result in 'r'.
7396  * If you expect to get an error then you should set expect_error:true.
7397  *)
7398 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7399   match cmd with
7400   | [] -> assert false
7401   | name :: args ->
7402       (* Look up the command to find out what args/ret it has. *)
7403       let style =
7404         try
7405           let _, style, _, _, _, _, _ =
7406             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7407           style
7408         with Not_found ->
7409           failwithf "%s: in test, command %s was not found" test_name name in
7410
7411       if List.length (snd style) <> List.length args then
7412         failwithf "%s: in test, wrong number of args given to %s"
7413           test_name name;
7414
7415       pr "  {\n";
7416
7417       List.iter (
7418         function
7419         | OptString n, "NULL" -> ()
7420         | Pathname n, arg
7421         | Device n, arg
7422         | Dev_or_Path n, arg
7423         | String n, arg
7424         | OptString n, arg ->
7425             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7426         | BufferIn n, arg ->
7427             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7428             pr "    size_t %s_size = %d;\n" n (String.length arg)
7429         | Int _, _
7430         | Int64 _, _
7431         | Bool _, _
7432         | FileIn _, _ | FileOut _, _ -> ()
7433         | StringList n, "" | DeviceList n, "" ->
7434             pr "    const char *const %s[1] = { NULL };\n" n
7435         | StringList n, arg | DeviceList n, arg ->
7436             let strs = string_split " " arg in
7437             iteri (
7438               fun i str ->
7439                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7440             ) strs;
7441             pr "    const char *const %s[] = {\n" n;
7442             iteri (
7443               fun i _ -> pr "      %s_%d,\n" n i
7444             ) strs;
7445             pr "      NULL\n";
7446             pr "    };\n";
7447       ) (List.combine (snd style) args);
7448
7449       let error_code =
7450         match fst style with
7451         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7452         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7453         | RConstString _ | RConstOptString _ ->
7454             pr "    const char *r;\n"; "NULL"
7455         | RString _ -> pr "    char *r;\n"; "NULL"
7456         | RStringList _ | RHashtable _ ->
7457             pr "    char **r;\n";
7458             pr "    int i;\n";
7459             "NULL"
7460         | RStruct (_, typ) ->
7461             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7462         | RStructList (_, typ) ->
7463             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7464         | RBufferOut _ ->
7465             pr "    char *r;\n";
7466             pr "    size_t size;\n";
7467             "NULL" in
7468
7469       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7470       pr "    r = guestfs_%s (g" name;
7471
7472       (* Generate the parameters. *)
7473       List.iter (
7474         function
7475         | OptString _, "NULL" -> pr ", NULL"
7476         | Pathname n, _
7477         | Device n, _ | Dev_or_Path n, _
7478         | String n, _
7479         | OptString n, _ ->
7480             pr ", %s" n
7481         | BufferIn n, _ ->
7482             pr ", %s, %s_size" n n
7483         | FileIn _, arg | FileOut _, arg ->
7484             pr ", \"%s\"" (c_quote arg)
7485         | StringList n, _ | DeviceList n, _ ->
7486             pr ", (char **) %s" n
7487         | Int _, arg ->
7488             let i =
7489               try int_of_string arg
7490               with Failure "int_of_string" ->
7491                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7492             pr ", %d" i
7493         | Int64 _, arg ->
7494             let i =
7495               try Int64.of_string arg
7496               with Failure "int_of_string" ->
7497                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7498             pr ", %Ld" i
7499         | Bool _, arg ->
7500             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7501       ) (List.combine (snd style) args);
7502
7503       (match fst style with
7504        | RBufferOut _ -> pr ", &size"
7505        | _ -> ()
7506       );
7507
7508       pr ");\n";
7509
7510       if not expect_error then
7511         pr "    if (r == %s)\n" error_code
7512       else
7513         pr "    if (r != %s)\n" error_code;
7514       pr "      return -1;\n";
7515
7516       (* Insert the test code. *)
7517       (match test with
7518        | None -> ()
7519        | Some f -> f ()
7520       );
7521
7522       (match fst style with
7523        | RErr | RInt _ | RInt64 _ | RBool _
7524        | RConstString _ | RConstOptString _ -> ()
7525        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7526        | RStringList _ | RHashtable _ ->
7527            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7528            pr "      free (r[i]);\n";
7529            pr "    free (r);\n"
7530        | RStruct (_, typ) ->
7531            pr "    guestfs_free_%s (r);\n" typ
7532        | RStructList (_, typ) ->
7533            pr "    guestfs_free_%s_list (r);\n" typ
7534       );
7535
7536       pr "  }\n"
7537
7538 and c_quote str =
7539   let str = replace_str str "\r" "\\r" in
7540   let str = replace_str str "\n" "\\n" in
7541   let str = replace_str str "\t" "\\t" in
7542   let str = replace_str str "\000" "\\0" in
7543   str
7544
7545 (* Generate a lot of different functions for guestfish. *)
7546 and generate_fish_cmds () =
7547   generate_header CStyle GPLv2plus;
7548
7549   let all_functions =
7550     List.filter (
7551       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7552     ) all_functions in
7553   let all_functions_sorted =
7554     List.filter (
7555       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7556     ) all_functions_sorted in
7557
7558   pr "#include <config.h>\n";
7559   pr "\n";
7560   pr "#include <stdio.h>\n";
7561   pr "#include <stdlib.h>\n";
7562   pr "#include <string.h>\n";
7563   pr "#include <inttypes.h>\n";
7564   pr "\n";
7565   pr "#include <guestfs.h>\n";
7566   pr "#include \"c-ctype.h\"\n";
7567   pr "#include \"full-write.h\"\n";
7568   pr "#include \"xstrtol.h\"\n";
7569   pr "#include \"fish.h\"\n";
7570   pr "\n";
7571   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7572   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7573   pr "\n";
7574
7575   (* list_commands function, which implements guestfish -h *)
7576   pr "void list_commands (void)\n";
7577   pr "{\n";
7578   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7579   pr "  list_builtin_commands ();\n";
7580   List.iter (
7581     fun (name, _, _, flags, _, shortdesc, _) ->
7582       let name = replace_char name '_' '-' in
7583       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7584         name shortdesc
7585   ) all_functions_sorted;
7586   pr "  printf (\"    %%s\\n\",";
7587   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7588   pr "}\n";
7589   pr "\n";
7590
7591   (* display_command function, which implements guestfish -h cmd *)
7592   pr "int display_command (const char *cmd)\n";
7593   pr "{\n";
7594   List.iter (
7595     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7596       let name2 = replace_char name '_' '-' in
7597       let alias =
7598         try find_map (function FishAlias n -> Some n | _ -> None) flags
7599         with Not_found -> name in
7600       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7601       let synopsis =
7602         match snd style with
7603         | [] -> name2
7604         | args ->
7605             sprintf "%s %s"
7606               name2 (String.concat " " (List.map name_of_argt args)) in
7607
7608       let warnings =
7609         if List.mem ProtocolLimitWarning flags then
7610           ("\n\n" ^ protocol_limit_warning)
7611         else "" in
7612
7613       (* For DangerWillRobinson commands, we should probably have
7614        * guestfish prompt before allowing you to use them (especially
7615        * in interactive mode). XXX
7616        *)
7617       let warnings =
7618         warnings ^
7619           if List.mem DangerWillRobinson flags then
7620             ("\n\n" ^ danger_will_robinson)
7621           else "" in
7622
7623       let warnings =
7624         warnings ^
7625           match deprecation_notice flags with
7626           | None -> ""
7627           | Some txt -> "\n\n" ^ txt in
7628
7629       let describe_alias =
7630         if name <> alias then
7631           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7632         else "" in
7633
7634       pr "  if (";
7635       pr "STRCASEEQ (cmd, \"%s\")" name;
7636       if name <> name2 then
7637         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7638       if name <> alias then
7639         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7640       pr ") {\n";
7641       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7642         name2 shortdesc
7643         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7644          "=head1 DESCRIPTION\n\n" ^
7645          longdesc ^ warnings ^ describe_alias);
7646       pr "    return 0;\n";
7647       pr "  }\n";
7648       pr "  else\n"
7649   ) all_functions;
7650   pr "    return display_builtin_command (cmd);\n";
7651   pr "}\n";
7652   pr "\n";
7653
7654   let emit_print_list_function typ =
7655     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7656       typ typ typ;
7657     pr "{\n";
7658     pr "  unsigned int i;\n";
7659     pr "\n";
7660     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7661     pr "    printf (\"[%%d] = {\\n\", i);\n";
7662     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7663     pr "    printf (\"}\\n\");\n";
7664     pr "  }\n";
7665     pr "}\n";
7666     pr "\n";
7667   in
7668
7669   (* print_* functions *)
7670   List.iter (
7671     fun (typ, cols) ->
7672       let needs_i =
7673         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7674
7675       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7676       pr "{\n";
7677       if needs_i then (
7678         pr "  unsigned int i;\n";
7679         pr "\n"
7680       );
7681       List.iter (
7682         function
7683         | name, FString ->
7684             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7685         | name, FUUID ->
7686             pr "  printf (\"%%s%s: \", indent);\n" name;
7687             pr "  for (i = 0; i < 32; ++i)\n";
7688             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7689             pr "  printf (\"\\n\");\n"
7690         | name, FBuffer ->
7691             pr "  printf (\"%%s%s: \", indent);\n" name;
7692             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7693             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7694             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7695             pr "    else\n";
7696             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7697             pr "  printf (\"\\n\");\n"
7698         | name, (FUInt64|FBytes) ->
7699             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7700               name typ name
7701         | name, FInt64 ->
7702             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7703               name typ name
7704         | name, FUInt32 ->
7705             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7706               name typ name
7707         | name, FInt32 ->
7708             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7709               name typ name
7710         | name, FChar ->
7711             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7712               name typ name
7713         | name, FOptPercent ->
7714             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7715               typ name name typ name;
7716             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7717       ) cols;
7718       pr "}\n";
7719       pr "\n";
7720   ) structs;
7721
7722   (* Emit a print_TYPE_list function definition only if that function is used. *)
7723   List.iter (
7724     function
7725     | typ, (RStructListOnly | RStructAndList) ->
7726         (* generate the function for typ *)
7727         emit_print_list_function typ
7728     | typ, _ -> () (* empty *)
7729   ) (rstructs_used_by all_functions);
7730
7731   (* Emit a print_TYPE function definition only if that function is used. *)
7732   List.iter (
7733     function
7734     | typ, (RStructOnly | RStructAndList) ->
7735         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7736         pr "{\n";
7737         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7738         pr "}\n";
7739         pr "\n";
7740     | typ, _ -> () (* empty *)
7741   ) (rstructs_used_by all_functions);
7742
7743   (* run_<action> actions *)
7744   List.iter (
7745     fun (name, style, _, flags, _, _, _) ->
7746       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7747       pr "{\n";
7748       (match fst style with
7749        | RErr
7750        | RInt _
7751        | RBool _ -> pr "  int r;\n"
7752        | RInt64 _ -> pr "  int64_t r;\n"
7753        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7754        | RString _ -> pr "  char *r;\n"
7755        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7756        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7757        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7758        | RBufferOut _ ->
7759            pr "  char *r;\n";
7760            pr "  size_t size;\n";
7761       );
7762       List.iter (
7763         function
7764         | Device n
7765         | String n
7766         | OptString n -> pr "  const char *%s;\n" n
7767         | Pathname n
7768         | Dev_or_Path n
7769         | FileIn n
7770         | FileOut n -> pr "  char *%s;\n" n
7771         | BufferIn n ->
7772             pr "  const char *%s;\n" n;
7773             pr "  size_t %s_size;\n" n
7774         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7775         | Bool n -> pr "  int %s;\n" n
7776         | Int n -> pr "  int %s;\n" n
7777         | Int64 n -> pr "  int64_t %s;\n" n
7778       ) (snd style);
7779
7780       (* Check and convert parameters. *)
7781       let argc_expected = List.length (snd style) in
7782       pr "  if (argc != %d) {\n" argc_expected;
7783       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7784         argc_expected;
7785       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7786       pr "    return -1;\n";
7787       pr "  }\n";
7788
7789       let parse_integer fn fntyp rtyp range name i =
7790         pr "  {\n";
7791         pr "    strtol_error xerr;\n";
7792         pr "    %s r;\n" fntyp;
7793         pr "\n";
7794         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7795         pr "    if (xerr != LONGINT_OK) {\n";
7796         pr "      fprintf (stderr,\n";
7797         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7798         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7799         pr "      return -1;\n";
7800         pr "    }\n";
7801         (match range with
7802          | None -> ()
7803          | Some (min, max, comment) ->
7804              pr "    /* %s */\n" comment;
7805              pr "    if (r < %s || r > %s) {\n" min max;
7806              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7807                name;
7808              pr "      return -1;\n";
7809              pr "    }\n";
7810              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7811         );
7812         pr "    %s = r;\n" name;
7813         pr "  }\n";
7814       in
7815
7816       iteri (
7817         fun i ->
7818           function
7819           | Device name
7820           | String name ->
7821               pr "  %s = argv[%d];\n" name i
7822           | Pathname name
7823           | Dev_or_Path name ->
7824               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7825               pr "  if (%s == NULL) return -1;\n" name
7826           | OptString name ->
7827               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7828                 name i i
7829           | BufferIn name ->
7830               pr "  %s = argv[%d];\n" name i;
7831               pr "  %s_size = strlen (argv[%d]);\n" name i
7832           | FileIn name ->
7833               pr "  %s = file_in (argv[%d]);\n" name i;
7834               pr "  if (%s == NULL) return -1;\n" name
7835           | FileOut name ->
7836               pr "  %s = file_out (argv[%d]);\n" name i;
7837               pr "  if (%s == NULL) return -1;\n" name
7838           | StringList name | DeviceList name ->
7839               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7840               pr "  if (%s == NULL) return -1;\n" name;
7841           | Bool name ->
7842               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7843           | Int name ->
7844               let range =
7845                 let min = "(-(2LL<<30))"
7846                 and max = "((2LL<<30)-1)"
7847                 and comment =
7848                   "The Int type in the generator is a signed 31 bit int." in
7849                 Some (min, max, comment) in
7850               parse_integer "xstrtoll" "long long" "int" range name i
7851           | Int64 name ->
7852               parse_integer "xstrtoll" "long long" "int64_t" None name i
7853       ) (snd style);
7854
7855       (* Call C API function. *)
7856       pr "  r = guestfs_%s " name;
7857       generate_c_call_args ~handle:"g" style;
7858       pr ";\n";
7859
7860       List.iter (
7861         function
7862         | Device name | String name
7863         | OptString name | Bool name
7864         | Int name | Int64 name
7865         | BufferIn name -> ()
7866         | Pathname name | Dev_or_Path name | FileOut name ->
7867             pr "  free (%s);\n" name
7868         | FileIn name ->
7869             pr "  free_file_in (%s);\n" name
7870         | StringList name | DeviceList name ->
7871             pr "  free_strings (%s);\n" name
7872       ) (snd style);
7873
7874       (* Any output flags? *)
7875       let fish_output =
7876         let flags = filter_map (
7877           function FishOutput flag -> Some flag | _ -> None
7878         ) flags in
7879         match flags with
7880         | [] -> None
7881         | [f] -> Some f
7882         | _ ->
7883             failwithf "%s: more than one FishOutput flag is not allowed" name in
7884
7885       (* Check return value for errors and display command results. *)
7886       (match fst style with
7887        | RErr -> pr "  return r;\n"
7888        | RInt _ ->
7889            pr "  if (r == -1) return -1;\n";
7890            (match fish_output with
7891             | None ->
7892                 pr "  printf (\"%%d\\n\", r);\n";
7893             | Some FishOutputOctal ->
7894                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7895             | Some FishOutputHexadecimal ->
7896                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7897            pr "  return 0;\n"
7898        | RInt64 _ ->
7899            pr "  if (r == -1) return -1;\n";
7900            (match fish_output with
7901             | None ->
7902                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7903             | Some FishOutputOctal ->
7904                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7905             | Some FishOutputHexadecimal ->
7906                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7907            pr "  return 0;\n"
7908        | RBool _ ->
7909            pr "  if (r == -1) return -1;\n";
7910            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7911            pr "  return 0;\n"
7912        | RConstString _ ->
7913            pr "  if (r == NULL) return -1;\n";
7914            pr "  printf (\"%%s\\n\", r);\n";
7915            pr "  return 0;\n"
7916        | RConstOptString _ ->
7917            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7918            pr "  return 0;\n"
7919        | RString _ ->
7920            pr "  if (r == NULL) return -1;\n";
7921            pr "  printf (\"%%s\\n\", r);\n";
7922            pr "  free (r);\n";
7923            pr "  return 0;\n"
7924        | RStringList _ ->
7925            pr "  if (r == NULL) return -1;\n";
7926            pr "  print_strings (r);\n";
7927            pr "  free_strings (r);\n";
7928            pr "  return 0;\n"
7929        | RStruct (_, typ) ->
7930            pr "  if (r == NULL) return -1;\n";
7931            pr "  print_%s (r);\n" typ;
7932            pr "  guestfs_free_%s (r);\n" typ;
7933            pr "  return 0;\n"
7934        | RStructList (_, typ) ->
7935            pr "  if (r == NULL) return -1;\n";
7936            pr "  print_%s_list (r);\n" typ;
7937            pr "  guestfs_free_%s_list (r);\n" typ;
7938            pr "  return 0;\n"
7939        | RHashtable _ ->
7940            pr "  if (r == NULL) return -1;\n";
7941            pr "  print_table (r);\n";
7942            pr "  free_strings (r);\n";
7943            pr "  return 0;\n"
7944        | RBufferOut _ ->
7945            pr "  if (r == NULL) return -1;\n";
7946            pr "  if (full_write (1, r, size) != size) {\n";
7947            pr "    perror (\"write\");\n";
7948            pr "    free (r);\n";
7949            pr "    return -1;\n";
7950            pr "  }\n";
7951            pr "  free (r);\n";
7952            pr "  return 0;\n"
7953       );
7954       pr "}\n";
7955       pr "\n"
7956   ) all_functions;
7957
7958   (* run_action function *)
7959   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7960   pr "{\n";
7961   List.iter (
7962     fun (name, _, _, flags, _, _, _) ->
7963       let name2 = replace_char name '_' '-' in
7964       let alias =
7965         try find_map (function FishAlias n -> Some n | _ -> None) flags
7966         with Not_found -> name in
7967       pr "  if (";
7968       pr "STRCASEEQ (cmd, \"%s\")" name;
7969       if name <> name2 then
7970         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7971       if name <> alias then
7972         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7973       pr ")\n";
7974       pr "    return run_%s (cmd, argc, argv);\n" name;
7975       pr "  else\n";
7976   ) all_functions;
7977   pr "    {\n";
7978   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7979   pr "      if (command_num == 1)\n";
7980   pr "        extended_help_message ();\n";
7981   pr "      return -1;\n";
7982   pr "    }\n";
7983   pr "  return 0;\n";
7984   pr "}\n";
7985   pr "\n"
7986
7987 (* Readline completion for guestfish. *)
7988 and generate_fish_completion () =
7989   generate_header CStyle GPLv2plus;
7990
7991   let all_functions =
7992     List.filter (
7993       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7994     ) all_functions in
7995
7996   pr "\
7997 #include <config.h>
7998
7999 #include <stdio.h>
8000 #include <stdlib.h>
8001 #include <string.h>
8002
8003 #ifdef HAVE_LIBREADLINE
8004 #include <readline/readline.h>
8005 #endif
8006
8007 #include \"fish.h\"
8008
8009 #ifdef HAVE_LIBREADLINE
8010
8011 static const char *const commands[] = {
8012   BUILTIN_COMMANDS_FOR_COMPLETION,
8013 ";
8014
8015   (* Get the commands, including the aliases.  They don't need to be
8016    * sorted - the generator() function just does a dumb linear search.
8017    *)
8018   let commands =
8019     List.map (
8020       fun (name, _, _, flags, _, _, _) ->
8021         let name2 = replace_char name '_' '-' in
8022         let alias =
8023           try find_map (function FishAlias n -> Some n | _ -> None) flags
8024           with Not_found -> name in
8025
8026         if name <> alias then [name2; alias] else [name2]
8027     ) all_functions in
8028   let commands = List.flatten commands in
8029
8030   List.iter (pr "  \"%s\",\n") commands;
8031
8032   pr "  NULL
8033 };
8034
8035 static char *
8036 generator (const char *text, int state)
8037 {
8038   static int index, len;
8039   const char *name;
8040
8041   if (!state) {
8042     index = 0;
8043     len = strlen (text);
8044   }
8045
8046   rl_attempted_completion_over = 1;
8047
8048   while ((name = commands[index]) != NULL) {
8049     index++;
8050     if (STRCASEEQLEN (name, text, len))
8051       return strdup (name);
8052   }
8053
8054   return NULL;
8055 }
8056
8057 #endif /* HAVE_LIBREADLINE */
8058
8059 #ifdef HAVE_RL_COMPLETION_MATCHES
8060 #define RL_COMPLETION_MATCHES rl_completion_matches
8061 #else
8062 #ifdef HAVE_COMPLETION_MATCHES
8063 #define RL_COMPLETION_MATCHES completion_matches
8064 #endif
8065 #endif /* else just fail if we don't have either symbol */
8066
8067 char **
8068 do_completion (const char *text, int start, int end)
8069 {
8070   char **matches = NULL;
8071
8072 #ifdef HAVE_LIBREADLINE
8073   rl_completion_append_character = ' ';
8074
8075   if (start == 0)
8076     matches = RL_COMPLETION_MATCHES (text, generator);
8077   else if (complete_dest_paths)
8078     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8079 #endif
8080
8081   return matches;
8082 }
8083 ";
8084
8085 (* Generate the POD documentation for guestfish. *)
8086 and generate_fish_actions_pod () =
8087   let all_functions_sorted =
8088     List.filter (
8089       fun (_, _, _, flags, _, _, _) ->
8090         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8091     ) all_functions_sorted in
8092
8093   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8094
8095   List.iter (
8096     fun (name, style, _, flags, _, _, longdesc) ->
8097       let longdesc =
8098         Str.global_substitute rex (
8099           fun s ->
8100             let sub =
8101               try Str.matched_group 1 s
8102               with Not_found ->
8103                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8104             "C<" ^ replace_char sub '_' '-' ^ ">"
8105         ) longdesc in
8106       let name = replace_char name '_' '-' in
8107       let alias =
8108         try find_map (function FishAlias n -> Some n | _ -> None) flags
8109         with Not_found -> name in
8110
8111       pr "=head2 %s" name;
8112       if name <> alias then
8113         pr " | %s" alias;
8114       pr "\n";
8115       pr "\n";
8116       pr " %s" name;
8117       List.iter (
8118         function
8119         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8120         | OptString n -> pr " %s" n
8121         | StringList n | DeviceList n -> pr " '%s ...'" n
8122         | Bool _ -> pr " true|false"
8123         | Int n -> pr " %s" n
8124         | Int64 n -> pr " %s" n
8125         | FileIn n | FileOut n -> pr " (%s|-)" n
8126         | BufferIn n -> pr " %s" n
8127       ) (snd style);
8128       pr "\n";
8129       pr "\n";
8130       pr "%s\n\n" longdesc;
8131
8132       if List.exists (function FileIn _ | FileOut _ -> true
8133                       | _ -> false) (snd style) then
8134         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8135
8136       if List.mem ProtocolLimitWarning flags then
8137         pr "%s\n\n" protocol_limit_warning;
8138
8139       if List.mem DangerWillRobinson flags then
8140         pr "%s\n\n" danger_will_robinson;
8141
8142       match deprecation_notice flags with
8143       | None -> ()
8144       | Some txt -> pr "%s\n\n" txt
8145   ) all_functions_sorted
8146
8147 (* Generate a C function prototype. *)
8148 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8149     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8150     ?(prefix = "")
8151     ?handle name style =
8152   if extern then pr "extern ";
8153   if static then pr "static ";
8154   (match fst style with
8155    | RErr -> pr "int "
8156    | RInt _ -> pr "int "
8157    | RInt64 _ -> pr "int64_t "
8158    | RBool _ -> pr "int "
8159    | RConstString _ | RConstOptString _ -> pr "const char *"
8160    | RString _ | RBufferOut _ -> pr "char *"
8161    | RStringList _ | RHashtable _ -> pr "char **"
8162    | RStruct (_, typ) ->
8163        if not in_daemon then pr "struct guestfs_%s *" typ
8164        else pr "guestfs_int_%s *" typ
8165    | RStructList (_, typ) ->
8166        if not in_daemon then pr "struct guestfs_%s_list *" typ
8167        else pr "guestfs_int_%s_list *" typ
8168   );
8169   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8170   pr "%s%s (" prefix name;
8171   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8172     pr "void"
8173   else (
8174     let comma = ref false in
8175     (match handle with
8176      | None -> ()
8177      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8178     );
8179     let next () =
8180       if !comma then (
8181         if single_line then pr ", " else pr ",\n\t\t"
8182       );
8183       comma := true
8184     in
8185     List.iter (
8186       function
8187       | Pathname n
8188       | Device n | Dev_or_Path n
8189       | String n
8190       | OptString n ->
8191           next ();
8192           pr "const char *%s" n
8193       | StringList n | DeviceList n ->
8194           next ();
8195           pr "char *const *%s" n
8196       | Bool n -> next (); pr "int %s" n
8197       | Int n -> next (); pr "int %s" n
8198       | Int64 n -> next (); pr "int64_t %s" n
8199       | FileIn n
8200       | FileOut n ->
8201           if not in_daemon then (next (); pr "const char *%s" n)
8202       | BufferIn n ->
8203           next ();
8204           pr "const char *%s" n;
8205           next ();
8206           pr "size_t %s_size" n
8207     ) (snd style);
8208     if is_RBufferOut then (next (); pr "size_t *size_r");
8209   );
8210   pr ")";
8211   if semicolon then pr ";";
8212   if newline then pr "\n"
8213
8214 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8215 and generate_c_call_args ?handle ?(decl = false) style =
8216   pr "(";
8217   let comma = ref false in
8218   let next () =
8219     if !comma then pr ", ";
8220     comma := true
8221   in
8222   (match handle with
8223    | None -> ()
8224    | Some handle -> pr "%s" handle; comma := true
8225   );
8226   List.iter (
8227     function
8228     | BufferIn n ->
8229         next ();
8230         pr "%s, %s_size" n n
8231     | arg ->
8232         next ();
8233         pr "%s" (name_of_argt arg)
8234   ) (snd style);
8235   (* For RBufferOut calls, add implicit &size parameter. *)
8236   if not decl then (
8237     match fst style with
8238     | RBufferOut _ ->
8239         next ();
8240         pr "&size"
8241     | _ -> ()
8242   );
8243   pr ")"
8244
8245 (* Generate the OCaml bindings interface. *)
8246 and generate_ocaml_mli () =
8247   generate_header OCamlStyle LGPLv2plus;
8248
8249   pr "\
8250 (** For API documentation you should refer to the C API
8251     in the guestfs(3) manual page.  The OCaml API uses almost
8252     exactly the same calls. *)
8253
8254 type t
8255 (** A [guestfs_h] handle. *)
8256
8257 exception Error of string
8258 (** This exception is raised when there is an error. *)
8259
8260 exception Handle_closed of string
8261 (** This exception is raised if you use a {!Guestfs.t} handle
8262     after calling {!close} on it.  The string is the name of
8263     the function. *)
8264
8265 val create : unit -> t
8266 (** Create a {!Guestfs.t} handle. *)
8267
8268 val close : t -> unit
8269 (** Close the {!Guestfs.t} handle and free up all resources used
8270     by it immediately.
8271
8272     Handles are closed by the garbage collector when they become
8273     unreferenced, but callers can call this in order to provide
8274     predictable cleanup. *)
8275
8276 ";
8277   generate_ocaml_structure_decls ();
8278
8279   (* The actions. *)
8280   List.iter (
8281     fun (name, style, _, _, _, shortdesc, _) ->
8282       generate_ocaml_prototype name style;
8283       pr "(** %s *)\n" shortdesc;
8284       pr "\n"
8285   ) all_functions_sorted
8286
8287 (* Generate the OCaml bindings implementation. *)
8288 and generate_ocaml_ml () =
8289   generate_header OCamlStyle LGPLv2plus;
8290
8291   pr "\
8292 type t
8293
8294 exception Error of string
8295 exception Handle_closed of string
8296
8297 external create : unit -> t = \"ocaml_guestfs_create\"
8298 external close : t -> unit = \"ocaml_guestfs_close\"
8299
8300 (* Give the exceptions names, so they can be raised from the C code. *)
8301 let () =
8302   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8303   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8304
8305 ";
8306
8307   generate_ocaml_structure_decls ();
8308
8309   (* The actions. *)
8310   List.iter (
8311     fun (name, style, _, _, _, shortdesc, _) ->
8312       generate_ocaml_prototype ~is_external:true name style;
8313   ) all_functions_sorted
8314
8315 (* Generate the OCaml bindings C implementation. *)
8316 and generate_ocaml_c () =
8317   generate_header CStyle LGPLv2plus;
8318
8319   pr "\
8320 #include <stdio.h>
8321 #include <stdlib.h>
8322 #include <string.h>
8323
8324 #include <caml/config.h>
8325 #include <caml/alloc.h>
8326 #include <caml/callback.h>
8327 #include <caml/fail.h>
8328 #include <caml/memory.h>
8329 #include <caml/mlvalues.h>
8330 #include <caml/signals.h>
8331
8332 #include <guestfs.h>
8333
8334 #include \"guestfs_c.h\"
8335
8336 /* Copy a hashtable of string pairs into an assoc-list.  We return
8337  * the list in reverse order, but hashtables aren't supposed to be
8338  * ordered anyway.
8339  */
8340 static CAMLprim value
8341 copy_table (char * const * argv)
8342 {
8343   CAMLparam0 ();
8344   CAMLlocal5 (rv, pairv, kv, vv, cons);
8345   int i;
8346
8347   rv = Val_int (0);
8348   for (i = 0; argv[i] != NULL; i += 2) {
8349     kv = caml_copy_string (argv[i]);
8350     vv = caml_copy_string (argv[i+1]);
8351     pairv = caml_alloc (2, 0);
8352     Store_field (pairv, 0, kv);
8353     Store_field (pairv, 1, vv);
8354     cons = caml_alloc (2, 0);
8355     Store_field (cons, 1, rv);
8356     rv = cons;
8357     Store_field (cons, 0, pairv);
8358   }
8359
8360   CAMLreturn (rv);
8361 }
8362
8363 ";
8364
8365   (* Struct copy functions. *)
8366
8367   let emit_ocaml_copy_list_function typ =
8368     pr "static CAMLprim value\n";
8369     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8370     pr "{\n";
8371     pr "  CAMLparam0 ();\n";
8372     pr "  CAMLlocal2 (rv, v);\n";
8373     pr "  unsigned int i;\n";
8374     pr "\n";
8375     pr "  if (%ss->len == 0)\n" typ;
8376     pr "    CAMLreturn (Atom (0));\n";
8377     pr "  else {\n";
8378     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8379     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8380     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8381     pr "      caml_modify (&Field (rv, i), v);\n";
8382     pr "    }\n";
8383     pr "    CAMLreturn (rv);\n";
8384     pr "  }\n";
8385     pr "}\n";
8386     pr "\n";
8387   in
8388
8389   List.iter (
8390     fun (typ, cols) ->
8391       let has_optpercent_col =
8392         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8393
8394       pr "static CAMLprim value\n";
8395       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8396       pr "{\n";
8397       pr "  CAMLparam0 ();\n";
8398       if has_optpercent_col then
8399         pr "  CAMLlocal3 (rv, v, v2);\n"
8400       else
8401         pr "  CAMLlocal2 (rv, v);\n";
8402       pr "\n";
8403       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8404       iteri (
8405         fun i col ->
8406           (match col with
8407            | name, FString ->
8408                pr "  v = caml_copy_string (%s->%s);\n" typ name
8409            | name, FBuffer ->
8410                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8411                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8412                  typ name typ name
8413            | name, FUUID ->
8414                pr "  v = caml_alloc_string (32);\n";
8415                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8416            | name, (FBytes|FInt64|FUInt64) ->
8417                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8418            | name, (FInt32|FUInt32) ->
8419                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8420            | name, FOptPercent ->
8421                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8422                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8423                pr "    v = caml_alloc (1, 0);\n";
8424                pr "    Store_field (v, 0, v2);\n";
8425                pr "  } else /* None */\n";
8426                pr "    v = Val_int (0);\n";
8427            | name, FChar ->
8428                pr "  v = Val_int (%s->%s);\n" typ name
8429           );
8430           pr "  Store_field (rv, %d, v);\n" i
8431       ) cols;
8432       pr "  CAMLreturn (rv);\n";
8433       pr "}\n";
8434       pr "\n";
8435   ) structs;
8436
8437   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8438   List.iter (
8439     function
8440     | typ, (RStructListOnly | RStructAndList) ->
8441         (* generate the function for typ *)
8442         emit_ocaml_copy_list_function typ
8443     | typ, _ -> () (* empty *)
8444   ) (rstructs_used_by all_functions);
8445
8446   (* The wrappers. *)
8447   List.iter (
8448     fun (name, style, _, _, _, _, _) ->
8449       pr "/* Automatically generated wrapper for function\n";
8450       pr " * ";
8451       generate_ocaml_prototype name style;
8452       pr " */\n";
8453       pr "\n";
8454
8455       let params =
8456         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8457
8458       let needs_extra_vs =
8459         match fst style with RConstOptString _ -> true | _ -> false in
8460
8461       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8462       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8463       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8464       pr "\n";
8465
8466       pr "CAMLprim value\n";
8467       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8468       List.iter (pr ", value %s") (List.tl params);
8469       pr ")\n";
8470       pr "{\n";
8471
8472       (match params with
8473        | [p1; p2; p3; p4; p5] ->
8474            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8475        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8476            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8477            pr "  CAMLxparam%d (%s);\n"
8478              (List.length rest) (String.concat ", " rest)
8479        | ps ->
8480            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8481       );
8482       if not needs_extra_vs then
8483         pr "  CAMLlocal1 (rv);\n"
8484       else
8485         pr "  CAMLlocal3 (rv, v, v2);\n";
8486       pr "\n";
8487
8488       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8489       pr "  if (g == NULL)\n";
8490       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8491       pr "\n";
8492
8493       List.iter (
8494         function
8495         | Pathname n
8496         | Device n | Dev_or_Path n
8497         | String n
8498         | FileIn n
8499         | FileOut n ->
8500             pr "  const char *%s = String_val (%sv);\n" n n
8501         | OptString n ->
8502             pr "  const char *%s =\n" n;
8503             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8504               n n
8505         | BufferIn n ->
8506             pr "  const char *%s = String_val (%sv);\n" n n;
8507             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8508         | StringList n | DeviceList n ->
8509             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8510         | Bool n ->
8511             pr "  int %s = Bool_val (%sv);\n" n n
8512         | Int n ->
8513             pr "  int %s = Int_val (%sv);\n" n n
8514         | Int64 n ->
8515             pr "  int64_t %s = Int64_val (%sv);\n" n n
8516       ) (snd style);
8517       let error_code =
8518         match fst style with
8519         | RErr -> pr "  int r;\n"; "-1"
8520         | RInt _ -> pr "  int r;\n"; "-1"
8521         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8522         | RBool _ -> pr "  int r;\n"; "-1"
8523         | RConstString _ | RConstOptString _ ->
8524             pr "  const char *r;\n"; "NULL"
8525         | RString _ -> pr "  char *r;\n"; "NULL"
8526         | RStringList _ ->
8527             pr "  int i;\n";
8528             pr "  char **r;\n";
8529             "NULL"
8530         | RStruct (_, typ) ->
8531             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8532         | RStructList (_, typ) ->
8533             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8534         | RHashtable _ ->
8535             pr "  int i;\n";
8536             pr "  char **r;\n";
8537             "NULL"
8538         | RBufferOut _ ->
8539             pr "  char *r;\n";
8540             pr "  size_t size;\n";
8541             "NULL" in
8542       pr "\n";
8543
8544       pr "  caml_enter_blocking_section ();\n";
8545       pr "  r = guestfs_%s " name;
8546       generate_c_call_args ~handle:"g" style;
8547       pr ";\n";
8548       pr "  caml_leave_blocking_section ();\n";
8549
8550       List.iter (
8551         function
8552         | StringList n | DeviceList n ->
8553             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8554         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8555         | Bool _ | Int _ | Int64 _
8556         | FileIn _ | FileOut _ | BufferIn _ -> ()
8557       ) (snd style);
8558
8559       pr "  if (r == %s)\n" error_code;
8560       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8561       pr "\n";
8562
8563       (match fst style with
8564        | RErr -> pr "  rv = Val_unit;\n"
8565        | RInt _ -> pr "  rv = Val_int (r);\n"
8566        | RInt64 _ ->
8567            pr "  rv = caml_copy_int64 (r);\n"
8568        | RBool _ -> pr "  rv = Val_bool (r);\n"
8569        | RConstString _ ->
8570            pr "  rv = caml_copy_string (r);\n"
8571        | RConstOptString _ ->
8572            pr "  if (r) { /* Some string */\n";
8573            pr "    v = caml_alloc (1, 0);\n";
8574            pr "    v2 = caml_copy_string (r);\n";
8575            pr "    Store_field (v, 0, v2);\n";
8576            pr "  } else /* None */\n";
8577            pr "    v = Val_int (0);\n";
8578        | RString _ ->
8579            pr "  rv = caml_copy_string (r);\n";
8580            pr "  free (r);\n"
8581        | RStringList _ ->
8582            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8583            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8584            pr "  free (r);\n"
8585        | RStruct (_, typ) ->
8586            pr "  rv = copy_%s (r);\n" typ;
8587            pr "  guestfs_free_%s (r);\n" typ;
8588        | RStructList (_, typ) ->
8589            pr "  rv = copy_%s_list (r);\n" typ;
8590            pr "  guestfs_free_%s_list (r);\n" typ;
8591        | RHashtable _ ->
8592            pr "  rv = copy_table (r);\n";
8593            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8594            pr "  free (r);\n";
8595        | RBufferOut _ ->
8596            pr "  rv = caml_alloc_string (size);\n";
8597            pr "  memcpy (String_val (rv), r, size);\n";
8598       );
8599
8600       pr "  CAMLreturn (rv);\n";
8601       pr "}\n";
8602       pr "\n";
8603
8604       if List.length params > 5 then (
8605         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8606         pr "CAMLprim value ";
8607         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8608         pr "CAMLprim value\n";
8609         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8610         pr "{\n";
8611         pr "  return ocaml_guestfs_%s (argv[0]" name;
8612         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8613         pr ");\n";
8614         pr "}\n";
8615         pr "\n"
8616       )
8617   ) all_functions_sorted
8618
8619 and generate_ocaml_structure_decls () =
8620   List.iter (
8621     fun (typ, cols) ->
8622       pr "type %s = {\n" typ;
8623       List.iter (
8624         function
8625         | name, FString -> pr "  %s : string;\n" name
8626         | name, FBuffer -> pr "  %s : string;\n" name
8627         | name, FUUID -> pr "  %s : string;\n" name
8628         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8629         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8630         | name, FChar -> pr "  %s : char;\n" name
8631         | name, FOptPercent -> pr "  %s : float option;\n" name
8632       ) cols;
8633       pr "}\n";
8634       pr "\n"
8635   ) structs
8636
8637 and generate_ocaml_prototype ?(is_external = false) name style =
8638   if is_external then pr "external " else pr "val ";
8639   pr "%s : t -> " name;
8640   List.iter (
8641     function
8642     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8643     | BufferIn _ -> pr "string -> "
8644     | OptString _ -> pr "string option -> "
8645     | StringList _ | DeviceList _ -> pr "string array -> "
8646     | Bool _ -> pr "bool -> "
8647     | Int _ -> pr "int -> "
8648     | Int64 _ -> pr "int64 -> "
8649   ) (snd style);
8650   (match fst style with
8651    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8652    | RInt _ -> pr "int"
8653    | RInt64 _ -> pr "int64"
8654    | RBool _ -> pr "bool"
8655    | RConstString _ -> pr "string"
8656    | RConstOptString _ -> pr "string option"
8657    | RString _ | RBufferOut _ -> pr "string"
8658    | RStringList _ -> pr "string array"
8659    | RStruct (_, typ) -> pr "%s" typ
8660    | RStructList (_, typ) -> pr "%s array" typ
8661    | RHashtable _ -> pr "(string * string) list"
8662   );
8663   if is_external then (
8664     pr " = ";
8665     if List.length (snd style) + 1 > 5 then
8666       pr "\"ocaml_guestfs_%s_byte\" " name;
8667     pr "\"ocaml_guestfs_%s\"" name
8668   );
8669   pr "\n"
8670
8671 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8672 and generate_perl_xs () =
8673   generate_header CStyle LGPLv2plus;
8674
8675   pr "\
8676 #include \"EXTERN.h\"
8677 #include \"perl.h\"
8678 #include \"XSUB.h\"
8679
8680 #include <guestfs.h>
8681
8682 #ifndef PRId64
8683 #define PRId64 \"lld\"
8684 #endif
8685
8686 static SV *
8687 my_newSVll(long long val) {
8688 #ifdef USE_64_BIT_ALL
8689   return newSViv(val);
8690 #else
8691   char buf[100];
8692   int len;
8693   len = snprintf(buf, 100, \"%%\" PRId64, val);
8694   return newSVpv(buf, len);
8695 #endif
8696 }
8697
8698 #ifndef PRIu64
8699 #define PRIu64 \"llu\"
8700 #endif
8701
8702 static SV *
8703 my_newSVull(unsigned long long val) {
8704 #ifdef USE_64_BIT_ALL
8705   return newSVuv(val);
8706 #else
8707   char buf[100];
8708   int len;
8709   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8710   return newSVpv(buf, len);
8711 #endif
8712 }
8713
8714 /* http://www.perlmonks.org/?node_id=680842 */
8715 static char **
8716 XS_unpack_charPtrPtr (SV *arg) {
8717   char **ret;
8718   AV *av;
8719   I32 i;
8720
8721   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8722     croak (\"array reference expected\");
8723
8724   av = (AV *)SvRV (arg);
8725   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8726   if (!ret)
8727     croak (\"malloc failed\");
8728
8729   for (i = 0; i <= av_len (av); i++) {
8730     SV **elem = av_fetch (av, i, 0);
8731
8732     if (!elem || !*elem)
8733       croak (\"missing element in list\");
8734
8735     ret[i] = SvPV_nolen (*elem);
8736   }
8737
8738   ret[i] = NULL;
8739
8740   return ret;
8741 }
8742
8743 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8744
8745 PROTOTYPES: ENABLE
8746
8747 guestfs_h *
8748 _create ()
8749    CODE:
8750       RETVAL = guestfs_create ();
8751       if (!RETVAL)
8752         croak (\"could not create guestfs handle\");
8753       guestfs_set_error_handler (RETVAL, NULL, NULL);
8754  OUTPUT:
8755       RETVAL
8756
8757 void
8758 DESTROY (g)
8759       guestfs_h *g;
8760  PPCODE:
8761       guestfs_close (g);
8762
8763 ";
8764
8765   List.iter (
8766     fun (name, style, _, _, _, _, _) ->
8767       (match fst style with
8768        | RErr -> pr "void\n"
8769        | RInt _ -> pr "SV *\n"
8770        | RInt64 _ -> pr "SV *\n"
8771        | RBool _ -> pr "SV *\n"
8772        | RConstString _ -> pr "SV *\n"
8773        | RConstOptString _ -> pr "SV *\n"
8774        | RString _ -> pr "SV *\n"
8775        | RBufferOut _ -> pr "SV *\n"
8776        | RStringList _
8777        | RStruct _ | RStructList _
8778        | RHashtable _ ->
8779            pr "void\n" (* all lists returned implictly on the stack *)
8780       );
8781       (* Call and arguments. *)
8782       pr "%s (g" name;
8783       List.iter (
8784         fun arg -> pr ", %s" (name_of_argt arg)
8785       ) (snd style);
8786       pr ")\n";
8787       pr "      guestfs_h *g;\n";
8788       iteri (
8789         fun i ->
8790           function
8791           | Pathname n | Device n | Dev_or_Path n | String n
8792           | FileIn n | FileOut n ->
8793               pr "      char *%s;\n" n
8794           | BufferIn n ->
8795               pr "      char *%s;\n" n;
8796               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8797           | OptString n ->
8798               (* http://www.perlmonks.org/?node_id=554277
8799                * Note that the implicit handle argument means we have
8800                * to add 1 to the ST(x) operator.
8801                *)
8802               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8803           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8804           | Bool n -> pr "      int %s;\n" n
8805           | Int n -> pr "      int %s;\n" n
8806           | Int64 n -> pr "      int64_t %s;\n" n
8807       ) (snd style);
8808
8809       let do_cleanups () =
8810         List.iter (
8811           function
8812           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8813           | Bool _ | Int _ | Int64 _
8814           | FileIn _ | FileOut _
8815           | BufferIn _ -> ()
8816           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8817         ) (snd style)
8818       in
8819
8820       (* Code. *)
8821       (match fst style with
8822        | RErr ->
8823            pr "PREINIT:\n";
8824            pr "      int r;\n";
8825            pr " PPCODE:\n";
8826            pr "      r = guestfs_%s " name;
8827            generate_c_call_args ~handle:"g" style;
8828            pr ";\n";
8829            do_cleanups ();
8830            pr "      if (r == -1)\n";
8831            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8832        | RInt n
8833        | RBool n ->
8834            pr "PREINIT:\n";
8835            pr "      int %s;\n" n;
8836            pr "   CODE:\n";
8837            pr "      %s = guestfs_%s " n name;
8838            generate_c_call_args ~handle:"g" style;
8839            pr ";\n";
8840            do_cleanups ();
8841            pr "      if (%s == -1)\n" n;
8842            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8843            pr "      RETVAL = newSViv (%s);\n" n;
8844            pr " OUTPUT:\n";
8845            pr "      RETVAL\n"
8846        | RInt64 n ->
8847            pr "PREINIT:\n";
8848            pr "      int64_t %s;\n" n;
8849            pr "   CODE:\n";
8850            pr "      %s = guestfs_%s " n name;
8851            generate_c_call_args ~handle:"g" style;
8852            pr ";\n";
8853            do_cleanups ();
8854            pr "      if (%s == -1)\n" n;
8855            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8856            pr "      RETVAL = my_newSVll (%s);\n" n;
8857            pr " OUTPUT:\n";
8858            pr "      RETVAL\n"
8859        | RConstString n ->
8860            pr "PREINIT:\n";
8861            pr "      const char *%s;\n" n;
8862            pr "   CODE:\n";
8863            pr "      %s = guestfs_%s " n name;
8864            generate_c_call_args ~handle:"g" style;
8865            pr ";\n";
8866            do_cleanups ();
8867            pr "      if (%s == NULL)\n" n;
8868            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8869            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8870            pr " OUTPUT:\n";
8871            pr "      RETVAL\n"
8872        | RConstOptString n ->
8873            pr "PREINIT:\n";
8874            pr "      const char *%s;\n" n;
8875            pr "   CODE:\n";
8876            pr "      %s = guestfs_%s " n name;
8877            generate_c_call_args ~handle:"g" style;
8878            pr ";\n";
8879            do_cleanups ();
8880            pr "      if (%s == NULL)\n" n;
8881            pr "        RETVAL = &PL_sv_undef;\n";
8882            pr "      else\n";
8883            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8884            pr " OUTPUT:\n";
8885            pr "      RETVAL\n"
8886        | RString n ->
8887            pr "PREINIT:\n";
8888            pr "      char *%s;\n" n;
8889            pr "   CODE:\n";
8890            pr "      %s = guestfs_%s " n name;
8891            generate_c_call_args ~handle:"g" style;
8892            pr ";\n";
8893            do_cleanups ();
8894            pr "      if (%s == NULL)\n" n;
8895            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8896            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8897            pr "      free (%s);\n" n;
8898            pr " OUTPUT:\n";
8899            pr "      RETVAL\n"
8900        | RStringList n | RHashtable n ->
8901            pr "PREINIT:\n";
8902            pr "      char **%s;\n" n;
8903            pr "      int i, n;\n";
8904            pr " PPCODE:\n";
8905            pr "      %s = guestfs_%s " n name;
8906            generate_c_call_args ~handle:"g" style;
8907            pr ";\n";
8908            do_cleanups ();
8909            pr "      if (%s == NULL)\n" n;
8910            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8911            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8912            pr "      EXTEND (SP, n);\n";
8913            pr "      for (i = 0; i < n; ++i) {\n";
8914            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8915            pr "        free (%s[i]);\n" n;
8916            pr "      }\n";
8917            pr "      free (%s);\n" n;
8918        | RStruct (n, typ) ->
8919            let cols = cols_of_struct typ in
8920            generate_perl_struct_code typ cols name style n do_cleanups
8921        | RStructList (n, typ) ->
8922            let cols = cols_of_struct typ in
8923            generate_perl_struct_list_code typ cols name style n do_cleanups
8924        | RBufferOut n ->
8925            pr "PREINIT:\n";
8926            pr "      char *%s;\n" n;
8927            pr "      size_t size;\n";
8928            pr "   CODE:\n";
8929            pr "      %s = guestfs_%s " n name;
8930            generate_c_call_args ~handle:"g" style;
8931            pr ";\n";
8932            do_cleanups ();
8933            pr "      if (%s == NULL)\n" n;
8934            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8935            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8936            pr "      free (%s);\n" n;
8937            pr " OUTPUT:\n";
8938            pr "      RETVAL\n"
8939       );
8940
8941       pr "\n"
8942   ) all_functions
8943
8944 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8945   pr "PREINIT:\n";
8946   pr "      struct guestfs_%s_list *%s;\n" typ n;
8947   pr "      int i;\n";
8948   pr "      HV *hv;\n";
8949   pr " PPCODE:\n";
8950   pr "      %s = guestfs_%s " n name;
8951   generate_c_call_args ~handle:"g" style;
8952   pr ";\n";
8953   do_cleanups ();
8954   pr "      if (%s == NULL)\n" n;
8955   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8956   pr "      EXTEND (SP, %s->len);\n" n;
8957   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8958   pr "        hv = newHV ();\n";
8959   List.iter (
8960     function
8961     | name, FString ->
8962         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8963           name (String.length name) n name
8964     | name, FUUID ->
8965         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8966           name (String.length name) n name
8967     | name, FBuffer ->
8968         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8969           name (String.length name) n name n name
8970     | name, (FBytes|FUInt64) ->
8971         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8972           name (String.length name) n name
8973     | name, FInt64 ->
8974         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8975           name (String.length name) n name
8976     | name, (FInt32|FUInt32) ->
8977         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8978           name (String.length name) n name
8979     | name, FChar ->
8980         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8981           name (String.length name) n name
8982     | name, FOptPercent ->
8983         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8984           name (String.length name) n name
8985   ) cols;
8986   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8987   pr "      }\n";
8988   pr "      guestfs_free_%s_list (%s);\n" typ n
8989
8990 and generate_perl_struct_code typ cols name style n do_cleanups =
8991   pr "PREINIT:\n";
8992   pr "      struct guestfs_%s *%s;\n" typ n;
8993   pr " PPCODE:\n";
8994   pr "      %s = guestfs_%s " n name;
8995   generate_c_call_args ~handle:"g" style;
8996   pr ";\n";
8997   do_cleanups ();
8998   pr "      if (%s == NULL)\n" n;
8999   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9000   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9001   List.iter (
9002     fun ((name, _) as col) ->
9003       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9004
9005       match col with
9006       | name, FString ->
9007           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9008             n name
9009       | name, FBuffer ->
9010           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9011             n name n name
9012       | name, FUUID ->
9013           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9014             n name
9015       | name, (FBytes|FUInt64) ->
9016           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9017             n name
9018       | name, FInt64 ->
9019           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9020             n name
9021       | name, (FInt32|FUInt32) ->
9022           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9023             n name
9024       | name, FChar ->
9025           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9026             n name
9027       | name, FOptPercent ->
9028           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9029             n name
9030   ) cols;
9031   pr "      free (%s);\n" n
9032
9033 (* Generate Sys/Guestfs.pm. *)
9034 and generate_perl_pm () =
9035   generate_header HashStyle LGPLv2plus;
9036
9037   pr "\
9038 =pod
9039
9040 =head1 NAME
9041
9042 Sys::Guestfs - Perl bindings for libguestfs
9043
9044 =head1 SYNOPSIS
9045
9046  use Sys::Guestfs;
9047
9048  my $h = Sys::Guestfs->new ();
9049  $h->add_drive ('guest.img');
9050  $h->launch ();
9051  $h->mount ('/dev/sda1', '/');
9052  $h->touch ('/hello');
9053  $h->sync ();
9054
9055 =head1 DESCRIPTION
9056
9057 The C<Sys::Guestfs> module provides a Perl XS binding to the
9058 libguestfs API for examining and modifying virtual machine
9059 disk images.
9060
9061 Amongst the things this is good for: making batch configuration
9062 changes to guests, getting disk used/free statistics (see also:
9063 virt-df), migrating between virtualization systems (see also:
9064 virt-p2v), performing partial backups, performing partial guest
9065 clones, cloning guests and changing registry/UUID/hostname info, and
9066 much else besides.
9067
9068 Libguestfs uses Linux kernel and qemu code, and can access any type of
9069 guest filesystem that Linux and qemu can, including but not limited
9070 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9071 schemes, qcow, qcow2, vmdk.
9072
9073 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9074 LVs, what filesystem is in each LV, etc.).  It can also run commands
9075 in the context of the guest.  Also you can access filesystems over
9076 FUSE.
9077
9078 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9079 functions for using libguestfs from Perl, including integration
9080 with libvirt.
9081
9082 =head1 ERRORS
9083
9084 All errors turn into calls to C<croak> (see L<Carp(3)>).
9085
9086 =head1 METHODS
9087
9088 =over 4
9089
9090 =cut
9091
9092 package Sys::Guestfs;
9093
9094 use strict;
9095 use warnings;
9096
9097 # This version number changes whenever a new function
9098 # is added to the libguestfs API.  It is not directly
9099 # related to the libguestfs version number.
9100 use vars qw($VERSION);
9101 $VERSION = '0.%d';
9102
9103 require XSLoader;
9104 XSLoader::load ('Sys::Guestfs');
9105
9106 =item $h = Sys::Guestfs->new ();
9107
9108 Create a new guestfs handle.
9109
9110 =cut
9111
9112 sub new {
9113   my $proto = shift;
9114   my $class = ref ($proto) || $proto;
9115
9116   my $self = Sys::Guestfs::_create ();
9117   bless $self, $class;
9118   return $self;
9119 }
9120
9121 " max_proc_nr;
9122
9123   (* Actions.  We only need to print documentation for these as
9124    * they are pulled in from the XS code automatically.
9125    *)
9126   List.iter (
9127     fun (name, style, _, flags, _, _, longdesc) ->
9128       if not (List.mem NotInDocs flags) then (
9129         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9130         pr "=item ";
9131         generate_perl_prototype name style;
9132         pr "\n\n";
9133         pr "%s\n\n" longdesc;
9134         if List.mem ProtocolLimitWarning flags then
9135           pr "%s\n\n" protocol_limit_warning;
9136         if List.mem DangerWillRobinson flags then
9137           pr "%s\n\n" danger_will_robinson;
9138         match deprecation_notice flags with
9139         | None -> ()
9140         | Some txt -> pr "%s\n\n" txt
9141       )
9142   ) all_functions_sorted;
9143
9144   (* End of file. *)
9145   pr "\
9146 =cut
9147
9148 1;
9149
9150 =back
9151
9152 =head1 COPYRIGHT
9153
9154 Copyright (C) %s Red Hat Inc.
9155
9156 =head1 LICENSE
9157
9158 Please see the file COPYING.LIB for the full license.
9159
9160 =head1 SEE ALSO
9161
9162 L<guestfs(3)>,
9163 L<guestfish(1)>,
9164 L<http://libguestfs.org>,
9165 L<Sys::Guestfs::Lib(3)>.
9166
9167 =cut
9168 " copyright_years
9169
9170 and generate_perl_prototype name style =
9171   (match fst style with
9172    | RErr -> ()
9173    | RBool n
9174    | RInt n
9175    | RInt64 n
9176    | RConstString n
9177    | RConstOptString n
9178    | RString n
9179    | RBufferOut n -> pr "$%s = " n
9180    | RStruct (n,_)
9181    | RHashtable n -> pr "%%%s = " n
9182    | RStringList n
9183    | RStructList (n,_) -> pr "@%s = " n
9184   );
9185   pr "$h->%s (" name;
9186   let comma = ref false in
9187   List.iter (
9188     fun arg ->
9189       if !comma then pr ", ";
9190       comma := true;
9191       match arg with
9192       | Pathname n | Device n | Dev_or_Path n | String n
9193       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9194       | BufferIn n ->
9195           pr "$%s" n
9196       | StringList n | DeviceList n ->
9197           pr "\\@%s" n
9198   ) (snd style);
9199   pr ");"
9200
9201 (* Generate Python C module. *)
9202 and generate_python_c () =
9203   generate_header CStyle LGPLv2plus;
9204
9205   pr "\
9206 #define PY_SSIZE_T_CLEAN 1
9207 #include <Python.h>
9208
9209 #if PY_VERSION_HEX < 0x02050000
9210 typedef int Py_ssize_t;
9211 #define PY_SSIZE_T_MAX INT_MAX
9212 #define PY_SSIZE_T_MIN INT_MIN
9213 #endif
9214
9215 #include <stdio.h>
9216 #include <stdlib.h>
9217 #include <assert.h>
9218
9219 #include \"guestfs.h\"
9220
9221 typedef struct {
9222   PyObject_HEAD
9223   guestfs_h *g;
9224 } Pyguestfs_Object;
9225
9226 static guestfs_h *
9227 get_handle (PyObject *obj)
9228 {
9229   assert (obj);
9230   assert (obj != Py_None);
9231   return ((Pyguestfs_Object *) obj)->g;
9232 }
9233
9234 static PyObject *
9235 put_handle (guestfs_h *g)
9236 {
9237   assert (g);
9238   return
9239     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9240 }
9241
9242 /* This list should be freed (but not the strings) after use. */
9243 static char **
9244 get_string_list (PyObject *obj)
9245 {
9246   int i, len;
9247   char **r;
9248
9249   assert (obj);
9250
9251   if (!PyList_Check (obj)) {
9252     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9253     return NULL;
9254   }
9255
9256   len = PyList_Size (obj);
9257   r = malloc (sizeof (char *) * (len+1));
9258   if (r == NULL) {
9259     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9260     return NULL;
9261   }
9262
9263   for (i = 0; i < len; ++i)
9264     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9265   r[len] = NULL;
9266
9267   return r;
9268 }
9269
9270 static PyObject *
9271 put_string_list (char * const * const argv)
9272 {
9273   PyObject *list;
9274   int argc, i;
9275
9276   for (argc = 0; argv[argc] != NULL; ++argc)
9277     ;
9278
9279   list = PyList_New (argc);
9280   for (i = 0; i < argc; ++i)
9281     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9282
9283   return list;
9284 }
9285
9286 static PyObject *
9287 put_table (char * const * const argv)
9288 {
9289   PyObject *list, *item;
9290   int argc, i;
9291
9292   for (argc = 0; argv[argc] != NULL; ++argc)
9293     ;
9294
9295   list = PyList_New (argc >> 1);
9296   for (i = 0; i < argc; i += 2) {
9297     item = PyTuple_New (2);
9298     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9299     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9300     PyList_SetItem (list, i >> 1, item);
9301   }
9302
9303   return list;
9304 }
9305
9306 static void
9307 free_strings (char **argv)
9308 {
9309   int argc;
9310
9311   for (argc = 0; argv[argc] != NULL; ++argc)
9312     free (argv[argc]);
9313   free (argv);
9314 }
9315
9316 static PyObject *
9317 py_guestfs_create (PyObject *self, PyObject *args)
9318 {
9319   guestfs_h *g;
9320
9321   g = guestfs_create ();
9322   if (g == NULL) {
9323     PyErr_SetString (PyExc_RuntimeError,
9324                      \"guestfs.create: failed to allocate handle\");
9325     return NULL;
9326   }
9327   guestfs_set_error_handler (g, NULL, NULL);
9328   return put_handle (g);
9329 }
9330
9331 static PyObject *
9332 py_guestfs_close (PyObject *self, PyObject *args)
9333 {
9334   PyObject *py_g;
9335   guestfs_h *g;
9336
9337   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9338     return NULL;
9339   g = get_handle (py_g);
9340
9341   guestfs_close (g);
9342
9343   Py_INCREF (Py_None);
9344   return Py_None;
9345 }
9346
9347 ";
9348
9349   let emit_put_list_function typ =
9350     pr "static PyObject *\n";
9351     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9352     pr "{\n";
9353     pr "  PyObject *list;\n";
9354     pr "  int i;\n";
9355     pr "\n";
9356     pr "  list = PyList_New (%ss->len);\n" typ;
9357     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9358     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9359     pr "  return list;\n";
9360     pr "};\n";
9361     pr "\n"
9362   in
9363
9364   (* Structures, turned into Python dictionaries. *)
9365   List.iter (
9366     fun (typ, cols) ->
9367       pr "static PyObject *\n";
9368       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9369       pr "{\n";
9370       pr "  PyObject *dict;\n";
9371       pr "\n";
9372       pr "  dict = PyDict_New ();\n";
9373       List.iter (
9374         function
9375         | name, FString ->
9376             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9377             pr "                        PyString_FromString (%s->%s));\n"
9378               typ name
9379         | name, FBuffer ->
9380             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9381             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9382               typ name typ name
9383         | name, FUUID ->
9384             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9385             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9386               typ name
9387         | name, (FBytes|FUInt64) ->
9388             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9389             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9390               typ name
9391         | name, FInt64 ->
9392             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9393             pr "                        PyLong_FromLongLong (%s->%s));\n"
9394               typ name
9395         | name, FUInt32 ->
9396             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9397             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9398               typ name
9399         | name, FInt32 ->
9400             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9401             pr "                        PyLong_FromLong (%s->%s));\n"
9402               typ name
9403         | name, FOptPercent ->
9404             pr "  if (%s->%s >= 0)\n" typ name;
9405             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9406             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9407               typ name;
9408             pr "  else {\n";
9409             pr "    Py_INCREF (Py_None);\n";
9410             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9411             pr "  }\n"
9412         | name, FChar ->
9413             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9414             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9415       ) cols;
9416       pr "  return dict;\n";
9417       pr "};\n";
9418       pr "\n";
9419
9420   ) structs;
9421
9422   (* Emit a put_TYPE_list function definition only if that function is used. *)
9423   List.iter (
9424     function
9425     | typ, (RStructListOnly | RStructAndList) ->
9426         (* generate the function for typ *)
9427         emit_put_list_function typ
9428     | typ, _ -> () (* empty *)
9429   ) (rstructs_used_by all_functions);
9430
9431   (* Python wrapper functions. *)
9432   List.iter (
9433     fun (name, style, _, _, _, _, _) ->
9434       pr "static PyObject *\n";
9435       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9436       pr "{\n";
9437
9438       pr "  PyObject *py_g;\n";
9439       pr "  guestfs_h *g;\n";
9440       pr "  PyObject *py_r;\n";
9441
9442       let error_code =
9443         match fst style with
9444         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9445         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9446         | RConstString _ | RConstOptString _ ->
9447             pr "  const char *r;\n"; "NULL"
9448         | RString _ -> pr "  char *r;\n"; "NULL"
9449         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9450         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9451         | RStructList (_, typ) ->
9452             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9453         | RBufferOut _ ->
9454             pr "  char *r;\n";
9455             pr "  size_t size;\n";
9456             "NULL" in
9457
9458       List.iter (
9459         function
9460         | Pathname n | Device n | Dev_or_Path n | String n
9461         | FileIn n | FileOut n ->
9462             pr "  const char *%s;\n" n
9463         | OptString n -> pr "  const char *%s;\n" n
9464         | BufferIn n ->
9465             pr "  const char *%s;\n" n;
9466             pr "  Py_ssize_t %s_size;\n" n
9467         | StringList n | DeviceList n ->
9468             pr "  PyObject *py_%s;\n" n;
9469             pr "  char **%s;\n" n
9470         | Bool n -> pr "  int %s;\n" n
9471         | Int n -> pr "  int %s;\n" n
9472         | Int64 n -> pr "  long long %s;\n" n
9473       ) (snd style);
9474
9475       pr "\n";
9476
9477       (* Convert the parameters. *)
9478       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9479       List.iter (
9480         function
9481         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9482         | OptString _ -> pr "z"
9483         | StringList _ | DeviceList _ -> pr "O"
9484         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9485         | Int _ -> pr "i"
9486         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9487                              * emulate C's int/long/long long in Python?
9488                              *)
9489         | BufferIn _ -> pr "s#"
9490       ) (snd style);
9491       pr ":guestfs_%s\",\n" name;
9492       pr "                         &py_g";
9493       List.iter (
9494         function
9495         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9496         | OptString n -> pr ", &%s" n
9497         | StringList n | DeviceList n -> pr ", &py_%s" n
9498         | Bool n -> pr ", &%s" n
9499         | Int n -> pr ", &%s" n
9500         | Int64 n -> pr ", &%s" n
9501         | BufferIn n -> pr ", &%s, &%s_size" n n
9502       ) (snd style);
9503
9504       pr "))\n";
9505       pr "    return NULL;\n";
9506
9507       pr "  g = get_handle (py_g);\n";
9508       List.iter (
9509         function
9510         | Pathname _ | Device _ | Dev_or_Path _ | String _
9511         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9512         | BufferIn _ -> ()
9513         | StringList n | DeviceList n ->
9514             pr "  %s = get_string_list (py_%s);\n" n n;
9515             pr "  if (!%s) return NULL;\n" n
9516       ) (snd style);
9517
9518       pr "\n";
9519
9520       pr "  r = guestfs_%s " name;
9521       generate_c_call_args ~handle:"g" style;
9522       pr ";\n";
9523
9524       List.iter (
9525         function
9526         | Pathname _ | Device _ | Dev_or_Path _ | String _
9527         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9528         | BufferIn _ -> ()
9529         | StringList n | DeviceList n ->
9530             pr "  free (%s);\n" n
9531       ) (snd style);
9532
9533       pr "  if (r == %s) {\n" error_code;
9534       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9535       pr "    return NULL;\n";
9536       pr "  }\n";
9537       pr "\n";
9538
9539       (match fst style with
9540        | RErr ->
9541            pr "  Py_INCREF (Py_None);\n";
9542            pr "  py_r = Py_None;\n"
9543        | RInt _
9544        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9545        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9546        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9547        | RConstOptString _ ->
9548            pr "  if (r)\n";
9549            pr "    py_r = PyString_FromString (r);\n";
9550            pr "  else {\n";
9551            pr "    Py_INCREF (Py_None);\n";
9552            pr "    py_r = Py_None;\n";
9553            pr "  }\n"
9554        | RString _ ->
9555            pr "  py_r = PyString_FromString (r);\n";
9556            pr "  free (r);\n"
9557        | RStringList _ ->
9558            pr "  py_r = put_string_list (r);\n";
9559            pr "  free_strings (r);\n"
9560        | RStruct (_, typ) ->
9561            pr "  py_r = put_%s (r);\n" typ;
9562            pr "  guestfs_free_%s (r);\n" typ
9563        | RStructList (_, typ) ->
9564            pr "  py_r = put_%s_list (r);\n" typ;
9565            pr "  guestfs_free_%s_list (r);\n" typ
9566        | RHashtable n ->
9567            pr "  py_r = put_table (r);\n";
9568            pr "  free_strings (r);\n"
9569        | RBufferOut _ ->
9570            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9571            pr "  free (r);\n"
9572       );
9573
9574       pr "  return py_r;\n";
9575       pr "}\n";
9576       pr "\n"
9577   ) all_functions;
9578
9579   (* Table of functions. *)
9580   pr "static PyMethodDef methods[] = {\n";
9581   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9582   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9583   List.iter (
9584     fun (name, _, _, _, _, _, _) ->
9585       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9586         name name
9587   ) all_functions;
9588   pr "  { NULL, NULL, 0, NULL }\n";
9589   pr "};\n";
9590   pr "\n";
9591
9592   (* Init function. *)
9593   pr "\
9594 void
9595 initlibguestfsmod (void)
9596 {
9597   static int initialized = 0;
9598
9599   if (initialized) return;
9600   Py_InitModule ((char *) \"libguestfsmod\", methods);
9601   initialized = 1;
9602 }
9603 "
9604
9605 (* Generate Python module. *)
9606 and generate_python_py () =
9607   generate_header HashStyle LGPLv2plus;
9608
9609   pr "\
9610 u\"\"\"Python bindings for libguestfs
9611
9612 import guestfs
9613 g = guestfs.GuestFS ()
9614 g.add_drive (\"guest.img\")
9615 g.launch ()
9616 parts = g.list_partitions ()
9617
9618 The guestfs module provides a Python binding to the libguestfs API
9619 for examining and modifying virtual machine disk images.
9620
9621 Amongst the things this is good for: making batch configuration
9622 changes to guests, getting disk used/free statistics (see also:
9623 virt-df), migrating between virtualization systems (see also:
9624 virt-p2v), performing partial backups, performing partial guest
9625 clones, cloning guests and changing registry/UUID/hostname info, and
9626 much else besides.
9627
9628 Libguestfs uses Linux kernel and qemu code, and can access any type of
9629 guest filesystem that Linux and qemu can, including but not limited
9630 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9631 schemes, qcow, qcow2, vmdk.
9632
9633 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9634 LVs, what filesystem is in each LV, etc.).  It can also run commands
9635 in the context of the guest.  Also you can access filesystems over
9636 FUSE.
9637
9638 Errors which happen while using the API are turned into Python
9639 RuntimeError exceptions.
9640
9641 To create a guestfs handle you usually have to perform the following
9642 sequence of calls:
9643
9644 # Create the handle, call add_drive at least once, and possibly
9645 # several times if the guest has multiple block devices:
9646 g = guestfs.GuestFS ()
9647 g.add_drive (\"guest.img\")
9648
9649 # Launch the qemu subprocess and wait for it to become ready:
9650 g.launch ()
9651
9652 # Now you can issue commands, for example:
9653 logvols = g.lvs ()
9654
9655 \"\"\"
9656
9657 import libguestfsmod
9658
9659 class GuestFS:
9660     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9661
9662     def __init__ (self):
9663         \"\"\"Create a new libguestfs handle.\"\"\"
9664         self._o = libguestfsmod.create ()
9665
9666     def __del__ (self):
9667         libguestfsmod.close (self._o)
9668
9669 ";
9670
9671   List.iter (
9672     fun (name, style, _, flags, _, _, longdesc) ->
9673       pr "    def %s " name;
9674       generate_py_call_args ~handle:"self" (snd style);
9675       pr ":\n";
9676
9677       if not (List.mem NotInDocs flags) then (
9678         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9679         let doc =
9680           match fst style with
9681           | RErr | RInt _ | RInt64 _ | RBool _
9682           | RConstOptString _ | RConstString _
9683           | RString _ | RBufferOut _ -> doc
9684           | RStringList _ ->
9685               doc ^ "\n\nThis function returns a list of strings."
9686           | RStruct (_, typ) ->
9687               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9688           | RStructList (_, typ) ->
9689               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9690           | RHashtable _ ->
9691               doc ^ "\n\nThis function returns a dictionary." in
9692         let doc =
9693           if List.mem ProtocolLimitWarning flags then
9694             doc ^ "\n\n" ^ protocol_limit_warning
9695           else doc in
9696         let doc =
9697           if List.mem DangerWillRobinson flags then
9698             doc ^ "\n\n" ^ danger_will_robinson
9699           else doc in
9700         let doc =
9701           match deprecation_notice flags with
9702           | None -> doc
9703           | Some txt -> doc ^ "\n\n" ^ txt in
9704         let doc = pod2text ~width:60 name doc in
9705         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9706         let doc = String.concat "\n        " doc in
9707         pr "        u\"\"\"%s\"\"\"\n" doc;
9708       );
9709       pr "        return libguestfsmod.%s " name;
9710       generate_py_call_args ~handle:"self._o" (snd style);
9711       pr "\n";
9712       pr "\n";
9713   ) all_functions
9714
9715 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9716 and generate_py_call_args ~handle args =
9717   pr "(%s" handle;
9718   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9719   pr ")"
9720
9721 (* Useful if you need the longdesc POD text as plain text.  Returns a
9722  * list of lines.
9723  *
9724  * Because this is very slow (the slowest part of autogeneration),
9725  * we memoize the results.
9726  *)
9727 and pod2text ~width name longdesc =
9728   let key = width, name, longdesc in
9729   try Hashtbl.find pod2text_memo key
9730   with Not_found ->
9731     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9732     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9733     close_out chan;
9734     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9735     let chan = open_process_in cmd in
9736     let lines = ref [] in
9737     let rec loop i =
9738       let line = input_line chan in
9739       if i = 1 then             (* discard the first line of output *)
9740         loop (i+1)
9741       else (
9742         let line = triml line in
9743         lines := line :: !lines;
9744         loop (i+1)
9745       ) in
9746     let lines = try loop 1 with End_of_file -> List.rev !lines in
9747     unlink filename;
9748     (match close_process_in chan with
9749      | WEXITED 0 -> ()
9750      | WEXITED i ->
9751          failwithf "pod2text: process exited with non-zero status (%d)" i
9752      | WSIGNALED i | WSTOPPED i ->
9753          failwithf "pod2text: process signalled or stopped by signal %d" i
9754     );
9755     Hashtbl.add pod2text_memo key lines;
9756     pod2text_memo_updated ();
9757     lines
9758
9759 (* Generate ruby bindings. *)
9760 and generate_ruby_c () =
9761   generate_header CStyle LGPLv2plus;
9762
9763   pr "\
9764 #include <stdio.h>
9765 #include <stdlib.h>
9766
9767 #include <ruby.h>
9768
9769 #include \"guestfs.h\"
9770
9771 #include \"extconf.h\"
9772
9773 /* For Ruby < 1.9 */
9774 #ifndef RARRAY_LEN
9775 #define RARRAY_LEN(r) (RARRAY((r))->len)
9776 #endif
9777
9778 static VALUE m_guestfs;                 /* guestfs module */
9779 static VALUE c_guestfs;                 /* guestfs_h handle */
9780 static VALUE e_Error;                   /* used for all errors */
9781
9782 static void ruby_guestfs_free (void *p)
9783 {
9784   if (!p) return;
9785   guestfs_close ((guestfs_h *) p);
9786 }
9787
9788 static VALUE ruby_guestfs_create (VALUE m)
9789 {
9790   guestfs_h *g;
9791
9792   g = guestfs_create ();
9793   if (!g)
9794     rb_raise (e_Error, \"failed to create guestfs handle\");
9795
9796   /* Don't print error messages to stderr by default. */
9797   guestfs_set_error_handler (g, NULL, NULL);
9798
9799   /* Wrap it, and make sure the close function is called when the
9800    * handle goes away.
9801    */
9802   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9803 }
9804
9805 static VALUE ruby_guestfs_close (VALUE gv)
9806 {
9807   guestfs_h *g;
9808   Data_Get_Struct (gv, guestfs_h, g);
9809
9810   ruby_guestfs_free (g);
9811   DATA_PTR (gv) = NULL;
9812
9813   return Qnil;
9814 }
9815
9816 ";
9817
9818   List.iter (
9819     fun (name, style, _, _, _, _, _) ->
9820       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9821       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9822       pr ")\n";
9823       pr "{\n";
9824       pr "  guestfs_h *g;\n";
9825       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9826       pr "  if (!g)\n";
9827       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9828         name;
9829       pr "\n";
9830
9831       List.iter (
9832         function
9833         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9834             pr "  Check_Type (%sv, T_STRING);\n" n;
9835             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9836             pr "  if (!%s)\n" n;
9837             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9838             pr "              \"%s\", \"%s\");\n" n name
9839         | BufferIn n ->
9840             pr "  Check_Type (%sv, T_STRING);\n" n;
9841             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9842             pr "  if (!%s)\n" n;
9843             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9844             pr "              \"%s\", \"%s\");\n" n name;
9845             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9846         | OptString n ->
9847             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9848         | StringList n | DeviceList n ->
9849             pr "  char **%s;\n" n;
9850             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9851             pr "  {\n";
9852             pr "    int i, len;\n";
9853             pr "    len = RARRAY_LEN (%sv);\n" n;
9854             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9855               n;
9856             pr "    for (i = 0; i < len; ++i) {\n";
9857             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9858             pr "      %s[i] = StringValueCStr (v);\n" n;
9859             pr "    }\n";
9860             pr "    %s[len] = NULL;\n" n;
9861             pr "  }\n";
9862         | Bool n ->
9863             pr "  int %s = RTEST (%sv);\n" n n
9864         | Int n ->
9865             pr "  int %s = NUM2INT (%sv);\n" n n
9866         | Int64 n ->
9867             pr "  long long %s = NUM2LL (%sv);\n" n n
9868       ) (snd style);
9869       pr "\n";
9870
9871       let error_code =
9872         match fst style with
9873         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9874         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9875         | RConstString _ | RConstOptString _ ->
9876             pr "  const char *r;\n"; "NULL"
9877         | RString _ -> pr "  char *r;\n"; "NULL"
9878         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9879         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9880         | RStructList (_, typ) ->
9881             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9882         | RBufferOut _ ->
9883             pr "  char *r;\n";
9884             pr "  size_t size;\n";
9885             "NULL" in
9886       pr "\n";
9887
9888       pr "  r = guestfs_%s " name;
9889       generate_c_call_args ~handle:"g" style;
9890       pr ";\n";
9891
9892       List.iter (
9893         function
9894         | Pathname _ | Device _ | Dev_or_Path _ | String _
9895         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9896         | BufferIn _ -> ()
9897         | StringList n | DeviceList n ->
9898             pr "  free (%s);\n" n
9899       ) (snd style);
9900
9901       pr "  if (r == %s)\n" error_code;
9902       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9903       pr "\n";
9904
9905       (match fst style with
9906        | RErr ->
9907            pr "  return Qnil;\n"
9908        | RInt _ | RBool _ ->
9909            pr "  return INT2NUM (r);\n"
9910        | RInt64 _ ->
9911            pr "  return ULL2NUM (r);\n"
9912        | RConstString _ ->
9913            pr "  return rb_str_new2 (r);\n";
9914        | RConstOptString _ ->
9915            pr "  if (r)\n";
9916            pr "    return rb_str_new2 (r);\n";
9917            pr "  else\n";
9918            pr "    return Qnil;\n";
9919        | RString _ ->
9920            pr "  VALUE rv = rb_str_new2 (r);\n";
9921            pr "  free (r);\n";
9922            pr "  return rv;\n";
9923        | RStringList _ ->
9924            pr "  int i, len = 0;\n";
9925            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9926            pr "  VALUE rv = rb_ary_new2 (len);\n";
9927            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9928            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9929            pr "    free (r[i]);\n";
9930            pr "  }\n";
9931            pr "  free (r);\n";
9932            pr "  return rv;\n"
9933        | RStruct (_, typ) ->
9934            let cols = cols_of_struct typ in
9935            generate_ruby_struct_code typ cols
9936        | RStructList (_, typ) ->
9937            let cols = cols_of_struct typ in
9938            generate_ruby_struct_list_code typ cols
9939        | RHashtable _ ->
9940            pr "  VALUE rv = rb_hash_new ();\n";
9941            pr "  int i;\n";
9942            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9943            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9944            pr "    free (r[i]);\n";
9945            pr "    free (r[i+1]);\n";
9946            pr "  }\n";
9947            pr "  free (r);\n";
9948            pr "  return rv;\n"
9949        | RBufferOut _ ->
9950            pr "  VALUE rv = rb_str_new (r, size);\n";
9951            pr "  free (r);\n";
9952            pr "  return rv;\n";
9953       );
9954
9955       pr "}\n";
9956       pr "\n"
9957   ) all_functions;
9958
9959   pr "\
9960 /* Initialize the module. */
9961 void Init__guestfs ()
9962 {
9963   m_guestfs = rb_define_module (\"Guestfs\");
9964   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9965   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9966
9967   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9968   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9969
9970 ";
9971   (* Define the rest of the methods. *)
9972   List.iter (
9973     fun (name, style, _, _, _, _, _) ->
9974       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9975       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9976   ) all_functions;
9977
9978   pr "}\n"
9979
9980 (* Ruby code to return a struct. *)
9981 and generate_ruby_struct_code typ cols =
9982   pr "  VALUE rv = rb_hash_new ();\n";
9983   List.iter (
9984     function
9985     | name, FString ->
9986         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9987     | name, FBuffer ->
9988         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9989     | name, FUUID ->
9990         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9991     | name, (FBytes|FUInt64) ->
9992         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9993     | name, FInt64 ->
9994         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9995     | name, FUInt32 ->
9996         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9997     | name, FInt32 ->
9998         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9999     | name, FOptPercent ->
10000         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10001     | name, FChar -> (* XXX wrong? *)
10002         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10003   ) cols;
10004   pr "  guestfs_free_%s (r);\n" typ;
10005   pr "  return rv;\n"
10006
10007 (* Ruby code to return a struct list. *)
10008 and generate_ruby_struct_list_code typ cols =
10009   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10010   pr "  int i;\n";
10011   pr "  for (i = 0; i < r->len; ++i) {\n";
10012   pr "    VALUE hv = rb_hash_new ();\n";
10013   List.iter (
10014     function
10015     | name, FString ->
10016         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10017     | name, FBuffer ->
10018         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
10019     | name, FUUID ->
10020         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10021     | name, (FBytes|FUInt64) ->
10022         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10023     | name, FInt64 ->
10024         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10025     | name, FUInt32 ->
10026         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10027     | name, FInt32 ->
10028         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10029     | name, FOptPercent ->
10030         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10031     | name, FChar -> (* XXX wrong? *)
10032         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10033   ) cols;
10034   pr "    rb_ary_push (rv, hv);\n";
10035   pr "  }\n";
10036   pr "  guestfs_free_%s_list (r);\n" typ;
10037   pr "  return rv;\n"
10038
10039 (* Generate Java bindings GuestFS.java file. *)
10040 and generate_java_java () =
10041   generate_header CStyle LGPLv2plus;
10042
10043   pr "\
10044 package com.redhat.et.libguestfs;
10045
10046 import java.util.HashMap;
10047 import com.redhat.et.libguestfs.LibGuestFSException;
10048 import com.redhat.et.libguestfs.PV;
10049 import com.redhat.et.libguestfs.VG;
10050 import com.redhat.et.libguestfs.LV;
10051 import com.redhat.et.libguestfs.Stat;
10052 import com.redhat.et.libguestfs.StatVFS;
10053 import com.redhat.et.libguestfs.IntBool;
10054 import com.redhat.et.libguestfs.Dirent;
10055
10056 /**
10057  * The GuestFS object is a libguestfs handle.
10058  *
10059  * @author rjones
10060  */
10061 public class GuestFS {
10062   // Load the native code.
10063   static {
10064     System.loadLibrary (\"guestfs_jni\");
10065   }
10066
10067   /**
10068    * The native guestfs_h pointer.
10069    */
10070   long g;
10071
10072   /**
10073    * Create a libguestfs handle.
10074    *
10075    * @throws LibGuestFSException
10076    */
10077   public GuestFS () throws LibGuestFSException
10078   {
10079     g = _create ();
10080   }
10081   private native long _create () throws LibGuestFSException;
10082
10083   /**
10084    * Close a libguestfs handle.
10085    *
10086    * You can also leave handles to be collected by the garbage
10087    * collector, but this method ensures that the resources used
10088    * by the handle are freed up immediately.  If you call any
10089    * other methods after closing the handle, you will get an
10090    * exception.
10091    *
10092    * @throws LibGuestFSException
10093    */
10094   public void close () throws LibGuestFSException
10095   {
10096     if (g != 0)
10097       _close (g);
10098     g = 0;
10099   }
10100   private native void _close (long g) throws LibGuestFSException;
10101
10102   public void finalize () throws LibGuestFSException
10103   {
10104     close ();
10105   }
10106
10107 ";
10108
10109   List.iter (
10110     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10111       if not (List.mem NotInDocs flags); then (
10112         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10113         let doc =
10114           if List.mem ProtocolLimitWarning flags then
10115             doc ^ "\n\n" ^ protocol_limit_warning
10116           else doc in
10117         let doc =
10118           if List.mem DangerWillRobinson flags then
10119             doc ^ "\n\n" ^ danger_will_robinson
10120           else doc in
10121         let doc =
10122           match deprecation_notice flags with
10123           | None -> doc
10124           | Some txt -> doc ^ "\n\n" ^ txt in
10125         let doc = pod2text ~width:60 name doc in
10126         let doc = List.map (            (* RHBZ#501883 *)
10127           function
10128           | "" -> "<p>"
10129           | nonempty -> nonempty
10130         ) doc in
10131         let doc = String.concat "\n   * " doc in
10132
10133         pr "  /**\n";
10134         pr "   * %s\n" shortdesc;
10135         pr "   * <p>\n";
10136         pr "   * %s\n" doc;
10137         pr "   * @throws LibGuestFSException\n";
10138         pr "   */\n";
10139         pr "  ";
10140       );
10141       generate_java_prototype ~public:true ~semicolon:false name style;
10142       pr "\n";
10143       pr "  {\n";
10144       pr "    if (g == 0)\n";
10145       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10146         name;
10147       pr "    ";
10148       if fst style <> RErr then pr "return ";
10149       pr "_%s " name;
10150       generate_java_call_args ~handle:"g" (snd style);
10151       pr ";\n";
10152       pr "  }\n";
10153       pr "  ";
10154       generate_java_prototype ~privat:true ~native:true name style;
10155       pr "\n";
10156       pr "\n";
10157   ) all_functions;
10158
10159   pr "}\n"
10160
10161 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10162 and generate_java_call_args ~handle args =
10163   pr "(%s" handle;
10164   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10165   pr ")"
10166
10167 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10168     ?(semicolon=true) name style =
10169   if privat then pr "private ";
10170   if public then pr "public ";
10171   if native then pr "native ";
10172
10173   (* return type *)
10174   (match fst style with
10175    | RErr -> pr "void ";
10176    | RInt _ -> pr "int ";
10177    | RInt64 _ -> pr "long ";
10178    | RBool _ -> pr "boolean ";
10179    | RConstString _ | RConstOptString _ | RString _
10180    | RBufferOut _ -> pr "String ";
10181    | RStringList _ -> pr "String[] ";
10182    | RStruct (_, typ) ->
10183        let name = java_name_of_struct typ in
10184        pr "%s " name;
10185    | RStructList (_, typ) ->
10186        let name = java_name_of_struct typ in
10187        pr "%s[] " name;
10188    | RHashtable _ -> pr "HashMap<String,String> ";
10189   );
10190
10191   if native then pr "_%s " name else pr "%s " name;
10192   pr "(";
10193   let needs_comma = ref false in
10194   if native then (
10195     pr "long g";
10196     needs_comma := true
10197   );
10198
10199   (* args *)
10200   List.iter (
10201     fun arg ->
10202       if !needs_comma then pr ", ";
10203       needs_comma := true;
10204
10205       match arg with
10206       | Pathname n
10207       | Device n | Dev_or_Path n
10208       | String n
10209       | OptString n
10210       | FileIn n
10211       | FileOut n ->
10212           pr "String %s" n
10213       | BufferIn n ->
10214           pr "byte[] %s" n
10215       | StringList n | DeviceList n ->
10216           pr "String[] %s" n
10217       | Bool n ->
10218           pr "boolean %s" n
10219       | Int n ->
10220           pr "int %s" n
10221       | Int64 n ->
10222           pr "long %s" n
10223   ) (snd style);
10224
10225   pr ")\n";
10226   pr "    throws LibGuestFSException";
10227   if semicolon then pr ";"
10228
10229 and generate_java_struct jtyp cols () =
10230   generate_header CStyle LGPLv2plus;
10231
10232   pr "\
10233 package com.redhat.et.libguestfs;
10234
10235 /**
10236  * Libguestfs %s structure.
10237  *
10238  * @author rjones
10239  * @see GuestFS
10240  */
10241 public class %s {
10242 " jtyp jtyp;
10243
10244   List.iter (
10245     function
10246     | name, FString
10247     | name, FUUID
10248     | name, FBuffer -> pr "  public String %s;\n" name
10249     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10250     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10251     | name, FChar -> pr "  public char %s;\n" name
10252     | name, FOptPercent ->
10253         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10254         pr "  public float %s;\n" name
10255   ) cols;
10256
10257   pr "}\n"
10258
10259 and generate_java_c () =
10260   generate_header CStyle LGPLv2plus;
10261
10262   pr "\
10263 #include <stdio.h>
10264 #include <stdlib.h>
10265 #include <string.h>
10266
10267 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10268 #include \"guestfs.h\"
10269
10270 /* Note that this function returns.  The exception is not thrown
10271  * until after the wrapper function returns.
10272  */
10273 static void
10274 throw_exception (JNIEnv *env, const char *msg)
10275 {
10276   jclass cl;
10277   cl = (*env)->FindClass (env,
10278                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10279   (*env)->ThrowNew (env, cl, msg);
10280 }
10281
10282 JNIEXPORT jlong JNICALL
10283 Java_com_redhat_et_libguestfs_GuestFS__1create
10284   (JNIEnv *env, jobject obj)
10285 {
10286   guestfs_h *g;
10287
10288   g = guestfs_create ();
10289   if (g == NULL) {
10290     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10291     return 0;
10292   }
10293   guestfs_set_error_handler (g, NULL, NULL);
10294   return (jlong) (long) g;
10295 }
10296
10297 JNIEXPORT void JNICALL
10298 Java_com_redhat_et_libguestfs_GuestFS__1close
10299   (JNIEnv *env, jobject obj, jlong jg)
10300 {
10301   guestfs_h *g = (guestfs_h *) (long) jg;
10302   guestfs_close (g);
10303 }
10304
10305 ";
10306
10307   List.iter (
10308     fun (name, style, _, _, _, _, _) ->
10309       pr "JNIEXPORT ";
10310       (match fst style with
10311        | RErr -> pr "void ";
10312        | RInt _ -> pr "jint ";
10313        | RInt64 _ -> pr "jlong ";
10314        | RBool _ -> pr "jboolean ";
10315        | RConstString _ | RConstOptString _ | RString _
10316        | RBufferOut _ -> pr "jstring ";
10317        | RStruct _ | RHashtable _ ->
10318            pr "jobject ";
10319        | RStringList _ | RStructList _ ->
10320            pr "jobjectArray ";
10321       );
10322       pr "JNICALL\n";
10323       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10324       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10325       pr "\n";
10326       pr "  (JNIEnv *env, jobject obj, jlong jg";
10327       List.iter (
10328         function
10329         | Pathname n
10330         | Device n | Dev_or_Path n
10331         | String n
10332         | OptString n
10333         | FileIn n
10334         | FileOut n ->
10335             pr ", jstring j%s" n
10336         | BufferIn n ->
10337             pr ", jbyteArray j%s" n
10338         | StringList n | DeviceList n ->
10339             pr ", jobjectArray j%s" n
10340         | Bool n ->
10341             pr ", jboolean j%s" n
10342         | Int n ->
10343             pr ", jint j%s" n
10344         | Int64 n ->
10345             pr ", jlong j%s" n
10346       ) (snd style);
10347       pr ")\n";
10348       pr "{\n";
10349       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10350       let error_code, no_ret =
10351         match fst style with
10352         | RErr -> pr "  int r;\n"; "-1", ""
10353         | RBool _
10354         | RInt _ -> pr "  int r;\n"; "-1", "0"
10355         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10356         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10357         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10358         | RString _ ->
10359             pr "  jstring jr;\n";
10360             pr "  char *r;\n"; "NULL", "NULL"
10361         | RStringList _ ->
10362             pr "  jobjectArray jr;\n";
10363             pr "  int r_len;\n";
10364             pr "  jclass cl;\n";
10365             pr "  jstring jstr;\n";
10366             pr "  char **r;\n"; "NULL", "NULL"
10367         | RStruct (_, typ) ->
10368             pr "  jobject jr;\n";
10369             pr "  jclass cl;\n";
10370             pr "  jfieldID fl;\n";
10371             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10372         | RStructList (_, typ) ->
10373             pr "  jobjectArray jr;\n";
10374             pr "  jclass cl;\n";
10375             pr "  jfieldID fl;\n";
10376             pr "  jobject jfl;\n";
10377             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10378         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10379         | RBufferOut _ ->
10380             pr "  jstring jr;\n";
10381             pr "  char *r;\n";
10382             pr "  size_t size;\n";
10383             "NULL", "NULL" in
10384       List.iter (
10385         function
10386         | Pathname n
10387         | Device n | Dev_or_Path n
10388         | String n
10389         | OptString n
10390         | FileIn n
10391         | FileOut n ->
10392             pr "  const char *%s;\n" n
10393         | BufferIn n ->
10394             pr "  jbyte *%s;\n" n;
10395             pr "  size_t %s_size;\n" n
10396         | StringList n | DeviceList n ->
10397             pr "  int %s_len;\n" n;
10398             pr "  const char **%s;\n" n
10399         | Bool n
10400         | Int n ->
10401             pr "  int %s;\n" n
10402         | Int64 n ->
10403             pr "  int64_t %s;\n" n
10404       ) (snd style);
10405
10406       let needs_i =
10407         (match fst style with
10408          | RStringList _ | RStructList _ -> true
10409          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10410          | RConstOptString _
10411          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10412           List.exists (function
10413                        | StringList _ -> true
10414                        | DeviceList _ -> true
10415                        | _ -> false) (snd style) in
10416       if needs_i then
10417         pr "  int i;\n";
10418
10419       pr "\n";
10420
10421       (* Get the parameters. *)
10422       List.iter (
10423         function
10424         | Pathname n
10425         | Device n | Dev_or_Path n
10426         | String n
10427         | FileIn n
10428         | FileOut n ->
10429             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10430         | OptString n ->
10431             (* This is completely undocumented, but Java null becomes
10432              * a NULL parameter.
10433              *)
10434             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10435         | BufferIn n ->
10436             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10437             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10438         | StringList n | DeviceList n ->
10439             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10440             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10441             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10442             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10443               n;
10444             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10445             pr "  }\n";
10446             pr "  %s[%s_len] = NULL;\n" n n;
10447         | Bool n
10448         | Int n
10449         | Int64 n ->
10450             pr "  %s = j%s;\n" n n
10451       ) (snd style);
10452
10453       (* Make the call. *)
10454       pr "  r = guestfs_%s " name;
10455       generate_c_call_args ~handle:"g" style;
10456       pr ";\n";
10457
10458       (* Release the parameters. *)
10459       List.iter (
10460         function
10461         | Pathname n
10462         | Device n | Dev_or_Path n
10463         | String n
10464         | FileIn n
10465         | FileOut n ->
10466             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10467         | OptString n ->
10468             pr "  if (j%s)\n" n;
10469             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10470         | BufferIn n ->
10471             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10472         | StringList n | DeviceList n ->
10473             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10474             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10475               n;
10476             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10477             pr "  }\n";
10478             pr "  free (%s);\n" n
10479         | Bool n
10480         | Int n
10481         | Int64 n -> ()
10482       ) (snd style);
10483
10484       (* Check for errors. *)
10485       pr "  if (r == %s) {\n" error_code;
10486       pr "    throw_exception (env, guestfs_last_error (g));\n";
10487       pr "    return %s;\n" no_ret;
10488       pr "  }\n";
10489
10490       (* Return value. *)
10491       (match fst style with
10492        | RErr -> ()
10493        | RInt _ -> pr "  return (jint) r;\n"
10494        | RBool _ -> pr "  return (jboolean) r;\n"
10495        | RInt64 _ -> pr "  return (jlong) r;\n"
10496        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10497        | RConstOptString _ ->
10498            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10499        | RString _ ->
10500            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10501            pr "  free (r);\n";
10502            pr "  return jr;\n"
10503        | RStringList _ ->
10504            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10505            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10506            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10507            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10508            pr "  for (i = 0; i < r_len; ++i) {\n";
10509            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10510            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10511            pr "    free (r[i]);\n";
10512            pr "  }\n";
10513            pr "  free (r);\n";
10514            pr "  return jr;\n"
10515        | RStruct (_, typ) ->
10516            let jtyp = java_name_of_struct typ in
10517            let cols = cols_of_struct typ in
10518            generate_java_struct_return typ jtyp cols
10519        | RStructList (_, typ) ->
10520            let jtyp = java_name_of_struct typ in
10521            let cols = cols_of_struct typ in
10522            generate_java_struct_list_return typ jtyp cols
10523        | RHashtable _ ->
10524            (* XXX *)
10525            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10526            pr "  return NULL;\n"
10527        | RBufferOut _ ->
10528            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10529            pr "  free (r);\n";
10530            pr "  return jr;\n"
10531       );
10532
10533       pr "}\n";
10534       pr "\n"
10535   ) all_functions
10536
10537 and generate_java_struct_return typ jtyp cols =
10538   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10539   pr "  jr = (*env)->AllocObject (env, cl);\n";
10540   List.iter (
10541     function
10542     | name, FString ->
10543         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10544         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10545     | name, FUUID ->
10546         pr "  {\n";
10547         pr "    char s[33];\n";
10548         pr "    memcpy (s, r->%s, 32);\n" name;
10549         pr "    s[32] = 0;\n";
10550         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10551         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10552         pr "  }\n";
10553     | name, FBuffer ->
10554         pr "  {\n";
10555         pr "    int len = r->%s_len;\n" name;
10556         pr "    char s[len+1];\n";
10557         pr "    memcpy (s, r->%s, len);\n" name;
10558         pr "    s[len] = 0;\n";
10559         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10560         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10561         pr "  }\n";
10562     | name, (FBytes|FUInt64|FInt64) ->
10563         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10564         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10565     | name, (FUInt32|FInt32) ->
10566         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10567         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10568     | name, FOptPercent ->
10569         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10570         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10571     | name, FChar ->
10572         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10573         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10574   ) cols;
10575   pr "  free (r);\n";
10576   pr "  return jr;\n"
10577
10578 and generate_java_struct_list_return typ jtyp cols =
10579   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10580   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10581   pr "  for (i = 0; i < r->len; ++i) {\n";
10582   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10583   List.iter (
10584     function
10585     | name, FString ->
10586         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10587         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10588     | name, FUUID ->
10589         pr "    {\n";
10590         pr "      char s[33];\n";
10591         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10592         pr "      s[32] = 0;\n";
10593         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10594         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10595         pr "    }\n";
10596     | name, FBuffer ->
10597         pr "    {\n";
10598         pr "      int len = r->val[i].%s_len;\n" name;
10599         pr "      char s[len+1];\n";
10600         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10601         pr "      s[len] = 0;\n";
10602         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10603         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10604         pr "    }\n";
10605     | name, (FBytes|FUInt64|FInt64) ->
10606         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10607         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10608     | name, (FUInt32|FInt32) ->
10609         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10610         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10611     | name, FOptPercent ->
10612         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10613         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10614     | name, FChar ->
10615         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10616         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10617   ) cols;
10618   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10619   pr "  }\n";
10620   pr "  guestfs_free_%s_list (r);\n" typ;
10621   pr "  return jr;\n"
10622
10623 and generate_java_makefile_inc () =
10624   generate_header HashStyle GPLv2plus;
10625
10626   pr "java_built_sources = \\\n";
10627   List.iter (
10628     fun (typ, jtyp) ->
10629         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10630   ) java_structs;
10631   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10632
10633 and generate_haskell_hs () =
10634   generate_header HaskellStyle LGPLv2plus;
10635
10636   (* XXX We only know how to generate partial FFI for Haskell
10637    * at the moment.  Please help out!
10638    *)
10639   let can_generate style =
10640     match style with
10641     | RErr, _
10642     | RInt _, _
10643     | RInt64 _, _ -> true
10644     | RBool _, _
10645     | RConstString _, _
10646     | RConstOptString _, _
10647     | RString _, _
10648     | RStringList _, _
10649     | RStruct _, _
10650     | RStructList _, _
10651     | RHashtable _, _
10652     | RBufferOut _, _ -> false in
10653
10654   pr "\
10655 {-# INCLUDE <guestfs.h> #-}
10656 {-# LANGUAGE ForeignFunctionInterface #-}
10657
10658 module Guestfs (
10659   create";
10660
10661   (* List out the names of the actions we want to export. *)
10662   List.iter (
10663     fun (name, style, _, _, _, _, _) ->
10664       if can_generate style then pr ",\n  %s" name
10665   ) all_functions;
10666
10667   pr "
10668   ) where
10669
10670 -- Unfortunately some symbols duplicate ones already present
10671 -- in Prelude.  We don't know which, so we hard-code a list
10672 -- here.
10673 import Prelude hiding (truncate)
10674
10675 import Foreign
10676 import Foreign.C
10677 import Foreign.C.Types
10678 import IO
10679 import Control.Exception
10680 import Data.Typeable
10681
10682 data GuestfsS = GuestfsS            -- represents the opaque C struct
10683 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10684 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10685
10686 -- XXX define properly later XXX
10687 data PV = PV
10688 data VG = VG
10689 data LV = LV
10690 data IntBool = IntBool
10691 data Stat = Stat
10692 data StatVFS = StatVFS
10693 data Hashtable = Hashtable
10694
10695 foreign import ccall unsafe \"guestfs_create\" c_create
10696   :: IO GuestfsP
10697 foreign import ccall unsafe \"&guestfs_close\" c_close
10698   :: FunPtr (GuestfsP -> IO ())
10699 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10700   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10701
10702 create :: IO GuestfsH
10703 create = do
10704   p <- c_create
10705   c_set_error_handler p nullPtr nullPtr
10706   h <- newForeignPtr c_close p
10707   return h
10708
10709 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10710   :: GuestfsP -> IO CString
10711
10712 -- last_error :: GuestfsH -> IO (Maybe String)
10713 -- last_error h = do
10714 --   str <- withForeignPtr h (\\p -> c_last_error p)
10715 --   maybePeek peekCString str
10716
10717 last_error :: GuestfsH -> IO (String)
10718 last_error h = do
10719   str <- withForeignPtr h (\\p -> c_last_error p)
10720   if (str == nullPtr)
10721     then return \"no error\"
10722     else peekCString str
10723
10724 ";
10725
10726   (* Generate wrappers for each foreign function. *)
10727   List.iter (
10728     fun (name, style, _, _, _, _, _) ->
10729       if can_generate style then (
10730         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10731         pr "  :: ";
10732         generate_haskell_prototype ~handle:"GuestfsP" style;
10733         pr "\n";
10734         pr "\n";
10735         pr "%s :: " name;
10736         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10737         pr "\n";
10738         pr "%s %s = do\n" name
10739           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10740         pr "  r <- ";
10741         (* Convert pointer arguments using with* functions. *)
10742         List.iter (
10743           function
10744           | FileIn n
10745           | FileOut n
10746           | Pathname n | Device n | Dev_or_Path n | String n ->
10747               pr "withCString %s $ \\%s -> " n n
10748           | BufferIn n ->
10749               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10750           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10751           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10752           | Bool _ | Int _ | Int64 _ -> ()
10753         ) (snd style);
10754         (* Convert integer arguments. *)
10755         let args =
10756           List.map (
10757             function
10758             | Bool n -> sprintf "(fromBool %s)" n
10759             | Int n -> sprintf "(fromIntegral %s)" n
10760             | Int64 n -> sprintf "(fromIntegral %s)" n
10761             | FileIn n | FileOut n
10762             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10763             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10764           ) (snd style) in
10765         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10766           (String.concat " " ("p" :: args));
10767         (match fst style with
10768          | RErr | RInt _ | RInt64 _ | RBool _ ->
10769              pr "  if (r == -1)\n";
10770              pr "    then do\n";
10771              pr "      err <- last_error h\n";
10772              pr "      fail err\n";
10773          | RConstString _ | RConstOptString _ | RString _
10774          | RStringList _ | RStruct _
10775          | RStructList _ | RHashtable _ | RBufferOut _ ->
10776              pr "  if (r == nullPtr)\n";
10777              pr "    then do\n";
10778              pr "      err <- last_error h\n";
10779              pr "      fail err\n";
10780         );
10781         (match fst style with
10782          | RErr ->
10783              pr "    else return ()\n"
10784          | RInt _ ->
10785              pr "    else return (fromIntegral r)\n"
10786          | RInt64 _ ->
10787              pr "    else return (fromIntegral r)\n"
10788          | RBool _ ->
10789              pr "    else return (toBool r)\n"
10790          | RConstString _
10791          | RConstOptString _
10792          | RString _
10793          | RStringList _
10794          | RStruct _
10795          | RStructList _
10796          | RHashtable _
10797          | RBufferOut _ ->
10798              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10799         );
10800         pr "\n";
10801       )
10802   ) all_functions
10803
10804 and generate_haskell_prototype ~handle ?(hs = false) style =
10805   pr "%s -> " handle;
10806   let string = if hs then "String" else "CString" in
10807   let int = if hs then "Int" else "CInt" in
10808   let bool = if hs then "Bool" else "CInt" in
10809   let int64 = if hs then "Integer" else "Int64" in
10810   List.iter (
10811     fun arg ->
10812       (match arg with
10813        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10814        | BufferIn _ ->
10815            if hs then pr "String"
10816            else pr "CString -> CInt"
10817        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10818        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10819        | Bool _ -> pr "%s" bool
10820        | Int _ -> pr "%s" int
10821        | Int64 _ -> pr "%s" int
10822        | FileIn _ -> pr "%s" string
10823        | FileOut _ -> pr "%s" string
10824       );
10825       pr " -> ";
10826   ) (snd style);
10827   pr "IO (";
10828   (match fst style with
10829    | RErr -> if not hs then pr "CInt"
10830    | RInt _ -> pr "%s" int
10831    | RInt64 _ -> pr "%s" int64
10832    | RBool _ -> pr "%s" bool
10833    | RConstString _ -> pr "%s" string
10834    | RConstOptString _ -> pr "Maybe %s" string
10835    | RString _ -> pr "%s" string
10836    | RStringList _ -> pr "[%s]" string
10837    | RStruct (_, typ) ->
10838        let name = java_name_of_struct typ in
10839        pr "%s" name
10840    | RStructList (_, typ) ->
10841        let name = java_name_of_struct typ in
10842        pr "[%s]" name
10843    | RHashtable _ -> pr "Hashtable"
10844    | RBufferOut _ -> pr "%s" string
10845   );
10846   pr ")"
10847
10848 and generate_csharp () =
10849   generate_header CPlusPlusStyle LGPLv2plus;
10850
10851   (* XXX Make this configurable by the C# assembly users. *)
10852   let library = "libguestfs.so.0" in
10853
10854   pr "\
10855 // These C# bindings are highly experimental at present.
10856 //
10857 // Firstly they only work on Linux (ie. Mono).  In order to get them
10858 // to work on Windows (ie. .Net) you would need to port the library
10859 // itself to Windows first.
10860 //
10861 // The second issue is that some calls are known to be incorrect and
10862 // can cause Mono to segfault.  Particularly: calls which pass or
10863 // return string[], or return any structure value.  This is because
10864 // we haven't worked out the correct way to do this from C#.
10865 //
10866 // The third issue is that when compiling you get a lot of warnings.
10867 // We are not sure whether the warnings are important or not.
10868 //
10869 // Fourthly we do not routinely build or test these bindings as part
10870 // of the make && make check cycle, which means that regressions might
10871 // go unnoticed.
10872 //
10873 // Suggestions and patches are welcome.
10874
10875 // To compile:
10876 //
10877 // gmcs Libguestfs.cs
10878 // mono Libguestfs.exe
10879 //
10880 // (You'll probably want to add a Test class / static main function
10881 // otherwise this won't do anything useful).
10882
10883 using System;
10884 using System.IO;
10885 using System.Runtime.InteropServices;
10886 using System.Runtime.Serialization;
10887 using System.Collections;
10888
10889 namespace Guestfs
10890 {
10891   class Error : System.ApplicationException
10892   {
10893     public Error (string message) : base (message) {}
10894     protected Error (SerializationInfo info, StreamingContext context) {}
10895   }
10896
10897   class Guestfs
10898   {
10899     IntPtr _handle;
10900
10901     [DllImport (\"%s\")]
10902     static extern IntPtr guestfs_create ();
10903
10904     public Guestfs ()
10905     {
10906       _handle = guestfs_create ();
10907       if (_handle == IntPtr.Zero)
10908         throw new Error (\"could not create guestfs handle\");
10909     }
10910
10911     [DllImport (\"%s\")]
10912     static extern void guestfs_close (IntPtr h);
10913
10914     ~Guestfs ()
10915     {
10916       guestfs_close (_handle);
10917     }
10918
10919     [DllImport (\"%s\")]
10920     static extern string guestfs_last_error (IntPtr h);
10921
10922 " library library library;
10923
10924   (* Generate C# structure bindings.  We prefix struct names with
10925    * underscore because C# cannot have conflicting struct names and
10926    * method names (eg. "class stat" and "stat").
10927    *)
10928   List.iter (
10929     fun (typ, cols) ->
10930       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10931       pr "    public class _%s {\n" typ;
10932       List.iter (
10933         function
10934         | name, FChar -> pr "      char %s;\n" name
10935         | name, FString -> pr "      string %s;\n" name
10936         | name, FBuffer ->
10937             pr "      uint %s_len;\n" name;
10938             pr "      string %s;\n" name
10939         | name, FUUID ->
10940             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10941             pr "      string %s;\n" name
10942         | name, FUInt32 -> pr "      uint %s;\n" name
10943         | name, FInt32 -> pr "      int %s;\n" name
10944         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10945         | name, FInt64 -> pr "      long %s;\n" name
10946         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10947       ) cols;
10948       pr "    }\n";
10949       pr "\n"
10950   ) structs;
10951
10952   (* Generate C# function bindings. *)
10953   List.iter (
10954     fun (name, style, _, _, _, shortdesc, _) ->
10955       let rec csharp_return_type () =
10956         match fst style with
10957         | RErr -> "void"
10958         | RBool n -> "bool"
10959         | RInt n -> "int"
10960         | RInt64 n -> "long"
10961         | RConstString n
10962         | RConstOptString n
10963         | RString n
10964         | RBufferOut n -> "string"
10965         | RStruct (_,n) -> "_" ^ n
10966         | RHashtable n -> "Hashtable"
10967         | RStringList n -> "string[]"
10968         | RStructList (_,n) -> sprintf "_%s[]" n
10969
10970       and c_return_type () =
10971         match fst style with
10972         | RErr
10973         | RBool _
10974         | RInt _ -> "int"
10975         | RInt64 _ -> "long"
10976         | RConstString _
10977         | RConstOptString _
10978         | RString _
10979         | RBufferOut _ -> "string"
10980         | RStruct (_,n) -> "_" ^ n
10981         | RHashtable _
10982         | RStringList _ -> "string[]"
10983         | RStructList (_,n) -> sprintf "_%s[]" n
10984
10985       and c_error_comparison () =
10986         match fst style with
10987         | RErr
10988         | RBool _
10989         | RInt _
10990         | RInt64 _ -> "== -1"
10991         | RConstString _
10992         | RConstOptString _
10993         | RString _
10994         | RBufferOut _
10995         | RStruct (_,_)
10996         | RHashtable _
10997         | RStringList _
10998         | RStructList (_,_) -> "== null"
10999
11000       and generate_extern_prototype () =
11001         pr "    static extern %s guestfs_%s (IntPtr h"
11002           (c_return_type ()) name;
11003         List.iter (
11004           function
11005           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11006           | FileIn n | FileOut n
11007           | BufferIn n ->
11008               pr ", [In] string %s" n
11009           | StringList n | DeviceList n ->
11010               pr ", [In] string[] %s" n
11011           | Bool n ->
11012               pr ", bool %s" n
11013           | Int n ->
11014               pr ", int %s" n
11015           | Int64 n ->
11016               pr ", long %s" n
11017         ) (snd style);
11018         pr ");\n"
11019
11020       and generate_public_prototype () =
11021         pr "    public %s %s (" (csharp_return_type ()) name;
11022         let comma = ref false in
11023         let next () =
11024           if !comma then pr ", ";
11025           comma := true
11026         in
11027         List.iter (
11028           function
11029           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11030           | FileIn n | FileOut n
11031           | BufferIn n ->
11032               next (); pr "string %s" n
11033           | StringList n | DeviceList n ->
11034               next (); pr "string[] %s" n
11035           | Bool n ->
11036               next (); pr "bool %s" n
11037           | Int n ->
11038               next (); pr "int %s" n
11039           | Int64 n ->
11040               next (); pr "long %s" n
11041         ) (snd style);
11042         pr ")\n"
11043
11044       and generate_call () =
11045         pr "guestfs_%s (_handle" name;
11046         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11047         pr ");\n";
11048       in
11049
11050       pr "    [DllImport (\"%s\")]\n" library;
11051       generate_extern_prototype ();
11052       pr "\n";
11053       pr "    /// <summary>\n";
11054       pr "    /// %s\n" shortdesc;
11055       pr "    /// </summary>\n";
11056       generate_public_prototype ();
11057       pr "    {\n";
11058       pr "      %s r;\n" (c_return_type ());
11059       pr "      r = ";
11060       generate_call ();
11061       pr "      if (r %s)\n" (c_error_comparison ());
11062       pr "        throw new Error (guestfs_last_error (_handle));\n";
11063       (match fst style with
11064        | RErr -> ()
11065        | RBool _ ->
11066            pr "      return r != 0 ? true : false;\n"
11067        | RHashtable _ ->
11068            pr "      Hashtable rr = new Hashtable ();\n";
11069            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11070            pr "        rr.Add (r[i], r[i+1]);\n";
11071            pr "      return rr;\n"
11072        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11073        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11074        | RStructList _ ->
11075            pr "      return r;\n"
11076       );
11077       pr "    }\n";
11078       pr "\n";
11079   ) all_functions_sorted;
11080
11081   pr "  }
11082 }
11083 "
11084
11085 and generate_bindtests () =
11086   generate_header CStyle LGPLv2plus;
11087
11088   pr "\
11089 #include <stdio.h>
11090 #include <stdlib.h>
11091 #include <inttypes.h>
11092 #include <string.h>
11093
11094 #include \"guestfs.h\"
11095 #include \"guestfs-internal.h\"
11096 #include \"guestfs-internal-actions.h\"
11097 #include \"guestfs_protocol.h\"
11098
11099 #define error guestfs_error
11100 #define safe_calloc guestfs_safe_calloc
11101 #define safe_malloc guestfs_safe_malloc
11102
11103 static void
11104 print_strings (char *const *argv)
11105 {
11106   int argc;
11107
11108   printf (\"[\");
11109   for (argc = 0; argv[argc] != NULL; ++argc) {
11110     if (argc > 0) printf (\", \");
11111     printf (\"\\\"%%s\\\"\", argv[argc]);
11112   }
11113   printf (\"]\\n\");
11114 }
11115
11116 /* The test0 function prints its parameters to stdout. */
11117 ";
11118
11119   let test0, tests =
11120     match test_functions with
11121     | [] -> assert false
11122     | test0 :: tests -> test0, tests in
11123
11124   let () =
11125     let (name, style, _, _, _, _, _) = test0 in
11126     generate_prototype ~extern:false ~semicolon:false ~newline:true
11127       ~handle:"g" ~prefix:"guestfs__" name style;
11128     pr "{\n";
11129     List.iter (
11130       function
11131       | Pathname n
11132       | Device n | Dev_or_Path n
11133       | String n
11134       | FileIn n
11135       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11136       | BufferIn n ->
11137           pr "  {\n";
11138           pr "    size_t i;\n";
11139           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11140           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11141           pr "    printf (\"\\n\");\n";
11142           pr "  }\n";
11143       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11144       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11145       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11146       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11147       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11148     ) (snd style);
11149     pr "  /* Java changes stdout line buffering so we need this: */\n";
11150     pr "  fflush (stdout);\n";
11151     pr "  return 0;\n";
11152     pr "}\n";
11153     pr "\n" in
11154
11155   List.iter (
11156     fun (name, style, _, _, _, _, _) ->
11157       if String.sub name (String.length name - 3) 3 <> "err" then (
11158         pr "/* Test normal return. */\n";
11159         generate_prototype ~extern:false ~semicolon:false ~newline:true
11160           ~handle:"g" ~prefix:"guestfs__" name style;
11161         pr "{\n";
11162         (match fst style with
11163          | RErr ->
11164              pr "  return 0;\n"
11165          | RInt _ ->
11166              pr "  int r;\n";
11167              pr "  sscanf (val, \"%%d\", &r);\n";
11168              pr "  return r;\n"
11169          | RInt64 _ ->
11170              pr "  int64_t r;\n";
11171              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11172              pr "  return r;\n"
11173          | RBool _ ->
11174              pr "  return STREQ (val, \"true\");\n"
11175          | RConstString _
11176          | RConstOptString _ ->
11177              (* Can't return the input string here.  Return a static
11178               * string so we ensure we get a segfault if the caller
11179               * tries to free it.
11180               *)
11181              pr "  return \"static string\";\n"
11182          | RString _ ->
11183              pr "  return strdup (val);\n"
11184          | RStringList _ ->
11185              pr "  char **strs;\n";
11186              pr "  int n, i;\n";
11187              pr "  sscanf (val, \"%%d\", &n);\n";
11188              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11189              pr "  for (i = 0; i < n; ++i) {\n";
11190              pr "    strs[i] = safe_malloc (g, 16);\n";
11191              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11192              pr "  }\n";
11193              pr "  strs[n] = NULL;\n";
11194              pr "  return strs;\n"
11195          | RStruct (_, typ) ->
11196              pr "  struct guestfs_%s *r;\n" typ;
11197              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11198              pr "  return r;\n"
11199          | RStructList (_, typ) ->
11200              pr "  struct guestfs_%s_list *r;\n" typ;
11201              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11202              pr "  sscanf (val, \"%%d\", &r->len);\n";
11203              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11204              pr "  return r;\n"
11205          | RHashtable _ ->
11206              pr "  char **strs;\n";
11207              pr "  int n, i;\n";
11208              pr "  sscanf (val, \"%%d\", &n);\n";
11209              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11210              pr "  for (i = 0; i < n; ++i) {\n";
11211              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11212              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11213              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11214              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11215              pr "  }\n";
11216              pr "  strs[n*2] = NULL;\n";
11217              pr "  return strs;\n"
11218          | RBufferOut _ ->
11219              pr "  return strdup (val);\n"
11220         );
11221         pr "}\n";
11222         pr "\n"
11223       ) else (
11224         pr "/* Test error return. */\n";
11225         generate_prototype ~extern:false ~semicolon:false ~newline:true
11226           ~handle:"g" ~prefix:"guestfs__" name style;
11227         pr "{\n";
11228         pr "  error (g, \"error\");\n";
11229         (match fst style with
11230          | RErr | RInt _ | RInt64 _ | RBool _ ->
11231              pr "  return -1;\n"
11232          | RConstString _ | RConstOptString _
11233          | RString _ | RStringList _ | RStruct _
11234          | RStructList _
11235          | RHashtable _
11236          | RBufferOut _ ->
11237              pr "  return NULL;\n"
11238         );
11239         pr "}\n";
11240         pr "\n"
11241       )
11242   ) tests
11243
11244 and generate_ocaml_bindtests () =
11245   generate_header OCamlStyle GPLv2plus;
11246
11247   pr "\
11248 let () =
11249   let g = Guestfs.create () in
11250 ";
11251
11252   let mkargs args =
11253     String.concat " " (
11254       List.map (
11255         function
11256         | CallString s -> "\"" ^ s ^ "\""
11257         | CallOptString None -> "None"
11258         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11259         | CallStringList xs ->
11260             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11261         | CallInt i when i >= 0 -> string_of_int i
11262         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11263         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11264         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11265         | CallBool b -> string_of_bool b
11266         | CallBuffer s -> sprintf "%S" s
11267       ) args
11268     )
11269   in
11270
11271   generate_lang_bindtests (
11272     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11273   );
11274
11275   pr "print_endline \"EOF\"\n"
11276
11277 and generate_perl_bindtests () =
11278   pr "#!/usr/bin/perl -w\n";
11279   generate_header HashStyle GPLv2plus;
11280
11281   pr "\
11282 use strict;
11283
11284 use Sys::Guestfs;
11285
11286 my $g = Sys::Guestfs->new ();
11287 ";
11288
11289   let mkargs args =
11290     String.concat ", " (
11291       List.map (
11292         function
11293         | CallString s -> "\"" ^ s ^ "\""
11294         | CallOptString None -> "undef"
11295         | CallOptString (Some s) -> sprintf "\"%s\"" s
11296         | CallStringList xs ->
11297             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11298         | CallInt i -> string_of_int i
11299         | CallInt64 i -> Int64.to_string i
11300         | CallBool b -> if b then "1" else "0"
11301         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11302       ) args
11303     )
11304   in
11305
11306   generate_lang_bindtests (
11307     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11308   );
11309
11310   pr "print \"EOF\\n\"\n"
11311
11312 and generate_python_bindtests () =
11313   generate_header HashStyle GPLv2plus;
11314
11315   pr "\
11316 import guestfs
11317
11318 g = guestfs.GuestFS ()
11319 ";
11320
11321   let mkargs args =
11322     String.concat ", " (
11323       List.map (
11324         function
11325         | CallString s -> "\"" ^ s ^ "\""
11326         | CallOptString None -> "None"
11327         | CallOptString (Some s) -> sprintf "\"%s\"" s
11328         | CallStringList xs ->
11329             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11330         | CallInt i -> string_of_int i
11331         | CallInt64 i -> Int64.to_string i
11332         | CallBool b -> if b then "1" else "0"
11333         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11334       ) args
11335     )
11336   in
11337
11338   generate_lang_bindtests (
11339     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11340   );
11341
11342   pr "print \"EOF\"\n"
11343
11344 and generate_ruby_bindtests () =
11345   generate_header HashStyle GPLv2plus;
11346
11347   pr "\
11348 require 'guestfs'
11349
11350 g = Guestfs::create()
11351 ";
11352
11353   let mkargs args =
11354     String.concat ", " (
11355       List.map (
11356         function
11357         | CallString s -> "\"" ^ s ^ "\""
11358         | CallOptString None -> "nil"
11359         | CallOptString (Some s) -> sprintf "\"%s\"" s
11360         | CallStringList xs ->
11361             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11362         | CallInt i -> string_of_int i
11363         | CallInt64 i -> Int64.to_string i
11364         | CallBool b -> string_of_bool b
11365         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11366       ) args
11367     )
11368   in
11369
11370   generate_lang_bindtests (
11371     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11372   );
11373
11374   pr "print \"EOF\\n\"\n"
11375
11376 and generate_java_bindtests () =
11377   generate_header CStyle GPLv2plus;
11378
11379   pr "\
11380 import com.redhat.et.libguestfs.*;
11381
11382 public class Bindtests {
11383     public static void main (String[] argv)
11384     {
11385         try {
11386             GuestFS g = new GuestFS ();
11387 ";
11388
11389   let mkargs args =
11390     String.concat ", " (
11391       List.map (
11392         function
11393         | CallString s -> "\"" ^ s ^ "\""
11394         | CallOptString None -> "null"
11395         | CallOptString (Some s) -> sprintf "\"%s\"" s
11396         | CallStringList xs ->
11397             "new String[]{" ^
11398               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11399         | CallInt i -> string_of_int i
11400         | CallInt64 i -> Int64.to_string i
11401         | CallBool b -> string_of_bool b
11402         | CallBuffer s ->
11403             "new byte[] { " ^ String.concat "," (
11404               map_chars (fun c -> string_of_int (Char.code c)) s
11405             ) ^ " }"
11406       ) args
11407     )
11408   in
11409
11410   generate_lang_bindtests (
11411     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11412   );
11413
11414   pr "
11415             System.out.println (\"EOF\");
11416         }
11417         catch (Exception exn) {
11418             System.err.println (exn);
11419             System.exit (1);
11420         }
11421     }
11422 }
11423 "
11424
11425 and generate_haskell_bindtests () =
11426   generate_header HaskellStyle GPLv2plus;
11427
11428   pr "\
11429 module Bindtests where
11430 import qualified Guestfs
11431
11432 main = do
11433   g <- Guestfs.create
11434 ";
11435
11436   let mkargs args =
11437     String.concat " " (
11438       List.map (
11439         function
11440         | CallString s -> "\"" ^ s ^ "\""
11441         | CallOptString None -> "Nothing"
11442         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11443         | CallStringList xs ->
11444             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11445         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11446         | CallInt i -> string_of_int i
11447         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11448         | CallInt64 i -> Int64.to_string i
11449         | CallBool true -> "True"
11450         | CallBool false -> "False"
11451         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11452       ) args
11453     )
11454   in
11455
11456   generate_lang_bindtests (
11457     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11458   );
11459
11460   pr "  putStrLn \"EOF\"\n"
11461
11462 (* Language-independent bindings tests - we do it this way to
11463  * ensure there is parity in testing bindings across all languages.
11464  *)
11465 and generate_lang_bindtests call =
11466   call "test0" [CallString "abc"; CallOptString (Some "def");
11467                 CallStringList []; CallBool false;
11468                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11469                 CallBuffer "abc\000abc"];
11470   call "test0" [CallString "abc"; CallOptString None;
11471                 CallStringList []; CallBool false;
11472                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11473                 CallBuffer "abc\000abc"];
11474   call "test0" [CallString ""; CallOptString (Some "def");
11475                 CallStringList []; CallBool false;
11476                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11477                 CallBuffer "abc\000abc"];
11478   call "test0" [CallString ""; CallOptString (Some "");
11479                 CallStringList []; CallBool false;
11480                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11481                 CallBuffer "abc\000abc"];
11482   call "test0" [CallString "abc"; CallOptString (Some "def");
11483                 CallStringList ["1"]; CallBool false;
11484                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11485                 CallBuffer "abc\000abc"];
11486   call "test0" [CallString "abc"; CallOptString (Some "def");
11487                 CallStringList ["1"; "2"]; CallBool false;
11488                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11489                 CallBuffer "abc\000abc"];
11490   call "test0" [CallString "abc"; CallOptString (Some "def");
11491                 CallStringList ["1"]; CallBool true;
11492                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11493                 CallBuffer "abc\000abc"];
11494   call "test0" [CallString "abc"; CallOptString (Some "def");
11495                 CallStringList ["1"]; CallBool false;
11496                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11497                 CallBuffer "abc\000abc"];
11498   call "test0" [CallString "abc"; CallOptString (Some "def");
11499                 CallStringList ["1"]; CallBool false;
11500                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11501                 CallBuffer "abc\000abc"];
11502   call "test0" [CallString "abc"; CallOptString (Some "def");
11503                 CallStringList ["1"]; CallBool false;
11504                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11505                 CallBuffer "abc\000abc"];
11506   call "test0" [CallString "abc"; CallOptString (Some "def");
11507                 CallStringList ["1"]; CallBool false;
11508                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11509                 CallBuffer "abc\000abc"];
11510   call "test0" [CallString "abc"; CallOptString (Some "def");
11511                 CallStringList ["1"]; CallBool false;
11512                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11513                 CallBuffer "abc\000abc"];
11514   call "test0" [CallString "abc"; CallOptString (Some "def");
11515                 CallStringList ["1"]; CallBool false;
11516                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11517                 CallBuffer "abc\000abc"]
11518
11519 (* XXX Add here tests of the return and error functions. *)
11520
11521 (* Code to generator bindings for virt-inspector.  Currently only
11522  * implemented for OCaml code (for virt-p2v 2.0).
11523  *)
11524 let rng_input = "inspector/virt-inspector.rng"
11525
11526 (* Read the input file and parse it into internal structures.  This is
11527  * by no means a complete RELAX NG parser, but is just enough to be
11528  * able to parse the specific input file.
11529  *)
11530 type rng =
11531   | Element of string * rng list        (* <element name=name/> *)
11532   | Attribute of string * rng list        (* <attribute name=name/> *)
11533   | Interleave of rng list                (* <interleave/> *)
11534   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11535   | OneOrMore of rng                        (* <oneOrMore/> *)
11536   | Optional of rng                        (* <optional/> *)
11537   | Choice of string list                (* <choice><value/>*</choice> *)
11538   | Value of string                        (* <value>str</value> *)
11539   | Text                                (* <text/> *)
11540
11541 let rec string_of_rng = function
11542   | Element (name, xs) ->
11543       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11544   | Attribute (name, xs) ->
11545       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11546   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11547   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11548   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11549   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11550   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11551   | Value value -> "Value \"" ^ value ^ "\""
11552   | Text -> "Text"
11553
11554 and string_of_rng_list xs =
11555   String.concat ", " (List.map string_of_rng xs)
11556
11557 let rec parse_rng ?defines context = function
11558   | [] -> []
11559   | Xml.Element ("element", ["name", name], children) :: rest ->
11560       Element (name, parse_rng ?defines context children)
11561       :: parse_rng ?defines context rest
11562   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11563       Attribute (name, parse_rng ?defines context children)
11564       :: parse_rng ?defines context rest
11565   | Xml.Element ("interleave", [], children) :: rest ->
11566       Interleave (parse_rng ?defines context children)
11567       :: parse_rng ?defines context rest
11568   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11569       let rng = parse_rng ?defines context [child] in
11570       (match rng with
11571        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11572        | _ ->
11573            failwithf "%s: <zeroOrMore> contains more than one child element"
11574              context
11575       )
11576   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11577       let rng = parse_rng ?defines context [child] in
11578       (match rng with
11579        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11580        | _ ->
11581            failwithf "%s: <oneOrMore> contains more than one child element"
11582              context
11583       )
11584   | Xml.Element ("optional", [], [child]) :: rest ->
11585       let rng = parse_rng ?defines context [child] in
11586       (match rng with
11587        | [child] -> Optional child :: parse_rng ?defines context rest
11588        | _ ->
11589            failwithf "%s: <optional> contains more than one child element"
11590              context
11591       )
11592   | Xml.Element ("choice", [], children) :: rest ->
11593       let values = List.map (
11594         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11595         | _ ->
11596             failwithf "%s: can't handle anything except <value> in <choice>"
11597               context
11598       ) children in
11599       Choice values
11600       :: parse_rng ?defines context rest
11601   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11602       Value value :: parse_rng ?defines context rest
11603   | Xml.Element ("text", [], []) :: rest ->
11604       Text :: parse_rng ?defines context rest
11605   | Xml.Element ("ref", ["name", name], []) :: rest ->
11606       (* Look up the reference.  Because of limitations in this parser,
11607        * we can't handle arbitrarily nested <ref> yet.  You can only
11608        * use <ref> from inside <start>.
11609        *)
11610       (match defines with
11611        | None ->
11612            failwithf "%s: contains <ref>, but no refs are defined yet" context
11613        | Some map ->
11614            let rng = StringMap.find name map in
11615            rng @ parse_rng ?defines context rest
11616       )
11617   | x :: _ ->
11618       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11619
11620 let grammar =
11621   let xml = Xml.parse_file rng_input in
11622   match xml with
11623   | Xml.Element ("grammar", _,
11624                  Xml.Element ("start", _, gram) :: defines) ->
11625       (* The <define/> elements are referenced in the <start> section,
11626        * so build a map of those first.
11627        *)
11628       let defines = List.fold_left (
11629         fun map ->
11630           function Xml.Element ("define", ["name", name], defn) ->
11631             StringMap.add name defn map
11632           | _ ->
11633               failwithf "%s: expected <define name=name/>" rng_input
11634       ) StringMap.empty defines in
11635       let defines = StringMap.mapi parse_rng defines in
11636
11637       (* Parse the <start> clause, passing the defines. *)
11638       parse_rng ~defines "<start>" gram
11639   | _ ->
11640       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11641         rng_input
11642
11643 let name_of_field = function
11644   | Element (name, _) | Attribute (name, _)
11645   | ZeroOrMore (Element (name, _))
11646   | OneOrMore (Element (name, _))
11647   | Optional (Element (name, _)) -> name
11648   | Optional (Attribute (name, _)) -> name
11649   | Text -> (* an unnamed field in an element *)
11650       "data"
11651   | rng ->
11652       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11653
11654 (* At the moment this function only generates OCaml types.  However we
11655  * should parameterize it later so it can generate types/structs in a
11656  * variety of languages.
11657  *)
11658 let generate_types xs =
11659   (* A simple type is one that can be printed out directly, eg.
11660    * "string option".  A complex type is one which has a name and has
11661    * to be defined via another toplevel definition, eg. a struct.
11662    *
11663    * generate_type generates code for either simple or complex types.
11664    * In the simple case, it returns the string ("string option").  In
11665    * the complex case, it returns the name ("mountpoint").  In the
11666    * complex case it has to print out the definition before returning,
11667    * so it should only be called when we are at the beginning of a
11668    * new line (BOL context).
11669    *)
11670   let rec generate_type = function
11671     | Text ->                                (* string *)
11672         "string", true
11673     | Choice values ->                        (* [`val1|`val2|...] *)
11674         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11675     | ZeroOrMore rng ->                        (* <rng> list *)
11676         let t, is_simple = generate_type rng in
11677         t ^ " list (* 0 or more *)", is_simple
11678     | OneOrMore rng ->                        (* <rng> list *)
11679         let t, is_simple = generate_type rng in
11680         t ^ " list (* 1 or more *)", is_simple
11681                                         (* virt-inspector hack: bool *)
11682     | Optional (Attribute (name, [Value "1"])) ->
11683         "bool", true
11684     | Optional rng ->                        (* <rng> list *)
11685         let t, is_simple = generate_type rng in
11686         t ^ " option", is_simple
11687                                         (* type name = { fields ... } *)
11688     | Element (name, fields) when is_attrs_interleave fields ->
11689         generate_type_struct name (get_attrs_interleave fields)
11690     | Element (name, [field])                (* type name = field *)
11691     | Attribute (name, [field]) ->
11692         let t, is_simple = generate_type field in
11693         if is_simple then (t, true)
11694         else (
11695           pr "type %s = %s\n" name t;
11696           name, false
11697         )
11698     | Element (name, fields) ->              (* type name = { fields ... } *)
11699         generate_type_struct name fields
11700     | rng ->
11701         failwithf "generate_type failed at: %s" (string_of_rng rng)
11702
11703   and is_attrs_interleave = function
11704     | [Interleave _] -> true
11705     | Attribute _ :: fields -> is_attrs_interleave fields
11706     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11707     | _ -> false
11708
11709   and get_attrs_interleave = function
11710     | [Interleave fields] -> fields
11711     | ((Attribute _) as field) :: fields
11712     | ((Optional (Attribute _)) as field) :: fields ->
11713         field :: get_attrs_interleave fields
11714     | _ -> assert false
11715
11716   and generate_types xs =
11717     List.iter (fun x -> ignore (generate_type x)) xs
11718
11719   and generate_type_struct name fields =
11720     (* Calculate the types of the fields first.  We have to do this
11721      * before printing anything so we are still in BOL context.
11722      *)
11723     let types = List.map fst (List.map generate_type fields) in
11724
11725     (* Special case of a struct containing just a string and another
11726      * field.  Turn it into an assoc list.
11727      *)
11728     match types with
11729     | ["string"; other] ->
11730         let fname1, fname2 =
11731           match fields with
11732           | [f1; f2] -> name_of_field f1, name_of_field f2
11733           | _ -> assert false in
11734         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11735         name, false
11736
11737     | types ->
11738         pr "type %s = {\n" name;
11739         List.iter (
11740           fun (field, ftype) ->
11741             let fname = name_of_field field in
11742             pr "  %s_%s : %s;\n" name fname ftype
11743         ) (List.combine fields types);
11744         pr "}\n";
11745         (* Return the name of this type, and
11746          * false because it's not a simple type.
11747          *)
11748         name, false
11749   in
11750
11751   generate_types xs
11752
11753 let generate_parsers xs =
11754   (* As for generate_type above, generate_parser makes a parser for
11755    * some type, and returns the name of the parser it has generated.
11756    * Because it (may) need to print something, it should always be
11757    * called in BOL context.
11758    *)
11759   let rec generate_parser = function
11760     | Text ->                                (* string *)
11761         "string_child_or_empty"
11762     | Choice values ->                        (* [`val1|`val2|...] *)
11763         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11764           (String.concat "|"
11765              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11766     | ZeroOrMore rng ->                        (* <rng> list *)
11767         let pa = generate_parser rng in
11768         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11769     | OneOrMore rng ->                        (* <rng> list *)
11770         let pa = generate_parser rng in
11771         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11772                                         (* virt-inspector hack: bool *)
11773     | Optional (Attribute (name, [Value "1"])) ->
11774         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11775     | Optional rng ->                        (* <rng> list *)
11776         let pa = generate_parser rng in
11777         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11778                                         (* type name = { fields ... } *)
11779     | Element (name, fields) when is_attrs_interleave fields ->
11780         generate_parser_struct name (get_attrs_interleave fields)
11781     | Element (name, [field]) ->        (* type name = field *)
11782         let pa = generate_parser field in
11783         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11784         pr "let %s =\n" parser_name;
11785         pr "  %s\n" pa;
11786         pr "let parse_%s = %s\n" name parser_name;
11787         parser_name
11788     | Attribute (name, [field]) ->
11789         let pa = generate_parser field in
11790         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11791         pr "let %s =\n" parser_name;
11792         pr "  %s\n" pa;
11793         pr "let parse_%s = %s\n" name parser_name;
11794         parser_name
11795     | Element (name, fields) ->              (* type name = { fields ... } *)
11796         generate_parser_struct name ([], fields)
11797     | rng ->
11798         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11799
11800   and is_attrs_interleave = function
11801     | [Interleave _] -> true
11802     | Attribute _ :: fields -> is_attrs_interleave fields
11803     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11804     | _ -> false
11805
11806   and get_attrs_interleave = function
11807     | [Interleave fields] -> [], fields
11808     | ((Attribute _) as field) :: fields
11809     | ((Optional (Attribute _)) as field) :: fields ->
11810         let attrs, interleaves = get_attrs_interleave fields in
11811         (field :: attrs), interleaves
11812     | _ -> assert false
11813
11814   and generate_parsers xs =
11815     List.iter (fun x -> ignore (generate_parser x)) xs
11816
11817   and generate_parser_struct name (attrs, interleaves) =
11818     (* Generate parsers for the fields first.  We have to do this
11819      * before printing anything so we are still in BOL context.
11820      *)
11821     let fields = attrs @ interleaves in
11822     let pas = List.map generate_parser fields in
11823
11824     (* Generate an intermediate tuple from all the fields first.
11825      * If the type is just a string + another field, then we will
11826      * return this directly, otherwise it is turned into a record.
11827      *
11828      * RELAX NG note: This code treats <interleave> and plain lists of
11829      * fields the same.  In other words, it doesn't bother enforcing
11830      * any ordering of fields in the XML.
11831      *)
11832     pr "let parse_%s x =\n" name;
11833     pr "  let t = (\n    ";
11834     let comma = ref false in
11835     List.iter (
11836       fun x ->
11837         if !comma then pr ",\n    ";
11838         comma := true;
11839         match x with
11840         | Optional (Attribute (fname, [field])), pa ->
11841             pr "%s x" pa
11842         | Optional (Element (fname, [field])), pa ->
11843             pr "%s (optional_child %S x)" pa fname
11844         | Attribute (fname, [Text]), _ ->
11845             pr "attribute %S x" fname
11846         | (ZeroOrMore _ | OneOrMore _), pa ->
11847             pr "%s x" pa
11848         | Text, pa ->
11849             pr "%s x" pa
11850         | (field, pa) ->
11851             let fname = name_of_field field in
11852             pr "%s (child %S x)" pa fname
11853     ) (List.combine fields pas);
11854     pr "\n  ) in\n";
11855
11856     (match fields with
11857      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11858          pr "  t\n"
11859
11860      | _ ->
11861          pr "  (Obj.magic t : %s)\n" name
11862 (*
11863          List.iter (
11864            function
11865            | (Optional (Attribute (fname, [field])), pa) ->
11866                pr "  %s_%s =\n" name fname;
11867                pr "    %s x;\n" pa
11868            | (Optional (Element (fname, [field])), pa) ->
11869                pr "  %s_%s =\n" name fname;
11870                pr "    (let x = optional_child %S x in\n" fname;
11871                pr "     %s x);\n" pa
11872            | (field, pa) ->
11873                let fname = name_of_field field in
11874                pr "  %s_%s =\n" name fname;
11875                pr "    (let x = child %S x in\n" fname;
11876                pr "     %s x);\n" pa
11877          ) (List.combine fields pas);
11878          pr "}\n"
11879 *)
11880     );
11881     sprintf "parse_%s" name
11882   in
11883
11884   generate_parsers xs
11885
11886 (* Generate ocaml/guestfs_inspector.mli. *)
11887 let generate_ocaml_inspector_mli () =
11888   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11889
11890   pr "\
11891 (** This is an OCaml language binding to the external [virt-inspector]
11892     program.
11893
11894     For more information, please read the man page [virt-inspector(1)].
11895 *)
11896
11897 ";
11898
11899   generate_types grammar;
11900   pr "(** The nested information returned from the {!inspect} function. *)\n";
11901   pr "\n";
11902
11903   pr "\
11904 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11905 (** To inspect a libvirt domain called [name], pass a singleton
11906     list: [inspect [name]].  When using libvirt only, you may
11907     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11908
11909     To inspect a disk image or images, pass a list of the filenames
11910     of the disk images: [inspect filenames]
11911
11912     This function inspects the given guest or disk images and
11913     returns a list of operating system(s) found and a large amount
11914     of information about them.  In the vast majority of cases,
11915     a virtual machine only contains a single operating system.
11916
11917     If the optional [~xml] parameter is given, then this function
11918     skips running the external virt-inspector program and just
11919     parses the given XML directly (which is expected to be XML
11920     produced from a previous run of virt-inspector).  The list of
11921     names and connect URI are ignored in this case.
11922
11923     This function can throw a wide variety of exceptions, for example
11924     if the external virt-inspector program cannot be found, or if
11925     it doesn't generate valid XML.
11926 *)
11927 "
11928
11929 (* Generate ocaml/guestfs_inspector.ml. *)
11930 let generate_ocaml_inspector_ml () =
11931   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11932
11933   pr "open Unix\n";
11934   pr "\n";
11935
11936   generate_types grammar;
11937   pr "\n";
11938
11939   pr "\
11940 (* Misc functions which are used by the parser code below. *)
11941 let first_child = function
11942   | Xml.Element (_, _, c::_) -> c
11943   | Xml.Element (name, _, []) ->
11944       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11945   | Xml.PCData str ->
11946       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11947
11948 let string_child_or_empty = function
11949   | Xml.Element (_, _, [Xml.PCData s]) -> s
11950   | Xml.Element (_, _, []) -> \"\"
11951   | Xml.Element (x, _, _) ->
11952       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11953                 x ^ \" instead\")
11954   | Xml.PCData str ->
11955       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11956
11957 let optional_child name xml =
11958   let children = Xml.children xml in
11959   try
11960     Some (List.find (function
11961                      | Xml.Element (n, _, _) when n = name -> true
11962                      | _ -> false) children)
11963   with
11964     Not_found -> None
11965
11966 let child name xml =
11967   match optional_child name xml with
11968   | Some c -> c
11969   | None ->
11970       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11971
11972 let attribute name xml =
11973   try Xml.attrib xml name
11974   with Xml.No_attribute _ ->
11975     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11976
11977 ";
11978
11979   generate_parsers grammar;
11980   pr "\n";
11981
11982   pr "\
11983 (* Run external virt-inspector, then use parser to parse the XML. *)
11984 let inspect ?connect ?xml names =
11985   let xml =
11986     match xml with
11987     | None ->
11988         if names = [] then invalid_arg \"inspect: no names given\";
11989         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11990           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11991           names in
11992         let cmd = List.map Filename.quote cmd in
11993         let cmd = String.concat \" \" cmd in
11994         let chan = open_process_in cmd in
11995         let xml = Xml.parse_in chan in
11996         (match close_process_in chan with
11997          | WEXITED 0 -> ()
11998          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11999          | WSIGNALED i | WSTOPPED i ->
12000              failwith (\"external virt-inspector command died or stopped on sig \" ^
12001                        string_of_int i)
12002         );
12003         xml
12004     | Some doc ->
12005         Xml.parse_string doc in
12006   parse_operatingsystems xml
12007 "
12008
12009 and generate_max_proc_nr () =
12010   pr "%d\n" max_proc_nr
12011
12012 let output_to filename k =
12013   let filename_new = filename ^ ".new" in
12014   chan := open_out filename_new;
12015   k ();
12016   close_out !chan;
12017   chan := Pervasives.stdout;
12018
12019   (* Is the new file different from the current file? *)
12020   if Sys.file_exists filename && files_equal filename filename_new then
12021     unlink filename_new                 (* same, so skip it *)
12022   else (
12023     (* different, overwrite old one *)
12024     (try chmod filename 0o644 with Unix_error _ -> ());
12025     rename filename_new filename;
12026     chmod filename 0o444;
12027     printf "written %s\n%!" filename;
12028   )
12029
12030 let perror msg = function
12031   | Unix_error (err, _, _) ->
12032       eprintf "%s: %s\n" msg (error_message err)
12033   | exn ->
12034       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12035
12036 (* Main program. *)
12037 let () =
12038   let lock_fd =
12039     try openfile "HACKING" [O_RDWR] 0
12040     with
12041     | Unix_error (ENOENT, _, _) ->
12042         eprintf "\
12043 You are probably running this from the wrong directory.
12044 Run it from the top source directory using the command
12045   src/generator.ml
12046 ";
12047         exit 1
12048     | exn ->
12049         perror "open: HACKING" exn;
12050         exit 1 in
12051
12052   (* Acquire a lock so parallel builds won't try to run the generator
12053    * twice at the same time.  Subsequent builds will wait for the first
12054    * one to finish.  Note the lock is released implicitly when the
12055    * program exits.
12056    *)
12057   (try lockf lock_fd F_LOCK 1
12058    with exn ->
12059      perror "lock: HACKING" exn;
12060      exit 1);
12061
12062   check_functions ();
12063
12064   output_to "src/guestfs_protocol.x" generate_xdr;
12065   output_to "src/guestfs-structs.h" generate_structs_h;
12066   output_to "src/guestfs-actions.h" generate_actions_h;
12067   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12068   output_to "src/guestfs-actions.c" generate_client_actions;
12069   output_to "src/guestfs-bindtests.c" generate_bindtests;
12070   output_to "src/guestfs-structs.pod" generate_structs_pod;
12071   output_to "src/guestfs-actions.pod" generate_actions_pod;
12072   output_to "src/guestfs-availability.pod" generate_availability_pod;
12073   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12074   output_to "src/libguestfs.syms" generate_linker_script;
12075   output_to "daemon/actions.h" generate_daemon_actions_h;
12076   output_to "daemon/stubs.c" generate_daemon_actions;
12077   output_to "daemon/names.c" generate_daemon_names;
12078   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12079   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12080   output_to "capitests/tests.c" generate_tests;
12081   output_to "fish/cmds.c" generate_fish_cmds;
12082   output_to "fish/completion.c" generate_fish_completion;
12083   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12084   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12085   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12086   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12087   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12088   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12089   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12090   output_to "perl/Guestfs.xs" generate_perl_xs;
12091   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12092   output_to "perl/bindtests.pl" generate_perl_bindtests;
12093   output_to "python/guestfs-py.c" generate_python_c;
12094   output_to "python/guestfs.py" generate_python_py;
12095   output_to "python/bindtests.py" generate_python_bindtests;
12096   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12097   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12098   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12099
12100   List.iter (
12101     fun (typ, jtyp) ->
12102       let cols = cols_of_struct typ in
12103       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12104       output_to filename (generate_java_struct jtyp cols);
12105   ) java_structs;
12106
12107   output_to "java/Makefile.inc" generate_java_makefile_inc;
12108   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12109   output_to "java/Bindtests.java" generate_java_bindtests;
12110   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12111   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12112   output_to "csharp/Libguestfs.cs" generate_csharp;
12113
12114   (* Always generate this file last, and unconditionally.  It's used
12115    * by the Makefile to know when we must re-run the generator.
12116    *)
12117   let chan = open_out "src/stamp-generator" in
12118   fprintf chan "1\n";
12119   close_out chan;
12120
12121   printf "generated %d lines of code\n" !lines