96a58478d6c0041790103887ba1cde11748586cd
[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 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write"; "/new"; "new file contents"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write"; "/new"; "new file contents"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1542    [],
1543    "create a file",
1544    "\
1545 This call creates a file called C<path>.  The contents of the
1546 file is the string C<content> (which can contain any 8 bit data),
1547 with length C<size>.
1548
1549 As a special case, if C<size> is C<0>
1550 then the length is calculated using C<strlen> (so in this case
1551 the content cannot contain embedded ASCII NULs).
1552
1553 I<NB.> Owing to a bug, writing content containing ASCII NUL
1554 characters does I<not> work, even if the length is specified.");
1555
1556   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557    [InitEmpty, Always, TestOutputListOfDevices (
1558       [["part_disk"; "/dev/sda"; "mbr"];
1559        ["mkfs"; "ext2"; "/dev/sda1"];
1560        ["mount_options"; ""; "/dev/sda1"; "/"];
1561        ["mounts"]], ["/dev/sda1"]);
1562     InitEmpty, Always, TestOutputList (
1563       [["part_disk"; "/dev/sda"; "mbr"];
1564        ["mkfs"; "ext2"; "/dev/sda1"];
1565        ["mount_options"; ""; "/dev/sda1"; "/"];
1566        ["umount"; "/"];
1567        ["mounts"]], [])],
1568    "unmount a filesystem",
1569    "\
1570 This unmounts the given filesystem.  The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1573
1574   ("mounts", (RStringList "devices", []), 46, [],
1575    [InitBasicFS, Always, TestOutputListOfDevices (
1576       [["mounts"]], ["/dev/sda1"])],
1577    "show mounted filesystems",
1578    "\
1579 This returns the list of currently mounted filesystems.  It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1581
1582 Some internal mounts are not shown.
1583
1584 See also: C<guestfs_mountpoints>");
1585
1586   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587    [InitBasicFS, Always, TestOutputList (
1588       [["umount_all"];
1589        ["mounts"]], []);
1590     (* check that umount_all can unmount nested mounts correctly: *)
1591     InitEmpty, Always, TestOutputList (
1592       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593        ["mkfs"; "ext2"; "/dev/sda1"];
1594        ["mkfs"; "ext2"; "/dev/sda2"];
1595        ["mkfs"; "ext2"; "/dev/sda3"];
1596        ["mount_options"; ""; "/dev/sda1"; "/"];
1597        ["mkdir"; "/mp1"];
1598        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599        ["mkdir"; "/mp1/mp2"];
1600        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601        ["mkdir"; "/mp1/mp2/mp3"];
1602        ["umount_all"];
1603        ["mounts"]], [])],
1604    "unmount all filesystems",
1605    "\
1606 This unmounts all mounted filesystems.
1607
1608 Some internal mounts are not unmounted by this call.");
1609
1610   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1611    [],
1612    "remove all LVM LVs, VGs and PVs",
1613    "\
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1616
1617   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618    [InitISOFS, Always, TestOutput (
1619       [["file"; "/empty"]], "empty");
1620     InitISOFS, Always, TestOutput (
1621       [["file"; "/known-1"]], "ASCII text");
1622     InitISOFS, Always, TestLastFail (
1623       [["file"; "/notexists"]])],
1624    "determine file type",
1625    "\
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file.  This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1629
1630 This call will also transparently look inside various types
1631 of compressed file.
1632
1633 The exact command which runs is C<file -zbsL path>.  Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1636
1637   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638    [InitBasicFS, Always, TestOutput (
1639       [["upload"; "test-command"; "/test-command"];
1640        ["chmod"; "0o755"; "/test-command"];
1641        ["command"; "/test-command 1"]], "Result1");
1642     InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 2"]], "Result2\n");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 3"]], "\nResult3");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 4"]], "\nResult4\n");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 5"]], "\nResult5\n\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 7"]], "");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 8"]], "\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 9"]], "\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682     InitBasicFS, Always, TestLastFail (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command"]])],
1686    "run a command from the guest filesystem",
1687    "\
1688 This call runs a command from the guest filesystem.  The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1692
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters.  The list must be
1696 non-empty (ie. must contain a program name).  Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1699
1700 The return value is anything printed to I<stdout> by
1701 the command.
1702
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message.  The error message
1705 string is the content of I<stderr> from the command.
1706
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>.  If you require a program from
1709 another location, you should provide the full path in the
1710 first parameter.
1711
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places.  It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1716 locations.");
1717
1718   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719    [InitBasicFS, Always, TestOutputList (
1720       [["upload"; "test-command"; "/test-command"];
1721        ["chmod"; "0o755"; "/test-command"];
1722        ["command_lines"; "/test-command 1"]], ["Result1"]);
1723     InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 2"]], ["Result2"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 7"]], []);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 8"]], [""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 9"]], ["";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763    "run a command, returning lines",
1764    "\
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1767
1768 See also: C<guestfs_sh_lines>");
1769
1770   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771    [InitISOFS, Always, TestOutputStruct (
1772       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773    "get file information",
1774    "\
1775 Returns file information for the given C<path>.
1776
1777 This is the same as the C<stat(2)> system call.");
1778
1779   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information for a symbolic link",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1788 refers to.
1789
1790 This is the same as the C<lstat(2)> system call.");
1791
1792   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795    "get file system statistics",
1796    "\
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1800
1801 This is the same as the C<statvfs(2)> system call.");
1802
1803   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1804    [], (* XXX test *)
1805    "get ext2/ext3/ext4 superblock details",
1806    "\
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1809
1810 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1811 manpage for more details.  The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1814
1815   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816    [InitEmpty, Always, TestOutputTrue (
1817       [["blockdev_setro"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-only",
1820    "\
1821 Sets the block device named C<device> to read-only.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826    [InitEmpty, Always, TestOutputFalse (
1827       [["blockdev_setrw"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-write",
1830    "\
1831 Sets the block device named C<device> to read-write.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "is block device set to read-only",
1840    "\
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847    [InitEmpty, Always, TestOutputInt (
1848       [["blockdev_getss"; "/dev/sda"]], 512)],
1849    "get sectorsize of block device",
1850    "\
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1853
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 for that).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862    "get blocksize of block device",
1863    "\
1864 This returns the block size of a device.
1865
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1872    [], (* XXX test *)
1873    "set blocksize of block device",
1874    "\
1875 This sets the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885    "get total size of device in 512-byte sectors",
1886    "\
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1889
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897    [InitEmpty, Always, TestOutputInt (
1898       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899    "get total size of device in bytes",
1900    "\
1901 This returns the size of the device in bytes.
1902
1903 See also C<guestfs_blockdev_getsz>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_flushbufs"; "/dev/sda"]]],
1910    "flush device buffers",
1911    "\
1912 This tells the kernel to flush internal buffers associated
1913 with C<device>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_rereadpt"; "/dev/sda"]]],
1920    "reread partition table",
1921    "\
1922 Reread the partition table on C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927    [InitBasicFS, Always, TestOutput (
1928       (* Pick a file from cwd which isn't likely to change. *)
1929       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930        ["checksum"; "md5"; "/COPYING.LIB"]],
1931       Digest.to_hex (Digest.file "COPYING.LIB"))],
1932    "upload a file from the local machine",
1933    "\
1934 Upload local file C<filename> to C<remotefilename> on the
1935 filesystem.
1936
1937 C<filename> can also be a named pipe.
1938
1939 See also C<guestfs_download>.");
1940
1941   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946        ["upload"; "testdownload.tmp"; "/upload"];
1947        ["checksum"; "md5"; "/upload"]],
1948       Digest.to_hex (Digest.file "COPYING.LIB"))],
1949    "download a file to the local machine",
1950    "\
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1953
1954 C<filename> can also be a named pipe.
1955
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1957
1958   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959    [InitISOFS, Always, TestOutput (
1960       [["checksum"; "crc"; "/known-3"]], "2891671662");
1961     InitISOFS, Always, TestLastFail (
1962       [["checksum"; "crc"; "/notexists"]]);
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1975     (* Test for RHBZ#579608, absolute symbolic links. *)
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.
2020
2021 To get the checksum for a device, use C<guestfs_checksum_device>.
2022
2023 To get the checksums for many files, use C<guestfs_checksums_out>.");
2024
2025   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2026    [InitBasicFS, Always, TestOutput (
2027       [["tar_in"; "../images/helloworld.tar"; "/"];
2028        ["cat"; "/hello"]], "hello\n")],
2029    "unpack tarfile to directory",
2030    "\
2031 This command uploads and unpacks local file C<tarfile> (an
2032 I<uncompressed> tar file) into C<directory>.
2033
2034 To upload a compressed tarball, use C<guestfs_tgz_in>
2035 or C<guestfs_txz_in>.");
2036
2037   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2038    [],
2039    "pack directory into tarfile",
2040    "\
2041 This command packs the contents of C<directory> and downloads
2042 it to local file C<tarfile>.
2043
2044 To download a compressed tarball, use C<guestfs_tgz_out>
2045 or C<guestfs_txz_out>.");
2046
2047   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2048    [InitBasicFS, Always, TestOutput (
2049       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2050        ["cat"; "/hello"]], "hello\n")],
2051    "unpack compressed tarball to directory",
2052    "\
2053 This command uploads and unpacks local file C<tarball> (a
2054 I<gzip compressed> tar file) into C<directory>.
2055
2056 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2057
2058   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2059    [],
2060    "pack directory into compressed tarball",
2061    "\
2062 This command packs the contents of C<directory> and downloads
2063 it to local file C<tarball>.
2064
2065 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2066
2067   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2068    [InitBasicFS, Always, TestLastFail (
2069       [["umount"; "/"];
2070        ["mount_ro"; "/dev/sda1"; "/"];
2071        ["touch"; "/new"]]);
2072     InitBasicFS, Always, TestOutput (
2073       [["write"; "/new"; "data"];
2074        ["umount"; "/"];
2075        ["mount_ro"; "/dev/sda1"; "/"];
2076        ["cat"; "/new"]], "data")],
2077    "mount a guest disk, read-only",
2078    "\
2079 This is the same as the C<guestfs_mount> command, but it
2080 mounts the filesystem with the read-only (I<-o ro>) flag.");
2081
2082   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2083    [],
2084    "mount a guest disk with mount options",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set the mount options as for the
2088 L<mount(8)> I<-o> flag.
2089
2090 If the C<options> parameter is an empty string, then
2091 no options are passed (all options default to whatever
2092 the filesystem uses).");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
2190     InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write"; "/old"; "file content"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write"; "/old"; "file content"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write"; "/olddir/file"; "file content"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write"; "/old"; "file content"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write"; "/file1"; "contents of a file"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["write"; "/file2"; "contents of another file"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], []);
2430     (* Test for RHBZ#579608, absolute symbolic links. *)
2431     InitISOFS, Always, TestRun (
2432       [["strings"; "/abssymlink"]])],
2433    "print the printable strings in a file",
2434    "\
2435 This runs the L<strings(1)> command on a file and returns
2436 the list of printable strings found.");
2437
2438   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2439    [InitISOFS, Always, TestOutputList (
2440       [["strings_e"; "b"; "/known-5"]], []);
2441     InitBasicFS, Always, TestOutputList (
2442       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2443        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2444    "print the printable strings in a file",
2445    "\
2446 This is like the C<guestfs_strings> command, but allows you to
2447 specify the encoding of strings that are looked for in
2448 the source file C<path>.
2449
2450 Allowed encodings are:
2451
2452 =over 4
2453
2454 =item s
2455
2456 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2457 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2458
2459 =item S
2460
2461 Single 8-bit-byte characters.
2462
2463 =item b
2464
2465 16-bit big endian strings such as those encoded in
2466 UTF-16BE or UCS-2BE.
2467
2468 =item l (lower case letter L)
2469
2470 16-bit little endian such as UTF-16LE and UCS-2LE.
2471 This is useful for examining binaries in Windows guests.
2472
2473 =item B
2474
2475 32-bit big endian such as UCS-4BE.
2476
2477 =item L
2478
2479 32-bit little endian such as UCS-4LE.
2480
2481 =back
2482
2483 The returned strings are transcoded to UTF-8.");
2484
2485   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2486    [InitISOFS, Always, TestOutput (
2487       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2488     (* Test for RHBZ#501888c2 regression which caused large hexdump
2489      * commands to segfault.
2490      *)
2491     InitISOFS, Always, TestRun (
2492       [["hexdump"; "/100krandom"]]);
2493     (* Test for RHBZ#579608, absolute symbolic links. *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/abssymlink"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write"; "/new"; "test file"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write"; "/new"; "test content"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write"; "/file"; "content"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000);
2851     (* Test for RHBZ#579608, absolute symbolic links. *)
2852     InitISOFS, Always, TestOutputInt (
2853       [["wc_l"; "/abssymlink"]], 10000)],
2854    "count lines in a file",
2855    "\
2856 This command counts the lines in a file, using the
2857 C<wc -l> external command.");
2858
2859   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2860    [InitISOFS, Always, TestOutputInt (
2861       [["wc_w"; "/10klines"]], 10000)],
2862    "count words in a file",
2863    "\
2864 This command counts the words in a file, using the
2865 C<wc -w> external command.");
2866
2867   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2868    [InitISOFS, Always, TestOutputInt (
2869       [["wc_c"; "/100kallspaces"]], 102400)],
2870    "count characters in a file",
2871    "\
2872 This command counts the characters in a file, using the
2873 C<wc -c> external command.");
2874
2875   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2876    [InitISOFS, Always, TestOutputList (
2877       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2878     (* Test for RHBZ#579608, absolute symbolic links. *)
2879     InitISOFS, Always, TestOutputList (
2880       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2881    "return first 10 lines of a file",
2882    "\
2883 This command returns up to the first 10 lines of a file as
2884 a list of strings.");
2885
2886   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2887    [InitISOFS, Always, TestOutputList (
2888       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2889     InitISOFS, Always, TestOutputList (
2890       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891     InitISOFS, Always, TestOutputList (
2892       [["head_n"; "0"; "/10klines"]], [])],
2893    "return first N lines of a file",
2894    "\
2895 If the parameter C<nrlines> is a positive number, this returns the first
2896 C<nrlines> lines of the file C<path>.
2897
2898 If the parameter C<nrlines> is a negative number, this returns lines
2899 from the file C<path>, excluding the last C<nrlines> lines.
2900
2901 If the parameter C<nrlines> is zero, this returns an empty list.");
2902
2903   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2906    "return last 10 lines of a file",
2907    "\
2908 This command returns up to the last 10 lines of a file as
2909 a list of strings.");
2910
2911   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2912    [InitISOFS, Always, TestOutputList (
2913       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2914     InitISOFS, Always, TestOutputList (
2915       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "0"; "/10klines"]], [])],
2918    "return last N lines of a file",
2919    "\
2920 If the parameter C<nrlines> is a positive number, this returns the last
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>, starting with the C<-nrlines>th line.
2925
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2927
2928   ("df", (RString "output", []), 125, [],
2929    [], (* XXX Tricky to test because it depends on the exact format
2930         * of the 'df' command and other imponderables.
2931         *)
2932    "report file system disk space usage",
2933    "\
2934 This command runs the C<df> command to report disk space used.
2935
2936 This command is mostly useful for interactive sessions.  It
2937 is I<not> intended that you try to parse the output string.
2938 Use C<statvfs> from programs.");
2939
2940   ("df_h", (RString "output", []), 126, [],
2941    [], (* XXX Tricky to test because it depends on the exact format
2942         * of the 'df' command and other imponderables.
2943         *)
2944    "report file system disk space usage (human readable)",
2945    "\
2946 This command runs the C<df -h> command to report disk space used
2947 in human-readable format.
2948
2949 This command is mostly useful for interactive sessions.  It
2950 is I<not> intended that you try to parse the output string.
2951 Use C<statvfs> from programs.");
2952
2953   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2954    [InitISOFS, Always, TestOutputInt (
2955       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2956    "estimate file space usage",
2957    "\
2958 This command runs the C<du -s> command to estimate file space
2959 usage for C<path>.
2960
2961 C<path> can be a file or a directory.  If C<path> is a directory
2962 then the estimate includes the contents of the directory and all
2963 subdirectories (recursively).
2964
2965 The result is the estimated size in I<kilobytes>
2966 (ie. units of 1024 bytes).");
2967
2968   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2969    [InitISOFS, Always, TestOutputList (
2970       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2971    "list files in an initrd",
2972    "\
2973 This command lists out files contained in an initrd.
2974
2975 The files are listed without any initial C</> character.  The
2976 files are listed in the order they appear (not necessarily
2977 alphabetical).  Directory names are listed as separate items.
2978
2979 Old Linux kernels (2.4 and earlier) used a compressed ext2
2980 filesystem as initrd.  We I<only> support the newer initramfs
2981 format (compressed cpio files).");
2982
2983   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2984    [],
2985    "mount a file using the loop device",
2986    "\
2987 This command lets you mount C<file> (a filesystem image
2988 in a file) on a mount point.  It is entirely equivalent to
2989 the command C<mount -o loop file mountpoint>.");
2990
2991   ("mkswap", (RErr, [Device "device"]), 130, [],
2992    [InitEmpty, Always, TestRun (
2993       [["part_disk"; "/dev/sda"; "mbr"];
2994        ["mkswap"; "/dev/sda1"]])],
2995    "create a swap partition",
2996    "\
2997 Create a swap partition on C<device>.");
2998
2999   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3000    [InitEmpty, Always, TestRun (
3001       [["part_disk"; "/dev/sda"; "mbr"];
3002        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3003    "create a swap partition with a label",
3004    "\
3005 Create a swap partition on C<device> with label C<label>.
3006
3007 Note that you cannot attach a swap label to a block device
3008 (eg. C</dev/sda>), just to a partition.  This appears to be
3009 a limitation of the kernel or swap tools.");
3010
3011   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3012    (let uuid = uuidgen () in
3013     [InitEmpty, Always, TestRun (
3014        [["part_disk"; "/dev/sda"; "mbr"];
3015         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3016    "create a swap partition with an explicit UUID",
3017    "\
3018 Create a swap partition on C<device> with UUID C<uuid>.");
3019
3020   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3021    [InitBasicFS, Always, TestOutputStruct (
3022       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3023        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3024        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3025     InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3027        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3028    "make block, character or FIFO devices",
3029    "\
3030 This call creates block or character special devices, or
3031 named pipes (FIFOs).
3032
3033 The C<mode> parameter should be the mode, using the standard
3034 constants.  C<devmajor> and C<devminor> are the
3035 device major and minor numbers, only used when creating block
3036 and character special devices.
3037
3038 Note that, just like L<mknod(2)>, the mode must be bitwise
3039 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3040 just creates a regular file).  These constants are
3041 available in the standard Linux header files, or you can use
3042 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3043 which are wrappers around this command which bitwise OR
3044 in the appropriate constant for you.
3045
3046 The mode actually set is affected by the umask.");
3047
3048   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mkfifo"; "0o777"; "/node"];
3051        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3052    "make FIFO (named pipe)",
3053    "\
3054 This call creates a FIFO (named pipe) called C<path> with
3055 mode C<mode>.  It is just a convenient wrapper around
3056 C<guestfs_mknod>.
3057
3058 The mode actually set is affected by the umask.");
3059
3060   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3061    [InitBasicFS, Always, TestOutputStruct (
3062       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3063        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3064    "make block device node",
3065    "\
3066 This call creates a block device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3069
3070 The mode actually set is affected by the umask.");
3071
3072   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3073    [InitBasicFS, Always, TestOutputStruct (
3074       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3075        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3076    "make char device node",
3077    "\
3078 This call creates a char device node called C<path> with
3079 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3080 It is just a convenient wrapper around C<guestfs_mknod>.
3081
3082 The mode actually set is affected by the umask.");
3083
3084   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3085    [InitEmpty, Always, TestOutputInt (
3086       [["umask"; "0o22"]], 0o22)],
3087    "set file mode creation mask (umask)",
3088    "\
3089 This function sets the mask used for creating new files and
3090 device nodes to C<mask & 0777>.
3091
3092 Typical umask values would be C<022> which creates new files
3093 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3094 C<002> which creates new files with permissions like
3095 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3096
3097 The default umask is C<022>.  This is important because it
3098 means that directories and device nodes will be created with
3099 C<0644> or C<0755> mode even if you specify C<0777>.
3100
3101 See also C<guestfs_get_umask>,
3102 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3103
3104 This call returns the previous umask.");
3105
3106   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3107    [],
3108    "read directories entries",
3109    "\
3110 This returns the list of directory entries in directory C<dir>.
3111
3112 All entries in the directory are returned, including C<.> and
3113 C<..>.  The entries are I<not> sorted, but returned in the same
3114 order as the underlying filesystem.
3115
3116 Also this call returns basic file type information about each
3117 file.  The C<ftyp> field will contain one of the following characters:
3118
3119 =over 4
3120
3121 =item 'b'
3122
3123 Block special
3124
3125 =item 'c'
3126
3127 Char special
3128
3129 =item 'd'
3130
3131 Directory
3132
3133 =item 'f'
3134
3135 FIFO (named pipe)
3136
3137 =item 'l'
3138
3139 Symbolic link
3140
3141 =item 'r'
3142
3143 Regular file
3144
3145 =item 's'
3146
3147 Socket
3148
3149 =item 'u'
3150
3151 Unknown file type
3152
3153 =item '?'
3154
3155 The L<readdir(3)> returned a C<d_type> field with an
3156 unexpected value
3157
3158 =back
3159
3160 This function is primarily intended for use by programs.  To
3161 get a simple list of names, use C<guestfs_ls>.  To get a printable
3162 directory for human consumption, use C<guestfs_ll>.");
3163
3164   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3165    [],
3166    "create partitions on a block device",
3167    "\
3168 This is a simplified interface to the C<guestfs_sfdisk>
3169 command, where partition sizes are specified in megabytes
3170 only (rounded to the nearest cylinder) and you don't need
3171 to specify the cyls, heads and sectors parameters which
3172 were rarely if ever used anyway.
3173
3174 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3175 and C<guestfs_part_disk>");
3176
3177   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3178    [],
3179    "determine file type inside a compressed file",
3180    "\
3181 This command runs C<file> after first decompressing C<path>
3182 using C<method>.
3183
3184 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3185
3186 Since 1.0.63, use C<guestfs_file> instead which can now
3187 process compressed files.");
3188
3189   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3190    [],
3191    "list extended attributes of a file or directory",
3192    "\
3193 This call lists the extended attributes of the file or directory
3194 C<path>.
3195
3196 At the system call level, this is a combination of the
3197 L<listxattr(2)> and L<getxattr(2)> calls.
3198
3199 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3200
3201   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3202    [],
3203    "list extended attributes of a file or directory",
3204    "\
3205 This is the same as C<guestfs_getxattrs>, but if C<path>
3206 is a symbolic link, then it returns the extended attributes
3207 of the link itself.");
3208
3209   ("setxattr", (RErr, [String "xattr";
3210                        String "val"; Int "vallen"; (* will be BufferIn *)
3211                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3212    [],
3213    "set extended attribute of a file or directory",
3214    "\
3215 This call sets the extended attribute named C<xattr>
3216 of the file C<path> to the value C<val> (of length C<vallen>).
3217 The value is arbitrary 8 bit data.
3218
3219 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3220
3221   ("lsetxattr", (RErr, [String "xattr";
3222                         String "val"; Int "vallen"; (* will be BufferIn *)
3223                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3224    [],
3225    "set extended attribute of a file or directory",
3226    "\
3227 This is the same as C<guestfs_setxattr>, but if C<path>
3228 is a symbolic link, then it sets an extended attribute
3229 of the link itself.");
3230
3231   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This call removes the extended attribute named C<xattr>
3236 of the file C<path>.
3237
3238 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3239
3240   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3241    [],
3242    "remove extended attribute of a file or directory",
3243    "\
3244 This is the same as C<guestfs_removexattr>, but if C<path>
3245 is a symbolic link, then it removes an extended attribute
3246 of the link itself.");
3247
3248   ("mountpoints", (RHashtable "mps", []), 147, [],
3249    [],
3250    "show mountpoints",
3251    "\
3252 This call is similar to C<guestfs_mounts>.  That call returns
3253 a list of devices.  This one returns a hash table (map) of
3254 device name to directory where the device is mounted.");
3255
3256   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3257    (* This is a special case: while you would expect a parameter
3258     * of type "Pathname", that doesn't work, because it implies
3259     * NEED_ROOT in the generated calling code in stubs.c, and
3260     * this function cannot use NEED_ROOT.
3261     *)
3262    [],
3263    "create a mountpoint",
3264    "\
3265 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3266 specialized calls that can be used to create extra mountpoints
3267 before mounting the first filesystem.
3268
3269 These calls are I<only> necessary in some very limited circumstances,
3270 mainly the case where you want to mount a mix of unrelated and/or
3271 read-only filesystems together.
3272
3273 For example, live CDs often contain a \"Russian doll\" nest of
3274 filesystems, an ISO outer layer, with a squashfs image inside, with
3275 an ext2/3 image inside that.  You can unpack this as follows
3276 in guestfish:
3277
3278  add-ro Fedora-11-i686-Live.iso
3279  run
3280  mkmountpoint /cd
3281  mkmountpoint /squash
3282  mkmountpoint /ext3
3283  mount /dev/sda /cd
3284  mount-loop /cd/LiveOS/squashfs.img /squash
3285  mount-loop /squash/LiveOS/ext3fs.img /ext3
3286
3287 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3288
3289   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3290    [],
3291    "remove a mountpoint",
3292    "\
3293 This calls removes a mountpoint that was previously created
3294 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3295 for full details.");
3296
3297   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputBuffer (
3299       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3300     (* Test various near large, large and too large files (RHBZ#589039). *)
3301     InitBasicFS, Always, TestLastFail (
3302       [["touch"; "/a"];
3303        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3304        ["read_file"; "/a"]]);
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3312        ["read_file"; "/a"]])],
3313    "read a file",
3314    "\
3315 This calls returns the contents of the file C<path> as a
3316 buffer.
3317
3318 Unlike C<guestfs_cat>, this function can correctly
3319 handle files that contain embedded ASCII NUL characters.
3320 However unlike C<guestfs_download>, this function is limited
3321 in the total size of file that can be handled.");
3322
3323   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3326     InitISOFS, Always, TestOutputList (
3327       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3328     (* Test for RHBZ#579608, absolute symbolic links. *)
3329     InitISOFS, Always, TestOutputList (
3330       [["grep"; "nomatch"; "/abssymlink"]], [])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<grep> program and returns the
3334 matching lines.");
3335
3336   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<egrep> program and returns the
3342 matching lines.");
3343
3344   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3345    [InitISOFS, Always, TestOutputList (
3346       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3347    "return lines matching a pattern",
3348    "\
3349 This calls the external C<fgrep> program and returns the
3350 matching lines.");
3351
3352   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3353    [InitISOFS, Always, TestOutputList (
3354       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3355    "return lines matching a pattern",
3356    "\
3357 This calls the external C<grep -i> program and returns the
3358 matching lines.");
3359
3360   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3361    [InitISOFS, Always, TestOutputList (
3362       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3363    "return lines matching a pattern",
3364    "\
3365 This calls the external C<egrep -i> program and returns the
3366 matching lines.");
3367
3368   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3369    [InitISOFS, Always, TestOutputList (
3370       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3371    "return lines matching a pattern",
3372    "\
3373 This calls the external C<fgrep -i> program and returns the
3374 matching lines.");
3375
3376   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3377    [InitISOFS, Always, TestOutputList (
3378       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3379    "return lines matching a pattern",
3380    "\
3381 This calls the external C<zgrep> program and returns the
3382 matching lines.");
3383
3384   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3385    [InitISOFS, Always, TestOutputList (
3386       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3387    "return lines matching a pattern",
3388    "\
3389 This calls the external C<zegrep> program and returns the
3390 matching lines.");
3391
3392   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3393    [InitISOFS, Always, TestOutputList (
3394       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3395    "return lines matching a pattern",
3396    "\
3397 This calls the external C<zfgrep> program and returns the
3398 matching lines.");
3399
3400   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3401    [InitISOFS, Always, TestOutputList (
3402       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3403    "return lines matching a pattern",
3404    "\
3405 This calls the external C<zgrep -i> program and returns the
3406 matching lines.");
3407
3408   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3409    [InitISOFS, Always, TestOutputList (
3410       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3411    "return lines matching a pattern",
3412    "\
3413 This calls the external C<zegrep -i> program and returns the
3414 matching lines.");
3415
3416   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3417    [InitISOFS, Always, TestOutputList (
3418       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3419    "return lines matching a pattern",
3420    "\
3421 This calls the external C<zfgrep -i> program and returns the
3422 matching lines.");
3423
3424   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3425    [InitISOFS, Always, TestOutput (
3426       [["realpath"; "/../directory"]], "/directory")],
3427    "canonicalized absolute pathname",
3428    "\
3429 Return the canonicalized absolute pathname of C<path>.  The
3430 returned path has no C<.>, C<..> or symbolic link path elements.");
3431
3432   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3433    [InitBasicFS, Always, TestOutputStruct (
3434       [["touch"; "/a"];
3435        ["ln"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln> command.");
3440
3441   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3442    [InitBasicFS, Always, TestOutputStruct (
3443       [["touch"; "/a"];
3444        ["touch"; "/b"];
3445        ["ln_f"; "/a"; "/b"];
3446        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3447    "create a hard link",
3448    "\
3449 This command creates a hard link using the C<ln -f> command.
3450 The C<-f> option removes the link (C<linkname>) if it exists already.");
3451
3452   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3453    [InitBasicFS, Always, TestOutputStruct (
3454       [["touch"; "/a"];
3455        ["ln_s"; "a"; "/b"];
3456        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -s> command.");
3460
3461   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3462    [InitBasicFS, Always, TestOutput (
3463       [["mkdir_p"; "/a/b"];
3464        ["touch"; "/a/b/c"];
3465        ["ln_sf"; "../d"; "/a/b/c"];
3466        ["readlink"; "/a/b/c"]], "../d")],
3467    "create a symbolic link",
3468    "\
3469 This command creates a symbolic link using the C<ln -sf> command,
3470 The C<-f> option removes the link (C<linkname>) if it exists already.");
3471
3472   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3473    [] (* XXX tested above *),
3474    "read the target of a symbolic link",
3475    "\
3476 This command reads the target of a symbolic link.");
3477
3478   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3479    [InitBasicFS, Always, TestOutputStruct (
3480       [["fallocate"; "/a"; "1000000"];
3481        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3482    "preallocate a file in the guest filesystem",
3483    "\
3484 This command preallocates a file (containing zero bytes) named
3485 C<path> of size C<len> bytes.  If the file exists already, it
3486 is overwritten.
3487
3488 Do not confuse this with the guestfish-specific
3489 C<alloc> command which allocates a file in the host and
3490 attaches it as a device.");
3491
3492   ("swapon_device", (RErr, [Device "device"]), 170, [],
3493    [InitPartition, Always, TestRun (
3494       [["mkswap"; "/dev/sda1"];
3495        ["swapon_device"; "/dev/sda1"];
3496        ["swapoff_device"; "/dev/sda1"]])],
3497    "enable swap on device",
3498    "\
3499 This command enables the libguestfs appliance to use the
3500 swap device or partition named C<device>.  The increased
3501 memory is made available for all commands, for example
3502 those run using C<guestfs_command> or C<guestfs_sh>.
3503
3504 Note that you should not swap to existing guest swap
3505 partitions unless you know what you are doing.  They may
3506 contain hibernation information, or other information that
3507 the guest doesn't want you to trash.  You also risk leaking
3508 information about the host to the guest this way.  Instead,
3509 attach a new host device to the guest and swap on that.");
3510
3511   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3512    [], (* XXX tested by swapon_device *)
3513    "disable swap on device",
3514    "\
3515 This command disables the libguestfs appliance swap
3516 device or partition named C<device>.
3517 See C<guestfs_swapon_device>.");
3518
3519   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3520    [InitBasicFS, Always, TestRun (
3521       [["fallocate"; "/swap"; "8388608"];
3522        ["mkswap_file"; "/swap"];
3523        ["swapon_file"; "/swap"];
3524        ["swapoff_file"; "/swap"]])],
3525    "enable swap on file",
3526    "\
3527 This command enables swap to a file.
3528 See C<guestfs_swapon_device> for other notes.");
3529
3530   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3531    [], (* XXX tested by swapon_file *)
3532    "disable swap on file",
3533    "\
3534 This command disables the libguestfs appliance swap on file.");
3535
3536   ("swapon_label", (RErr, [String "label"]), 174, [],
3537    [InitEmpty, Always, TestRun (
3538       [["part_disk"; "/dev/sdb"; "mbr"];
3539        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3540        ["swapon_label"; "swapit"];
3541        ["swapoff_label"; "swapit"];
3542        ["zero"; "/dev/sdb"];
3543        ["blockdev_rereadpt"; "/dev/sdb"]])],
3544    "enable swap on labeled swap partition",
3545    "\
3546 This command enables swap to a labeled swap partition.
3547 See C<guestfs_swapon_device> for other notes.");
3548
3549   ("swapoff_label", (RErr, [String "label"]), 175, [],
3550    [], (* XXX tested by swapon_label *)
3551    "disable swap on labeled swap partition",
3552    "\
3553 This command disables the libguestfs appliance swap on
3554 labeled swap partition.");
3555
3556   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3557    (let uuid = uuidgen () in
3558     [InitEmpty, Always, TestRun (
3559        [["mkswap_U"; uuid; "/dev/sdb"];
3560         ["swapon_uuid"; uuid];
3561         ["swapoff_uuid"; uuid]])]),
3562    "enable swap on swap partition by UUID",
3563    "\
3564 This command enables swap to a swap partition with the given UUID.
3565 See C<guestfs_swapon_device> for other notes.");
3566
3567   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3568    [], (* XXX tested by swapon_uuid *)
3569    "disable swap on swap partition by UUID",
3570    "\
3571 This command disables the libguestfs appliance swap partition
3572 with the given UUID.");
3573
3574   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3575    [InitBasicFS, Always, TestRun (
3576       [["fallocate"; "/swap"; "8388608"];
3577        ["mkswap_file"; "/swap"]])],
3578    "create a swap file",
3579    "\
3580 Create a swap file.
3581
3582 This command just writes a swap file signature to an existing
3583 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3584
3585   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3586    [InitISOFS, Always, TestRun (
3587       [["inotify_init"; "0"]])],
3588    "create an inotify handle",
3589    "\
3590 This command creates a new inotify handle.
3591 The inotify subsystem can be used to notify events which happen to
3592 objects in the guest filesystem.
3593
3594 C<maxevents> is the maximum number of events which will be
3595 queued up between calls to C<guestfs_inotify_read> or
3596 C<guestfs_inotify_files>.
3597 If this is passed as C<0>, then the kernel (or previously set)
3598 default is used.  For Linux 2.6.29 the default was 16384 events.
3599 Beyond this limit, the kernel throws away events, but records
3600 the fact that it threw them away by setting a flag
3601 C<IN_Q_OVERFLOW> in the returned structure list (see
3602 C<guestfs_inotify_read>).
3603
3604 Before any events are generated, you have to add some
3605 watches to the internal watch list.  See:
3606 C<guestfs_inotify_add_watch>,
3607 C<guestfs_inotify_rm_watch> and
3608 C<guestfs_inotify_watch_all>.
3609
3610 Queued up events should be read periodically by calling
3611 C<guestfs_inotify_read>
3612 (or C<guestfs_inotify_files> which is just a helpful
3613 wrapper around C<guestfs_inotify_read>).  If you don't
3614 read the events out often enough then you risk the internal
3615 queue overflowing.
3616
3617 The handle should be closed after use by calling
3618 C<guestfs_inotify_close>.  This also removes any
3619 watches automatically.
3620
3621 See also L<inotify(7)> for an overview of the inotify interface
3622 as exposed by the Linux kernel, which is roughly what we expose
3623 via libguestfs.  Note that there is one global inotify handle
3624 per libguestfs instance.");
3625
3626   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3627    [InitBasicFS, Always, TestOutputList (
3628       [["inotify_init"; "0"];
3629        ["inotify_add_watch"; "/"; "1073741823"];
3630        ["touch"; "/a"];
3631        ["touch"; "/b"];
3632        ["inotify_files"]], ["a"; "b"])],
3633    "add an inotify watch",
3634    "\
3635 Watch C<path> for the events listed in C<mask>.
3636
3637 Note that if C<path> is a directory then events within that
3638 directory are watched, but this does I<not> happen recursively
3639 (in subdirectories).
3640
3641 Note for non-C or non-Linux callers: the inotify events are
3642 defined by the Linux kernel ABI and are listed in
3643 C</usr/include/sys/inotify.h>.");
3644
3645   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3646    [],
3647    "remove an inotify watch",
3648    "\
3649 Remove a previously defined inotify watch.
3650 See C<guestfs_inotify_add_watch>.");
3651
3652   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3653    [],
3654    "return list of inotify events",
3655    "\
3656 Return the complete queue of events that have happened
3657 since the previous read call.
3658
3659 If no events have happened, this returns an empty list.
3660
3661 I<Note>: In order to make sure that all events have been
3662 read, you must call this function repeatedly until it
3663 returns an empty list.  The reason is that the call will
3664 read events up to the maximum appliance-to-host message
3665 size and leave remaining events in the queue.");
3666
3667   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3668    [],
3669    "return list of watched files that had events",
3670    "\
3671 This function is a helpful wrapper around C<guestfs_inotify_read>
3672 which just returns a list of pathnames of objects that were
3673 touched.  The returned pathnames are sorted and deduplicated.");
3674
3675   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3676    [],
3677    "close the inotify handle",
3678    "\
3679 This closes the inotify handle which was previously
3680 opened by inotify_init.  It removes all watches, throws
3681 away any pending events, and deallocates all resources.");
3682
3683   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3684    [],
3685    "set SELinux security context",
3686    "\
3687 This sets the SELinux security context of the daemon
3688 to the string C<context>.
3689
3690 See the documentation about SELINUX in L<guestfs(3)>.");
3691
3692   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3693    [],
3694    "get SELinux security context",
3695    "\
3696 This gets the SELinux security context of the daemon.
3697
3698 See the documentation about SELINUX in L<guestfs(3)>,
3699 and C<guestfs_setcon>");
3700
3701   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["part_disk"; "/dev/sda"; "mbr"];
3704        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3705        ["mount_options"; ""; "/dev/sda1"; "/"];
3706        ["write"; "/new"; "new file contents"];
3707        ["cat"; "/new"]], "new file contents")],
3708    "make a filesystem with block size",
3709    "\
3710 This call is similar to C<guestfs_mkfs>, but it allows you to
3711 control the block size of the resulting filesystem.  Supported
3712 block sizes depend on the filesystem type, but typically they
3713 are C<1024>, C<2048> or C<4096> only.");
3714
3715   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3716    [InitEmpty, Always, TestOutput (
3717       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718        ["mke2journal"; "4096"; "/dev/sda1"];
3719        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3720        ["mount_options"; ""; "/dev/sda2"; "/"];
3721        ["write"; "/new"; "new file contents"];
3722        ["cat"; "/new"]], "new file contents")],
3723    "make ext2/3/4 external journal",
3724    "\
3725 This creates an ext2 external journal on C<device>.  It is equivalent
3726 to the command:
3727
3728  mke2fs -O journal_dev -b blocksize device");
3729
3730   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3731    [InitEmpty, Always, TestOutput (
3732       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3733        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3734        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3735        ["mount_options"; ""; "/dev/sda2"; "/"];
3736        ["write"; "/new"; "new file contents"];
3737        ["cat"; "/new"]], "new file contents")],
3738    "make ext2/3/4 external journal with label",
3739    "\
3740 This creates an ext2 external journal on C<device> with label C<label>.");
3741
3742   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3743    (let uuid = uuidgen () in
3744     [InitEmpty, Always, TestOutput (
3745        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3746         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3747         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3748         ["mount_options"; ""; "/dev/sda2"; "/"];
3749         ["write"; "/new"; "new file contents"];
3750         ["cat"; "/new"]], "new file contents")]),
3751    "make ext2/3/4 external journal with UUID",
3752    "\
3753 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3754
3755   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3756    [],
3757    "make ext2/3/4 filesystem with external journal",
3758    "\
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on C<journal>.  It is equivalent
3761 to the command:
3762
3763  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3764
3765 See also C<guestfs_mke2journal>.");
3766
3767   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3768    [],
3769    "make ext2/3/4 filesystem with external journal",
3770    "\
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal labeled C<label>.
3773
3774 See also C<guestfs_mke2journal_L>.");
3775
3776   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3777    [],
3778    "make ext2/3/4 filesystem with external journal",
3779    "\
3780 This creates an ext2/3/4 filesystem on C<device> with
3781 an external journal on the journal with UUID C<uuid>.
3782
3783 See also C<guestfs_mke2journal_U>.");
3784
3785   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3786    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3787    "load a kernel module",
3788    "\
3789 This loads a kernel module in the appliance.
3790
3791 The kernel module must have been whitelisted when libguestfs
3792 was built (see C<appliance/kmod.whitelist.in> in the source).");
3793
3794   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3795    [InitNone, Always, TestOutput (
3796       [["echo_daemon"; "This is a test"]], "This is a test"
3797     )],
3798    "echo arguments back to the client",
3799    "\
3800 This command concatenates the list of C<words> passed with single spaces
3801 between them and returns the resulting string.
3802
3803 You can use this command to test the connection through to the daemon.
3804
3805 See also C<guestfs_ping_daemon>.");
3806
3807   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3808    [], (* There is a regression test for this. *)
3809    "find all files and directories, returning NUL-separated list",
3810    "\
3811 This command lists out all files and directories, recursively,
3812 starting at C<directory>, placing the resulting list in the
3813 external file called C<files>.
3814
3815 This command works the same way as C<guestfs_find> with the
3816 following exceptions:
3817
3818 =over 4
3819
3820 =item *
3821
3822 The resulting list is written to an external file.
3823
3824 =item *
3825
3826 Items (filenames) in the result are separated
3827 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3828
3829 =item *
3830
3831 This command is not limited in the number of names that it
3832 can return.
3833
3834 =item *
3835
3836 The result list is not sorted.
3837
3838 =back");
3839
3840   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3841    [InitISOFS, Always, TestOutput (
3842       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3843     InitISOFS, Always, TestOutput (
3844       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3845     InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3847     InitISOFS, Always, TestLastFail (
3848       [["case_sensitive_path"; "/Known-1/"]]);
3849     InitBasicFS, Always, TestOutput (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3854     InitBasicFS, Always, TestOutput (
3855       [["mkdir"; "/a"];
3856        ["mkdir"; "/a/bbb"];
3857        ["touch"; "/a/bbb/c"];
3858        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3859     InitBasicFS, Always, TestLastFail (
3860       [["mkdir"; "/a"];
3861        ["mkdir"; "/a/bbb"];
3862        ["touch"; "/a/bbb/c"];
3863        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3864    "return true path on case-insensitive filesystem",
3865    "\
3866 This can be used to resolve case insensitive paths on
3867 a filesystem which is case sensitive.  The use case is
3868 to resolve paths which you have read from Windows configuration
3869 files or the Windows Registry, to the true path.
3870
3871 The command handles a peculiarity of the Linux ntfs-3g
3872 filesystem driver (and probably others), which is that although
3873 the underlying filesystem is case-insensitive, the driver
3874 exports the filesystem to Linux as case-sensitive.
3875
3876 One consequence of this is that special directories such
3877 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3878 (or other things) depending on the precise details of how
3879 they were created.  In Windows itself this would not be
3880 a problem.
3881
3882 Bug or feature?  You decide:
3883 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3884
3885 This function resolves the true case of each element in the
3886 path and returns the case-sensitive path.
3887
3888 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3889 might return C<\"/WINDOWS/system32\"> (the exact return value
3890 would depend on details of how the directories were originally
3891 created under Windows).
3892
3893 I<Note>:
3894 This function does not handle drive names, backslashes etc.
3895
3896 See also C<guestfs_realpath>.");
3897
3898   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3899    [InitBasicFS, Always, TestOutput (
3900       [["vfs_type"; "/dev/sda1"]], "ext2")],
3901    "get the Linux VFS type corresponding to a mounted device",
3902    "\
3903 This command gets the block device type corresponding to
3904 a mounted device called C<device>.
3905
3906 Usually the result is the name of the Linux VFS module that
3907 is used to mount this device (probably determined automatically
3908 if you used the C<guestfs_mount> call).");
3909
3910   ("truncate", (RErr, [Pathname "path"]), 199, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["write"; "/test"; "some stuff so size is not zero"];
3913        ["truncate"; "/test"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3915    "truncate a file to zero size",
3916    "\
3917 This command truncates C<path> to a zero-length file.  The
3918 file must exist already.");
3919
3920   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3921    [InitBasicFS, Always, TestOutputStruct (
3922       [["touch"; "/test"];
3923        ["truncate_size"; "/test"; "1000"];
3924        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3925    "truncate a file to a particular size",
3926    "\
3927 This command truncates C<path> to size C<size> bytes.  The file
3928 must exist already.  If the file is smaller than C<size> then
3929 the file is extended to the required size with null bytes.");
3930
3931   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3932    [InitBasicFS, Always, TestOutputStruct (
3933       [["touch"; "/test"];
3934        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3935        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3936    "set timestamp of a file with nanosecond precision",
3937    "\
3938 This command sets the timestamps of a file with nanosecond
3939 precision.
3940
3941 C<atsecs, atnsecs> are the last access time (atime) in secs and
3942 nanoseconds from the epoch.
3943
3944 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3945 secs and nanoseconds from the epoch.
3946
3947 If the C<*nsecs> field contains the special value C<-1> then
3948 the corresponding timestamp is set to the current time.  (The
3949 C<*secs> field is ignored in this case).
3950
3951 If the C<*nsecs> field contains the special value C<-2> then
3952 the corresponding timestamp is left unchanged.  (The
3953 C<*secs> field is ignored in this case).");
3954
3955   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3956    [InitBasicFS, Always, TestOutputStruct (
3957       [["mkdir_mode"; "/test"; "0o111"];
3958        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3959    "create a directory with a particular mode",
3960    "\
3961 This command creates a directory, setting the initial permissions
3962 of the directory to C<mode>.
3963
3964 For common Linux filesystems, the actual mode which is set will
3965 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3966 interpret the mode in other ways.
3967
3968 See also C<guestfs_mkdir>, C<guestfs_umask>");
3969
3970   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3971    [], (* XXX *)
3972    "change file owner and group",
3973    "\
3974 Change the file owner to C<owner> and group to C<group>.
3975 This is like C<guestfs_chown> but if C<path> is a symlink then
3976 the link itself is changed, not the target.
3977
3978 Only numeric uid and gid are supported.  If you want to use
3979 names, you will need to locate and parse the password file
3980 yourself (Augeas support makes this relatively easy).");
3981
3982   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3983    [], (* XXX *)
3984    "lstat on multiple files",
3985    "\
3986 This call allows you to perform the C<guestfs_lstat> operation
3987 on multiple files, where all files are in the directory C<path>.
3988 C<names> is the list of files from this directory.
3989
3990 On return you get a list of stat structs, with a one-to-one
3991 correspondence to the C<names> list.  If any name did not exist
3992 or could not be lstat'd, then the C<ino> field of that structure
3993 is set to C<-1>.
3994
3995 This call is intended for programs that want to efficiently
3996 list a directory contents without making many round-trips.
3997 See also C<guestfs_lxattrlist> for a similarly efficient call
3998 for getting extended attributes.  Very long directory listings
3999 might cause the protocol message size to be exceeded, causing
4000 this call to fail.  The caller must split up such requests
4001 into smaller groups of names.");
4002
4003   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4004    [], (* XXX *)
4005    "lgetxattr on multiple files",
4006    "\
4007 This call allows you to get the extended attributes
4008 of multiple files, where all files are in the directory C<path>.
4009 C<names> is the list of files from this directory.
4010
4011 On return you get a flat list of xattr structs which must be
4012 interpreted sequentially.  The first xattr struct always has a zero-length
4013 C<attrname>.  C<attrval> in this struct is zero-length
4014 to indicate there was an error doing C<lgetxattr> for this
4015 file, I<or> is a C string which is a decimal number
4016 (the number of following attributes for this file, which could
4017 be C<\"0\">).  Then after the first xattr struct are the
4018 zero or more attributes for the first named file.
4019 This repeats for the second and subsequent files.
4020
4021 This call is intended for programs that want to efficiently
4022 list a directory contents without making many round-trips.
4023 See also C<guestfs_lstatlist> for a similarly efficient call
4024 for getting standard stats.  Very long directory listings
4025 might cause the protocol message size to be exceeded, causing
4026 this call to fail.  The caller must split up such requests
4027 into smaller groups of names.");
4028
4029   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4030    [], (* XXX *)
4031    "readlink on multiple files",
4032    "\
4033 This call allows you to do a C<readlink> operation
4034 on multiple files, where all files are in the directory C<path>.
4035 C<names> is the list of files from this directory.
4036
4037 On return you get a list of strings, with a one-to-one
4038 correspondence to the C<names> list.  Each string is the
4039 value of the symbol link.
4040
4041 If the C<readlink(2)> operation fails on any name, then
4042 the corresponding result string is the empty string C<\"\">.
4043 However the whole operation is completed even if there
4044 were C<readlink(2)> errors, and so you can call this
4045 function with names where you don't know if they are
4046 symbolic links already (albeit slightly less efficient).
4047
4048 This call is intended for programs that want to efficiently
4049 list a directory contents without making many round-trips.
4050 Very long directory listings might cause the protocol
4051 message size to be exceeded, causing
4052 this call to fail.  The caller must split up such requests
4053 into smaller groups of names.");
4054
4055   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4056    [InitISOFS, Always, TestOutputBuffer (
4057       [["pread"; "/known-4"; "1"; "3"]], "\n");
4058     InitISOFS, Always, TestOutputBuffer (
4059       [["pread"; "/empty"; "0"; "100"]], "")],
4060    "read part of a file",
4061    "\
4062 This command lets you read part of a file.  It reads C<count>
4063 bytes of the file, starting at C<offset>, from file C<path>.
4064
4065 This may read fewer bytes than requested.  For further details
4066 see the L<pread(2)> system call.
4067
4068 See also C<guestfs_pwrite>.");
4069
4070   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4071    [InitEmpty, Always, TestRun (
4072       [["part_init"; "/dev/sda"; "gpt"]])],
4073    "create an empty partition table",
4074    "\
4075 This creates an empty partition table on C<device> of one of the
4076 partition types listed below.  Usually C<parttype> should be
4077 either C<msdos> or C<gpt> (for large disks).
4078
4079 Initially there are no partitions.  Following this, you should
4080 call C<guestfs_part_add> for each partition required.
4081
4082 Possible values for C<parttype> are:
4083
4084 =over 4
4085
4086 =item B<efi> | B<gpt>
4087
4088 Intel EFI / GPT partition table.
4089
4090 This is recommended for >= 2 TB partitions that will be accessed
4091 from Linux and Intel-based Mac OS X.  It also has limited backwards
4092 compatibility with the C<mbr> format.
4093
4094 =item B<mbr> | B<msdos>
4095
4096 The standard PC \"Master Boot Record\" (MBR) format used
4097 by MS-DOS and Windows.  This partition type will B<only> work
4098 for device sizes up to 2 TB.  For large disks we recommend
4099 using C<gpt>.
4100
4101 =back
4102
4103 Other partition table types that may work but are not
4104 supported include:
4105
4106 =over 4
4107
4108 =item B<aix>
4109
4110 AIX disk labels.
4111
4112 =item B<amiga> | B<rdb>
4113
4114 Amiga \"Rigid Disk Block\" format.
4115
4116 =item B<bsd>
4117
4118 BSD disk labels.
4119
4120 =item B<dasd>
4121
4122 DASD, used on IBM mainframes.
4123
4124 =item B<dvh>
4125
4126 MIPS/SGI volumes.
4127
4128 =item B<mac>
4129
4130 Old Mac partition format.  Modern Macs use C<gpt>.
4131
4132 =item B<pc98>
4133
4134 NEC PC-98 format, common in Japan apparently.
4135
4136 =item B<sun>
4137
4138 Sun disk labels.
4139
4140 =back");
4141
4142   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4143    [InitEmpty, Always, TestRun (
4144       [["part_init"; "/dev/sda"; "mbr"];
4145        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4146     InitEmpty, Always, TestRun (
4147       [["part_init"; "/dev/sda"; "gpt"];
4148        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4149        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4150     InitEmpty, Always, TestRun (
4151       [["part_init"; "/dev/sda"; "mbr"];
4152        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4153        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4154        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4155        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4156    "add a partition to the device",
4157    "\
4158 This command adds a partition to C<device>.  If there is no partition
4159 table on the device, call C<guestfs_part_init> first.
4160
4161 The C<prlogex> parameter is the type of partition.  Normally you
4162 should pass C<p> or C<primary> here, but MBR partition tables also
4163 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4164 types.
4165
4166 C<startsect> and C<endsect> are the start and end of the partition
4167 in I<sectors>.  C<endsect> may be negative, which means it counts
4168 backwards from the end of the disk (C<-1> is the last sector).
4169
4170 Creating a partition which covers the whole disk is not so easy.
4171 Use C<guestfs_part_disk> to do that.");
4172
4173   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4174    [InitEmpty, Always, TestRun (
4175       [["part_disk"; "/dev/sda"; "mbr"]]);
4176     InitEmpty, Always, TestRun (
4177       [["part_disk"; "/dev/sda"; "gpt"]])],
4178    "partition whole disk with a single primary partition",
4179    "\
4180 This command is simply a combination of C<guestfs_part_init>
4181 followed by C<guestfs_part_add> to create a single primary partition
4182 covering the whole disk.
4183
4184 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4185 but other possible values are described in C<guestfs_part_init>.");
4186
4187   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4188    [InitEmpty, Always, TestRun (
4189       [["part_disk"; "/dev/sda"; "mbr"];
4190        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4191    "make a partition bootable",
4192    "\
4193 This sets the bootable flag on partition numbered C<partnum> on
4194 device C<device>.  Note that partitions are numbered from 1.
4195
4196 The bootable flag is used by some operating systems (notably
4197 Windows) to determine which partition to boot from.  It is by
4198 no means universally recognized.");
4199
4200   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4201    [InitEmpty, Always, TestRun (
4202       [["part_disk"; "/dev/sda"; "gpt"];
4203        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4204    "set partition name",
4205    "\
4206 This sets the partition name on partition numbered C<partnum> on
4207 device C<device>.  Note that partitions are numbered from 1.
4208
4209 The partition name can only be set on certain types of partition
4210 table.  This works on C<gpt> but not on C<mbr> partitions.");
4211
4212   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4213    [], (* XXX Add a regression test for this. *)
4214    "list partitions on a device",
4215    "\
4216 This command parses the partition table on C<device> and
4217 returns the list of partitions found.
4218
4219 The fields in the returned structure are:
4220
4221 =over 4
4222
4223 =item B<part_num>
4224
4225 Partition number, counting from 1.
4226
4227 =item B<part_start>
4228
4229 Start of the partition I<in bytes>.  To get sectors you have to
4230 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4231
4232 =item B<part_end>
4233
4234 End of the partition in bytes.
4235
4236 =item B<part_size>
4237
4238 Size of the partition in bytes.
4239
4240 =back");
4241
4242   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4243    [InitEmpty, Always, TestOutput (
4244       [["part_disk"; "/dev/sda"; "gpt"];
4245        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4246    "get the partition table type",
4247    "\
4248 This command examines the partition table on C<device> and
4249 returns the partition table type (format) being used.
4250
4251 Common return values include: C<msdos> (a DOS/Windows style MBR
4252 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4253 values are possible, although unusual.  See C<guestfs_part_init>
4254 for a full list.");
4255
4256   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4257    [InitBasicFS, Always, TestOutputBuffer (
4258       [["fill"; "0x63"; "10"; "/test"];
4259        ["read_file"; "/test"]], "cccccccccc")],
4260    "fill a file with octets",
4261    "\
4262 This command creates a new file called C<path>.  The initial
4263 content of the file is C<len> octets of C<c>, where C<c>
4264 must be a number in the range C<[0..255]>.
4265
4266 To fill a file with zero bytes (sparsely), it is
4267 much more efficient to use C<guestfs_truncate_size>.
4268 To create a file with a pattern of repeating bytes
4269 use C<guestfs_fill_pattern>.");
4270
4271   ("available", (RErr, [StringList "groups"]), 216, [],
4272    [InitNone, Always, TestRun [["available"; ""]]],
4273    "test availability of some parts of the API",
4274    "\
4275 This command is used to check the availability of some
4276 groups of functionality in the appliance, which not all builds of
4277 the libguestfs appliance will be able to provide.
4278
4279 The libguestfs groups, and the functions that those
4280 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4281 You can also fetch this list at runtime by calling
4282 C<guestfs_available_all_groups>.
4283
4284 The argument C<groups> is a list of group names, eg:
4285 C<[\"inotify\", \"augeas\"]> would check for the availability of
4286 the Linux inotify functions and Augeas (configuration file
4287 editing) functions.
4288
4289 The command returns no error if I<all> requested groups are available.
4290
4291 It fails with an error if one or more of the requested
4292 groups is unavailable in the appliance.
4293
4294 If an unknown group name is included in the
4295 list of groups then an error is always returned.
4296
4297 I<Notes:>
4298
4299 =over 4
4300
4301 =item *
4302
4303 You must call C<guestfs_launch> before calling this function.
4304
4305 The reason is because we don't know what groups are
4306 supported by the appliance/daemon until it is running and can
4307 be queried.
4308
4309 =item *
4310
4311 If a group of functions is available, this does not necessarily
4312 mean that they will work.  You still have to check for errors
4313 when calling individual API functions even if they are
4314 available.
4315
4316 =item *
4317
4318 It is usually the job of distro packagers to build
4319 complete functionality into the libguestfs appliance.
4320 Upstream libguestfs, if built from source with all
4321 requirements satisfied, will support everything.
4322
4323 =item *
4324
4325 This call was added in version C<1.0.80>.  In previous
4326 versions of libguestfs all you could do would be to speculatively
4327 execute a command to find out if the daemon implemented it.
4328 See also C<guestfs_version>.
4329
4330 =back");
4331
4332   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4333    [InitBasicFS, Always, TestOutputBuffer (
4334       [["write"; "/src"; "hello, world"];
4335        ["dd"; "/src"; "/dest"];
4336        ["read_file"; "/dest"]], "hello, world")],
4337    "copy from source to destination using dd",
4338    "\
4339 This command copies from one source device or file C<src>
4340 to another destination device or file C<dest>.  Normally you
4341 would use this to copy to or from a device or partition, for
4342 example to duplicate a filesystem.
4343
4344 If the destination is a device, it must be as large or larger
4345 than the source file or device, otherwise the copy will fail.
4346 This command cannot do partial copies (see C<guestfs_copy_size>).");
4347
4348   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4349    [InitBasicFS, Always, TestOutputInt (
4350       [["write"; "/file"; "hello, world"];
4351        ["filesize"; "/file"]], 12)],
4352    "return the size of the file in bytes",
4353    "\
4354 This command returns the size of C<file> in bytes.
4355
4356 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4357 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4358 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4359
4360   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4361    [InitBasicFSonLVM, Always, TestOutputList (
4362       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4363        ["lvs"]], ["/dev/VG/LV2"])],
4364    "rename an LVM logical volume",
4365    "\
4366 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4367
4368   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4369    [InitBasicFSonLVM, Always, TestOutputList (
4370       [["umount"; "/"];
4371        ["vg_activate"; "false"; "VG"];
4372        ["vgrename"; "VG"; "VG2"];
4373        ["vg_activate"; "true"; "VG2"];
4374        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4375        ["vgs"]], ["VG2"])],
4376    "rename an LVM volume group",
4377    "\
4378 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4379
4380   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4381    [InitISOFS, Always, TestOutputBuffer (
4382       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4383    "list the contents of a single file in an initrd",
4384    "\
4385 This command unpacks the file C<filename> from the initrd file
4386 called C<initrdpath>.  The filename must be given I<without> the
4387 initial C</> character.
4388
4389 For example, in guestfish you could use the following command
4390 to examine the boot script (usually called C</init>)
4391 contained in a Linux initrd or initramfs image:
4392
4393  initrd-cat /boot/initrd-<version>.img init
4394
4395 See also C<guestfs_initrd_list>.");
4396
4397   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4398    [],
4399    "get the UUID of a physical volume",
4400    "\
4401 This command returns the UUID of the LVM PV C<device>.");
4402
4403   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4404    [],
4405    "get the UUID of a volume group",
4406    "\
4407 This command returns the UUID of the LVM VG named C<vgname>.");
4408
4409   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4410    [],
4411    "get the UUID of a logical volume",
4412    "\
4413 This command returns the UUID of the LVM LV C<device>.");
4414
4415   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4416    [],
4417    "get the PV UUIDs containing the volume group",
4418    "\
4419 Given a VG called C<vgname>, this returns the UUIDs of all
4420 the physical volumes that this volume group resides on.
4421
4422 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4423 calls to associate physical volumes and volume groups.
4424
4425 See also C<guestfs_vglvuuids>.");
4426
4427   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4428    [],
4429    "get the LV UUIDs of all LVs in the volume group",
4430    "\
4431 Given a VG called C<vgname>, this returns the UUIDs of all
4432 the logical volumes created in this volume group.
4433
4434 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4435 calls to associate logical volumes and volume groups.
4436
4437 See also C<guestfs_vgpvuuids>.");
4438
4439   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4440    [InitBasicFS, Always, TestOutputBuffer (
4441       [["write"; "/src"; "hello, world"];
4442        ["copy_size"; "/src"; "/dest"; "5"];
4443        ["read_file"; "/dest"]], "hello")],
4444    "copy size bytes from source to destination using dd",
4445    "\
4446 This command copies exactly C<size> bytes from one source device
4447 or file C<src> to another destination device or file C<dest>.
4448
4449 Note this will fail if the source is too short or if the destination
4450 is not large enough.");
4451
4452   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4453    [InitBasicFSonLVM, Always, TestRun (
4454       [["zero_device"; "/dev/VG/LV"]])],
4455    "write zeroes to an entire device",
4456    "\
4457 This command writes zeroes over the entire C<device>.  Compare
4458 with C<guestfs_zero> which just zeroes the first few blocks of
4459 a device.");
4460
4461   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4462    [InitBasicFS, Always, TestOutput (
4463       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4464        ["cat"; "/hello"]], "hello\n")],
4465    "unpack compressed tarball to directory",
4466    "\
4467 This command uploads and unpacks local file C<tarball> (an
4468 I<xz compressed> tar file) into C<directory>.");
4469
4470   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4471    [],
4472    "pack directory into compressed tarball",
4473    "\
4474 This command packs the contents of C<directory> and downloads
4475 it to local file C<tarball> (as an xz compressed tar archive).");
4476
4477   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4478    [],
4479    "resize an NTFS filesystem",
4480    "\
4481 This command resizes an NTFS filesystem, expanding or
4482 shrinking it to the size of the underlying device.
4483 See also L<ntfsresize(8)>.");
4484
4485   ("vgscan", (RErr, []), 232, [],
4486    [InitEmpty, Always, TestRun (
4487       [["vgscan"]])],
4488    "rescan for LVM physical volumes, volume groups and logical volumes",
4489    "\
4490 This rescans all block devices and rebuilds the list of LVM
4491 physical volumes, volume groups and logical volumes.");
4492
4493   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4494    [InitEmpty, Always, TestRun (
4495       [["part_init"; "/dev/sda"; "mbr"];
4496        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4497        ["part_del"; "/dev/sda"; "1"]])],
4498    "delete a partition",
4499    "\
4500 This command deletes the partition numbered C<partnum> on C<device>.
4501
4502 Note that in the case of MBR partitioning, deleting an
4503 extended partition also deletes any logical partitions
4504 it contains.");
4505
4506   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4507    [InitEmpty, Always, TestOutputTrue (
4508       [["part_init"; "/dev/sda"; "mbr"];
4509        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4510        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4511        ["part_get_bootable"; "/dev/sda"; "1"]])],
4512    "return true if a partition is bootable",
4513    "\
4514 This command returns true if the partition C<partnum> on
4515 C<device> has the bootable flag set.
4516
4517 See also C<guestfs_part_set_bootable>.");
4518
4519   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4520    [InitEmpty, Always, TestOutputInt (
4521       [["part_init"; "/dev/sda"; "mbr"];
4522        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4523        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4524        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4525    "get the MBR type byte (ID byte) from a partition",
4526    "\
4527 Returns the MBR type byte (also known as the ID byte) from
4528 the numbered partition C<partnum>.
4529
4530 Note that only MBR (old DOS-style) partitions have type bytes.
4531 You will get undefined results for other partition table
4532 types (see C<guestfs_part_get_parttype>).");
4533
4534   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4535    [], (* tested by part_get_mbr_id *)
4536    "set the MBR type byte (ID byte) of a partition",
4537    "\
4538 Sets the MBR type byte (also known as the ID byte) of
4539 the numbered partition C<partnum> to C<idbyte>.  Note
4540 that the type bytes quoted in most documentation are
4541 in fact hexadecimal numbers, but usually documented
4542 without any leading \"0x\" which might be confusing.
4543
4544 Note that only MBR (old DOS-style) partitions have type bytes.
4545 You will get undefined results for other partition table
4546 types (see C<guestfs_part_get_parttype>).");
4547
4548   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4549    [InitISOFS, Always, TestOutput (
4550       [["checksum_device"; "md5"; "/dev/sdd"]],
4551       (Digest.to_hex (Digest.file "images/test.iso")))],
4552    "compute MD5, SHAx or CRC checksum of the contents of a device",
4553    "\
4554 This call computes the MD5, SHAx or CRC checksum of the
4555 contents of the device named C<device>.  For the types of
4556 checksums supported see the C<guestfs_checksum> command.");
4557
4558   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4559    [InitNone, Always, TestRun (
4560       [["part_disk"; "/dev/sda"; "mbr"];
4561        ["pvcreate"; "/dev/sda1"];
4562        ["vgcreate"; "VG"; "/dev/sda1"];
4563        ["lvcreate"; "LV"; "VG"; "10"];
4564        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4565    "expand an LV to fill free space",
4566    "\
4567 This expands an existing logical volume C<lv> so that it fills
4568 C<pc>% of the remaining free space in the volume group.  Commonly
4569 you would call this with pc = 100 which expands the logical volume
4570 as much as possible, using all remaining free space in the volume
4571 group.");
4572
4573   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4574    [], (* XXX Augeas code needs tests. *)
4575    "clear Augeas path",
4576    "\
4577 Set the value associated with C<path> to C<NULL>.  This
4578 is the same as the L<augtool(1)> C<clear> command.");
4579
4580   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4581    [InitEmpty, Always, TestOutputInt (
4582       [["get_umask"]], 0o22)],
4583    "get the current umask",
4584    "\
4585 Return the current umask.  By default the umask is C<022>
4586 unless it has been set by calling C<guestfs_umask>.");
4587
4588   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4589    [],
4590    "upload a file to the appliance (internal use only)",
4591    "\
4592 The C<guestfs_debug_upload> command uploads a file to
4593 the libguestfs appliance.
4594
4595 There is no comprehensive help for this command.  You have
4596 to look at the file C<daemon/debug.c> in the libguestfs source
4597 to find out what it is for.");
4598
4599   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4600    [InitBasicFS, Always, TestOutput (
4601       [["base64_in"; "../images/hello.b64"; "/hello"];
4602        ["cat"; "/hello"]], "hello\n")],
4603    "upload base64-encoded data to file",
4604    "\
4605 This command uploads base64-encoded data from C<base64file>
4606 to C<filename>.");
4607
4608   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4609    [],
4610    "download file and encode as base64",
4611    "\
4612 This command downloads the contents of C<filename>, writing
4613 it out to local file C<base64file> encoded as base64.");
4614
4615   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4616    [],
4617    "compute MD5, SHAx or CRC checksum of files in a directory",
4618    "\
4619 This command computes the checksums of all regular files in
4620 C<directory> and then emits a list of those checksums to
4621 the local output file C<sumsfile>.
4622
4623 This can be used for verifying the integrity of a virtual
4624 machine.  However to be properly secure you should pay
4625 attention to the output of the checksum command (it uses
4626 the ones from GNU coreutils).  In particular when the
4627 filename is not printable, coreutils uses a special
4628 backslash syntax.  For more information, see the GNU
4629 coreutils info file.");
4630
4631   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4632    [InitBasicFS, Always, TestOutputBuffer (
4633       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4634        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4635    "fill a file with a repeating pattern of bytes",
4636    "\
4637 This function is like C<guestfs_fill> except that it creates
4638 a new file of length C<len> containing the repeating pattern
4639 of bytes in C<pattern>.  The pattern is truncated if necessary
4640 to ensure the length of the file is exactly C<len> bytes.");
4641
4642   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4643    [InitBasicFS, Always, TestOutput (
4644       [["write"; "/new"; "new file contents"];
4645        ["cat"; "/new"]], "new file contents");
4646     InitBasicFS, Always, TestOutput (
4647       [["write"; "/new"; "\nnew file contents\n"];
4648        ["cat"; "/new"]], "\nnew file contents\n");
4649     InitBasicFS, Always, TestOutput (
4650       [["write"; "/new"; "\n\n"];
4651        ["cat"; "/new"]], "\n\n");
4652     InitBasicFS, Always, TestOutput (
4653       [["write"; "/new"; ""];
4654        ["cat"; "/new"]], "");
4655     InitBasicFS, Always, TestOutput (
4656       [["write"; "/new"; "\n\n\n"];
4657        ["cat"; "/new"]], "\n\n\n");
4658     InitBasicFS, Always, TestOutput (
4659       [["write"; "/new"; "\n"];
4660        ["cat"; "/new"]], "\n")],
4661    "create a new file",
4662    "\
4663 This call creates a file called C<path>.  The content of the
4664 file is the string C<content> (which can contain any 8 bit data).");
4665
4666   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4667    [InitBasicFS, Always, TestOutput (
4668       [["write"; "/new"; "new file contents"];
4669        ["pwrite"; "/new"; "data"; "4"];
4670        ["cat"; "/new"]], "new data contents");
4671     InitBasicFS, Always, TestOutput (
4672       [["write"; "/new"; "new file contents"];
4673        ["pwrite"; "/new"; "is extended"; "9"];
4674        ["cat"; "/new"]], "new file is extended");
4675     InitBasicFS, Always, TestOutput (
4676       [["write"; "/new"; "new file contents"];
4677        ["pwrite"; "/new"; ""; "4"];
4678        ["cat"; "/new"]], "new file contents")],
4679    "write to part of a file",
4680    "\
4681 This command writes to part of a file.  It writes the data
4682 buffer C<content> to the file C<path> starting at offset C<offset>.
4683
4684 This command implements the L<pwrite(2)> system call, and like
4685 that system call it may not write the full data requested.  The
4686 return value is the number of bytes that were actually written
4687 to the file.  This could even be 0, although short writes are
4688 unlikely for regular files in ordinary circumstances.
4689
4690 See also C<guestfs_pread>.");
4691
4692   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4693    [],
4694    "resize an ext2/ext3 filesystem (with size)",
4695    "\
4696 This command is the same as C<guestfs_resize2fs> except that it
4697 allows you to specify the new size (in bytes) explicitly.");
4698
4699   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4700    [],
4701    "resize an LVM physical volume (with size)",
4702    "\
4703 This command is the same as C<guestfs_pvresize> except that it
4704 allows you to specify the new size (in bytes) explicitly.");
4705
4706   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4707    [],
4708    "resize an NTFS filesystem (with size)",
4709    "\
4710 This command is the same as C<guestfs_ntfsresize> except that it
4711 allows you to specify the new size (in bytes) explicitly.");
4712
4713   ("available_all_groups", (RStringList "groups", []), 251, [],
4714    [InitNone, Always, TestRun [["available_all_groups"]]],
4715    "return a list of all optional groups",
4716    "\
4717 This command returns a list of all optional groups that this
4718 daemon knows about.  Note this returns both supported and unsupported
4719 groups.  To find out which ones the daemon can actually support
4720 you have to call C<guestfs_available> on each member of the
4721 returned list.
4722
4723 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4724
4725   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4726    [InitBasicFS, Always, TestOutputStruct (
4727       [["fallocate64"; "/a"; "1000000"];
4728        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4729    "preallocate a file in the guest filesystem",
4730    "\
4731 This command preallocates a file (containing zero bytes) named
4732 C<path> of size C<len> bytes.  If the file exists already, it
4733 is overwritten.
4734
4735 Note that this call allocates disk blocks for the file.
4736 To create a sparse file use C<guestfs_truncate_size> instead.
4737
4738 The deprecated call C<guestfs_fallocate> does the same,
4739 but owing to an oversight it only allowed 30 bit lengths
4740 to be specified, effectively limiting the maximum size
4741 of files created through that call to 1GB.
4742
4743 Do not confuse this with the guestfish-specific
4744 C<alloc> and C<sparse> commands which create
4745 a file in the host and attach it as a device.");
4746
4747 ]
4748
4749 let all_functions = non_daemon_functions @ daemon_functions
4750
4751 (* In some places we want the functions to be displayed sorted
4752  * alphabetically, so this is useful:
4753  *)
4754 let all_functions_sorted =
4755   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4756                compare n1 n2) all_functions
4757
4758 (* This is used to generate the src/MAX_PROC_NR file which
4759  * contains the maximum procedure number, a surrogate for the
4760  * ABI version number.  See src/Makefile.am for the details.
4761  *)
4762 let max_proc_nr =
4763   let proc_nrs = List.map (
4764     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4765   ) daemon_functions in
4766   List.fold_left max 0 proc_nrs
4767
4768 (* Field types for structures. *)
4769 type field =
4770   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4771   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4772   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4773   | FUInt32
4774   | FInt32
4775   | FUInt64
4776   | FInt64
4777   | FBytes                      (* Any int measure that counts bytes. *)
4778   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4779   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4780
4781 (* Because we generate extra parsing code for LVM command line tools,
4782  * we have to pull out the LVM columns separately here.
4783  *)
4784 let lvm_pv_cols = [
4785   "pv_name", FString;
4786   "pv_uuid", FUUID;
4787   "pv_fmt", FString;
4788   "pv_size", FBytes;
4789   "dev_size", FBytes;
4790   "pv_free", FBytes;
4791   "pv_used", FBytes;
4792   "pv_attr", FString (* XXX *);
4793   "pv_pe_count", FInt64;
4794   "pv_pe_alloc_count", FInt64;
4795   "pv_tags", FString;
4796   "pe_start", FBytes;
4797   "pv_mda_count", FInt64;
4798   "pv_mda_free", FBytes;
4799   (* Not in Fedora 10:
4800      "pv_mda_size", FBytes;
4801   *)
4802 ]
4803 let lvm_vg_cols = [
4804   "vg_name", FString;
4805   "vg_uuid", FUUID;
4806   "vg_fmt", FString;
4807   "vg_attr", FString (* XXX *);
4808   "vg_size", FBytes;
4809   "vg_free", FBytes;
4810   "vg_sysid", FString;
4811   "vg_extent_size", FBytes;
4812   "vg_extent_count", FInt64;
4813   "vg_free_count", FInt64;
4814   "max_lv", FInt64;
4815   "max_pv", FInt64;
4816   "pv_count", FInt64;
4817   "lv_count", FInt64;
4818   "snap_count", FInt64;
4819   "vg_seqno", FInt64;
4820   "vg_tags", FString;
4821   "vg_mda_count", FInt64;
4822   "vg_mda_free", FBytes;
4823   (* Not in Fedora 10:
4824      "vg_mda_size", FBytes;
4825   *)
4826 ]
4827 let lvm_lv_cols = [
4828   "lv_name", FString;
4829   "lv_uuid", FUUID;
4830   "lv_attr", FString (* XXX *);
4831   "lv_major", FInt64;
4832   "lv_minor", FInt64;
4833   "lv_kernel_major", FInt64;
4834   "lv_kernel_minor", FInt64;
4835   "lv_size", FBytes;
4836   "seg_count", FInt64;
4837   "origin", FString;
4838   "snap_percent", FOptPercent;
4839   "copy_percent", FOptPercent;
4840   "move_pv", FString;
4841   "lv_tags", FString;
4842   "mirror_log", FString;
4843   "modules", FString;
4844 ]
4845
4846 (* Names and fields in all structures (in RStruct and RStructList)
4847  * that we support.
4848  *)
4849 let structs = [
4850   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4851    * not use this struct in any new code.
4852    *)
4853   "int_bool", [
4854     "i", FInt32;                (* for historical compatibility *)
4855     "b", FInt32;                (* for historical compatibility *)
4856   ];
4857
4858   (* LVM PVs, VGs, LVs. *)
4859   "lvm_pv", lvm_pv_cols;
4860   "lvm_vg", lvm_vg_cols;
4861   "lvm_lv", lvm_lv_cols;
4862
4863   (* Column names and types from stat structures.
4864    * NB. Can't use things like 'st_atime' because glibc header files
4865    * define some of these as macros.  Ugh.
4866    *)
4867   "stat", [
4868     "dev", FInt64;
4869     "ino", FInt64;
4870     "mode", FInt64;
4871     "nlink", FInt64;
4872     "uid", FInt64;
4873     "gid", FInt64;
4874     "rdev", FInt64;
4875     "size", FInt64;
4876     "blksize", FInt64;
4877     "blocks", FInt64;
4878     "atime", FInt64;
4879     "mtime", FInt64;
4880     "ctime", FInt64;
4881   ];
4882   "statvfs", [
4883     "bsize", FInt64;
4884     "frsize", FInt64;
4885     "blocks", FInt64;
4886     "bfree", FInt64;
4887     "bavail", FInt64;
4888     "files", FInt64;
4889     "ffree", FInt64;
4890     "favail", FInt64;
4891     "fsid", FInt64;
4892     "flag", FInt64;
4893     "namemax", FInt64;
4894   ];
4895
4896   (* Column names in dirent structure. *)
4897   "dirent", [
4898     "ino", FInt64;
4899     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4900     "ftyp", FChar;
4901     "name", FString;
4902   ];
4903
4904   (* Version numbers. *)
4905   "version", [
4906     "major", FInt64;
4907     "minor", FInt64;
4908     "release", FInt64;
4909     "extra", FString;
4910   ];
4911
4912   (* Extended attribute. *)
4913   "xattr", [
4914     "attrname", FString;
4915     "attrval", FBuffer;
4916   ];
4917
4918   (* Inotify events. *)
4919   "inotify_event", [
4920     "in_wd", FInt64;
4921     "in_mask", FUInt32;
4922     "in_cookie", FUInt32;
4923     "in_name", FString;
4924   ];
4925
4926   (* Partition table entry. *)
4927   "partition", [
4928     "part_num", FInt32;
4929     "part_start", FBytes;
4930     "part_end", FBytes;
4931     "part_size", FBytes;
4932   ];
4933 ] (* end of structs *)
4934
4935 (* Ugh, Java has to be different ..
4936  * These names are also used by the Haskell bindings.
4937  *)
4938 let java_structs = [
4939   "int_bool", "IntBool";
4940   "lvm_pv", "PV";
4941   "lvm_vg", "VG";
4942   "lvm_lv", "LV";
4943   "stat", "Stat";
4944   "statvfs", "StatVFS";
4945   "dirent", "Dirent";
4946   "version", "Version";
4947   "xattr", "XAttr";
4948   "inotify_event", "INotifyEvent";
4949   "partition", "Partition";
4950 ]
4951
4952 (* What structs are actually returned. *)
4953 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4954
4955 (* Returns a list of RStruct/RStructList structs that are returned
4956  * by any function.  Each element of returned list is a pair:
4957  *
4958  * (structname, RStructOnly)
4959  *    == there exists function which returns RStruct (_, structname)
4960  * (structname, RStructListOnly)
4961  *    == there exists function which returns RStructList (_, structname)
4962  * (structname, RStructAndList)
4963  *    == there are functions returning both RStruct (_, structname)
4964  *                                      and RStructList (_, structname)
4965  *)
4966 let rstructs_used_by functions =
4967   (* ||| is a "logical OR" for rstructs_used_t *)
4968   let (|||) a b =
4969     match a, b with
4970     | RStructAndList, _
4971     | _, RStructAndList -> RStructAndList
4972     | RStructOnly, RStructListOnly
4973     | RStructListOnly, RStructOnly -> RStructAndList
4974     | RStructOnly, RStructOnly -> RStructOnly
4975     | RStructListOnly, RStructListOnly -> RStructListOnly
4976   in
4977
4978   let h = Hashtbl.create 13 in
4979
4980   (* if elem->oldv exists, update entry using ||| operator,
4981    * else just add elem->newv to the hash
4982    *)
4983   let update elem newv =
4984     try  let oldv = Hashtbl.find h elem in
4985          Hashtbl.replace h elem (newv ||| oldv)
4986     with Not_found -> Hashtbl.add h elem newv
4987   in
4988
4989   List.iter (
4990     fun (_, style, _, _, _, _, _) ->
4991       match fst style with
4992       | RStruct (_, structname) -> update structname RStructOnly
4993       | RStructList (_, structname) -> update structname RStructListOnly
4994       | _ -> ()
4995   ) functions;
4996
4997   (* return key->values as a list of (key,value) *)
4998   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4999
5000 (* Used for testing language bindings. *)
5001 type callt =
5002   | CallString of string
5003   | CallOptString of string option
5004   | CallStringList of string list
5005   | CallInt of int
5006   | CallInt64 of int64
5007   | CallBool of bool
5008   | CallBuffer of string
5009
5010 (* Used to memoize the result of pod2text. *)
5011 let pod2text_memo_filename = "src/.pod2text.data"
5012 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5013   try
5014     let chan = open_in pod2text_memo_filename in
5015     let v = input_value chan in
5016     close_in chan;
5017     v
5018   with
5019     _ -> Hashtbl.create 13
5020 let pod2text_memo_updated () =
5021   let chan = open_out pod2text_memo_filename in
5022   output_value chan pod2text_memo;
5023   close_out chan
5024
5025 (* Useful functions.
5026  * Note we don't want to use any external OCaml libraries which
5027  * makes this a bit harder than it should be.
5028  *)
5029 module StringMap = Map.Make (String)
5030
5031 let failwithf fs = ksprintf failwith fs
5032
5033 let unique = let i = ref 0 in fun () -> incr i; !i
5034
5035 let replace_char s c1 c2 =
5036   let s2 = String.copy s in
5037   let r = ref false in
5038   for i = 0 to String.length s2 - 1 do
5039     if String.unsafe_get s2 i = c1 then (
5040       String.unsafe_set s2 i c2;
5041       r := true
5042     )
5043   done;
5044   if not !r then s else s2
5045
5046 let isspace c =
5047   c = ' '
5048   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5049
5050 let triml ?(test = isspace) str =
5051   let i = ref 0 in
5052   let n = ref (String.length str) in
5053   while !n > 0 && test str.[!i]; do
5054     decr n;
5055     incr i
5056   done;
5057   if !i = 0 then str
5058   else String.sub str !i !n
5059
5060 let trimr ?(test = isspace) str =
5061   let n = ref (String.length str) in
5062   while !n > 0 && test str.[!n-1]; do
5063     decr n
5064   done;
5065   if !n = String.length str then str
5066   else String.sub str 0 !n
5067
5068 let trim ?(test = isspace) str =
5069   trimr ~test (triml ~test str)
5070
5071 let rec find s sub =
5072   let len = String.length s in
5073   let sublen = String.length sub in
5074   let rec loop i =
5075     if i <= len-sublen then (
5076       let rec loop2 j =
5077         if j < sublen then (
5078           if s.[i+j] = sub.[j] then loop2 (j+1)
5079           else -1
5080         ) else
5081           i (* found *)
5082       in
5083       let r = loop2 0 in
5084       if r = -1 then loop (i+1) else r
5085     ) else
5086       -1 (* not found *)
5087   in
5088   loop 0
5089
5090 let rec replace_str s s1 s2 =
5091   let len = String.length s in
5092   let sublen = String.length s1 in
5093   let i = find s s1 in
5094   if i = -1 then s
5095   else (
5096     let s' = String.sub s 0 i in
5097     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5098     s' ^ s2 ^ replace_str s'' s1 s2
5099   )
5100
5101 let rec string_split sep str =
5102   let len = String.length str in
5103   let seplen = String.length sep in
5104   let i = find str sep in
5105   if i = -1 then [str]
5106   else (
5107     let s' = String.sub str 0 i in
5108     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5109     s' :: string_split sep s''
5110   )
5111
5112 let files_equal n1 n2 =
5113   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5114   match Sys.command cmd with
5115   | 0 -> true
5116   | 1 -> false
5117   | i -> failwithf "%s: failed with error code %d" cmd i
5118
5119 let rec filter_map f = function
5120   | [] -> []
5121   | x :: xs ->
5122       match f x with
5123       | Some y -> y :: filter_map f xs
5124       | None -> filter_map f xs
5125
5126 let rec find_map f = function
5127   | [] -> raise Not_found
5128   | x :: xs ->
5129       match f x with
5130       | Some y -> y
5131       | None -> find_map f xs
5132
5133 let iteri f xs =
5134   let rec loop i = function
5135     | [] -> ()
5136     | x :: xs -> f i x; loop (i+1) xs
5137   in
5138   loop 0 xs
5139
5140 let mapi f xs =
5141   let rec loop i = function
5142     | [] -> []
5143     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5144   in
5145   loop 0 xs
5146
5147 let count_chars c str =
5148   let count = ref 0 in
5149   for i = 0 to String.length str - 1 do
5150     if c = String.unsafe_get str i then incr count
5151   done;
5152   !count
5153
5154 let explode str =
5155   let r = ref [] in
5156   for i = 0 to String.length str - 1 do
5157     let c = String.unsafe_get str i in
5158     r := c :: !r;
5159   done;
5160   List.rev !r
5161
5162 let map_chars f str =
5163   List.map f (explode str)
5164
5165 let name_of_argt = function
5166   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5167   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5168   | FileIn n | FileOut n | BufferIn n -> n
5169
5170 let java_name_of_struct typ =
5171   try List.assoc typ java_structs
5172   with Not_found ->
5173     failwithf
5174       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5175
5176 let cols_of_struct typ =
5177   try List.assoc typ structs
5178   with Not_found ->
5179     failwithf "cols_of_struct: unknown struct %s" typ
5180
5181 let seq_of_test = function
5182   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5183   | TestOutputListOfDevices (s, _)
5184   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5185   | TestOutputTrue s | TestOutputFalse s
5186   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5187   | TestOutputStruct (s, _)
5188   | TestLastFail s -> s
5189
5190 (* Handling for function flags. *)
5191 let protocol_limit_warning =
5192   "Because of the message protocol, there is a transfer limit
5193 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5194
5195 let danger_will_robinson =
5196   "B<This command is dangerous.  Without careful use you
5197 can easily destroy all your data>."
5198
5199 let deprecation_notice flags =
5200   try
5201     let alt =
5202       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5203     let txt =
5204       sprintf "This function is deprecated.
5205 In new code, use the C<%s> call instead.
5206
5207 Deprecated functions will not be removed from the API, but the
5208 fact that they are deprecated indicates that there are problems
5209 with correct use of these functions." alt in
5210     Some txt
5211   with
5212     Not_found -> None
5213
5214 (* Create list of optional groups. *)
5215 let optgroups =
5216   let h = Hashtbl.create 13 in
5217   List.iter (
5218     fun (name, _, _, flags, _, _, _) ->
5219       List.iter (
5220         function
5221         | Optional group ->
5222             let names = try Hashtbl.find h group with Not_found -> [] in
5223             Hashtbl.replace h group (name :: names)
5224         | _ -> ()
5225       ) flags
5226   ) daemon_functions;
5227   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5228   let groups =
5229     List.map (
5230       fun group -> group, List.sort compare (Hashtbl.find h group)
5231     ) groups in
5232   List.sort (fun x y -> compare (fst x) (fst y)) groups
5233
5234 (* Check function names etc. for consistency. *)
5235 let check_functions () =
5236   let contains_uppercase str =
5237     let len = String.length str in
5238     let rec loop i =
5239       if i >= len then false
5240       else (
5241         let c = str.[i] in
5242         if c >= 'A' && c <= 'Z' then true
5243         else loop (i+1)
5244       )
5245     in
5246     loop 0
5247   in
5248
5249   (* Check function names. *)
5250   List.iter (
5251     fun (name, _, _, _, _, _, _) ->
5252       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5253         failwithf "function name %s does not need 'guestfs' prefix" name;
5254       if name = "" then
5255         failwithf "function name is empty";
5256       if name.[0] < 'a' || name.[0] > 'z' then
5257         failwithf "function name %s must start with lowercase a-z" name;
5258       if String.contains name '-' then
5259         failwithf "function name %s should not contain '-', use '_' instead."
5260           name
5261   ) all_functions;
5262
5263   (* Check function parameter/return names. *)
5264   List.iter (
5265     fun (name, style, _, _, _, _, _) ->
5266       let check_arg_ret_name n =
5267         if contains_uppercase n then
5268           failwithf "%s param/ret %s should not contain uppercase chars"
5269             name n;
5270         if String.contains n '-' || String.contains n '_' then
5271           failwithf "%s param/ret %s should not contain '-' or '_'"
5272             name n;
5273         if n = "value" then
5274           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;
5275         if n = "int" || n = "char" || n = "short" || n = "long" then
5276           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5277         if n = "i" || n = "n" then
5278           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5279         if n = "argv" || n = "args" then
5280           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5281
5282         (* List Haskell, OCaml and C keywords here.
5283          * http://www.haskell.org/haskellwiki/Keywords
5284          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5285          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5286          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5287          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5288          * Omitting _-containing words, since they're handled above.
5289          * Omitting the OCaml reserved word, "val", is ok,
5290          * and saves us from renaming several parameters.
5291          *)
5292         let reserved = [
5293           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5294           "char"; "class"; "const"; "constraint"; "continue"; "data";
5295           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5296           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5297           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5298           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5299           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5300           "interface";
5301           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5302           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5303           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5304           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5305           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5306           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5307           "volatile"; "when"; "where"; "while";
5308           ] in
5309         if List.mem n reserved then
5310           failwithf "%s has param/ret using reserved word %s" name n;
5311       in
5312
5313       (match fst style with
5314        | RErr -> ()
5315        | RInt n | RInt64 n | RBool n
5316        | RConstString n | RConstOptString n | RString n
5317        | RStringList n | RStruct (n, _) | RStructList (n, _)
5318        | RHashtable n | RBufferOut n ->
5319            check_arg_ret_name n
5320       );
5321       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5322   ) all_functions;
5323
5324   (* Check short descriptions. *)
5325   List.iter (
5326     fun (name, _, _, _, _, shortdesc, _) ->
5327       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5328         failwithf "short description of %s should begin with lowercase." name;
5329       let c = shortdesc.[String.length shortdesc-1] in
5330       if c = '\n' || c = '.' then
5331         failwithf "short description of %s should not end with . or \\n." name
5332   ) all_functions;
5333
5334   (* Check long descriptions. *)
5335   List.iter (
5336     fun (name, _, _, _, _, _, longdesc) ->
5337       if longdesc.[String.length longdesc-1] = '\n' then
5338         failwithf "long description of %s should not end with \\n." name
5339   ) all_functions;
5340
5341   (* Check proc_nrs. *)
5342   List.iter (
5343     fun (name, _, proc_nr, _, _, _, _) ->
5344       if proc_nr <= 0 then
5345         failwithf "daemon function %s should have proc_nr > 0" name
5346   ) daemon_functions;
5347
5348   List.iter (
5349     fun (name, _, proc_nr, _, _, _, _) ->
5350       if proc_nr <> -1 then
5351         failwithf "non-daemon function %s should have proc_nr -1" name
5352   ) non_daemon_functions;
5353
5354   let proc_nrs =
5355     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5356       daemon_functions in
5357   let proc_nrs =
5358     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5359   let rec loop = function
5360     | [] -> ()
5361     | [_] -> ()
5362     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5363         loop rest
5364     | (name1,nr1) :: (name2,nr2) :: _ ->
5365         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5366           name1 name2 nr1 nr2
5367   in
5368   loop proc_nrs;
5369
5370   (* Check tests. *)
5371   List.iter (
5372     function
5373       (* Ignore functions that have no tests.  We generate a
5374        * warning when the user does 'make check' instead.
5375        *)
5376     | name, _, _, _, [], _, _ -> ()
5377     | name, _, _, _, tests, _, _ ->
5378         let funcs =
5379           List.map (
5380             fun (_, _, test) ->
5381               match seq_of_test test with
5382               | [] ->
5383                   failwithf "%s has a test containing an empty sequence" name
5384               | cmds -> List.map List.hd cmds
5385           ) tests in
5386         let funcs = List.flatten funcs in
5387
5388         let tested = List.mem name funcs in
5389
5390         if not tested then
5391           failwithf "function %s has tests but does not test itself" name
5392   ) all_functions
5393
5394 (* 'pr' prints to the current output file. *)
5395 let chan = ref Pervasives.stdout
5396 let lines = ref 0
5397 let pr fs =
5398   ksprintf
5399     (fun str ->
5400        let i = count_chars '\n' str in
5401        lines := !lines + i;
5402        output_string !chan str
5403     ) fs
5404
5405 let copyright_years =
5406   let this_year = 1900 + (localtime (time ())).tm_year in
5407   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5408
5409 (* Generate a header block in a number of standard styles. *)
5410 type comment_style =
5411     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5412 type license = GPLv2plus | LGPLv2plus
5413
5414 let generate_header ?(extra_inputs = []) comment license =
5415   let inputs = "src/generator.ml" :: extra_inputs in
5416   let c = match comment with
5417     | CStyle ->         pr "/* "; " *"
5418     | CPlusPlusStyle -> pr "// "; "//"
5419     | HashStyle ->      pr "# ";  "#"
5420     | OCamlStyle ->     pr "(* "; " *"
5421     | HaskellStyle ->   pr "{- "; "  " in
5422   pr "libguestfs generated file\n";
5423   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5424   List.iter (pr "%s   %s\n" c) inputs;
5425   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5426   pr "%s\n" c;
5427   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5428   pr "%s\n" c;
5429   (match license with
5430    | GPLv2plus ->
5431        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5432        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5433        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5434        pr "%s (at your option) any later version.\n" c;
5435        pr "%s\n" c;
5436        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5437        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5438        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5439        pr "%s GNU General Public License for more details.\n" c;
5440        pr "%s\n" c;
5441        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5442        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5443        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5444
5445    | LGPLv2plus ->
5446        pr "%s This library is free software; you can redistribute it and/or\n" c;
5447        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5448        pr "%s License as published by the Free Software Foundation; either\n" c;
5449        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5450        pr "%s\n" c;
5451        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5452        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5453        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5454        pr "%s Lesser General Public License for more details.\n" c;
5455        pr "%s\n" c;
5456        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5457        pr "%s License along with this library; if not, write to the Free Software\n" c;
5458        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5459   );
5460   (match comment with
5461    | CStyle -> pr " */\n"
5462    | CPlusPlusStyle
5463    | HashStyle -> ()
5464    | OCamlStyle -> pr " *)\n"
5465    | HaskellStyle -> pr "-}\n"
5466   );
5467   pr "\n"
5468
5469 (* Start of main code generation functions below this line. *)
5470
5471 (* Generate the pod documentation for the C API. *)
5472 let rec generate_actions_pod () =
5473   List.iter (
5474     fun (shortname, style, _, flags, _, _, longdesc) ->
5475       if not (List.mem NotInDocs flags) then (
5476         let name = "guestfs_" ^ shortname in
5477         pr "=head2 %s\n\n" name;
5478         pr " ";
5479         generate_prototype ~extern:false ~handle:"g" name style;
5480         pr "\n\n";
5481         pr "%s\n\n" longdesc;
5482         (match fst style with
5483          | RErr ->
5484              pr "This function returns 0 on success or -1 on error.\n\n"
5485          | RInt _ ->
5486              pr "On error this function returns -1.\n\n"
5487          | RInt64 _ ->
5488              pr "On error this function returns -1.\n\n"
5489          | RBool _ ->
5490              pr "This function returns a C truth value on success or -1 on error.\n\n"
5491          | RConstString _ ->
5492              pr "This function returns a string, or NULL on error.
5493 The string is owned by the guest handle and must I<not> be freed.\n\n"
5494          | RConstOptString _ ->
5495              pr "This function returns a string which may be NULL.
5496 There is way to return an error from this function.
5497 The string is owned by the guest handle and must I<not> be freed.\n\n"
5498          | RString _ ->
5499              pr "This function returns a string, or NULL on error.
5500 I<The caller must free the returned string after use>.\n\n"
5501          | RStringList _ ->
5502              pr "This function returns a NULL-terminated array of strings
5503 (like L<environ(3)>), or NULL if there was an error.
5504 I<The caller must free the strings and the array after use>.\n\n"
5505          | RStruct (_, typ) ->
5506              pr "This function returns a C<struct guestfs_%s *>,
5507 or NULL if there was an error.
5508 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5509          | RStructList (_, typ) ->
5510              pr "This function returns a C<struct guestfs_%s_list *>
5511 (see E<lt>guestfs-structs.hE<gt>),
5512 or NULL if there was an error.
5513 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5514          | RHashtable _ ->
5515              pr "This function returns a NULL-terminated array of
5516 strings, or NULL if there was an error.
5517 The array of strings will always have length C<2n+1>, where
5518 C<n> keys and values alternate, followed by the trailing NULL entry.
5519 I<The caller must free the strings and the array after use>.\n\n"
5520          | RBufferOut _ ->
5521              pr "This function returns a buffer, or NULL on error.
5522 The size of the returned buffer is written to C<*size_r>.
5523 I<The caller must free the returned buffer after use>.\n\n"
5524         );
5525         if List.mem ProtocolLimitWarning flags then
5526           pr "%s\n\n" protocol_limit_warning;
5527         if List.mem DangerWillRobinson flags then
5528           pr "%s\n\n" danger_will_robinson;
5529         match deprecation_notice flags with
5530         | None -> ()
5531         | Some txt -> pr "%s\n\n" txt
5532       )
5533   ) all_functions_sorted
5534
5535 and generate_structs_pod () =
5536   (* Structs documentation. *)
5537   List.iter (
5538     fun (typ, cols) ->
5539       pr "=head2 guestfs_%s\n" typ;
5540       pr "\n";
5541       pr " struct guestfs_%s {\n" typ;
5542       List.iter (
5543         function
5544         | name, FChar -> pr "   char %s;\n" name
5545         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5546         | name, FInt32 -> pr "   int32_t %s;\n" name
5547         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5548         | name, FInt64 -> pr "   int64_t %s;\n" name
5549         | name, FString -> pr "   char *%s;\n" name
5550         | name, FBuffer ->
5551             pr "   /* The next two fields describe a byte array. */\n";
5552             pr "   uint32_t %s_len;\n" name;
5553             pr "   char *%s;\n" name
5554         | name, FUUID ->
5555             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5556             pr "   char %s[32];\n" name
5557         | name, FOptPercent ->
5558             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5559             pr "   float %s;\n" name
5560       ) cols;
5561       pr " };\n";
5562       pr " \n";
5563       pr " struct guestfs_%s_list {\n" typ;
5564       pr "   uint32_t len; /* Number of elements in list. */\n";
5565       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5566       pr " };\n";
5567       pr " \n";
5568       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5569       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5570         typ typ;
5571       pr "\n"
5572   ) structs
5573
5574 and generate_availability_pod () =
5575   (* Availability documentation. *)
5576   pr "=over 4\n";
5577   pr "\n";
5578   List.iter (
5579     fun (group, functions) ->
5580       pr "=item B<%s>\n" group;
5581       pr "\n";
5582       pr "The following functions:\n";
5583       List.iter (pr "L</guestfs_%s>\n") functions;
5584       pr "\n"
5585   ) optgroups;
5586   pr "=back\n";
5587   pr "\n"
5588
5589 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5590  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5591  *
5592  * We have to use an underscore instead of a dash because otherwise
5593  * rpcgen generates incorrect code.
5594  *
5595  * This header is NOT exported to clients, but see also generate_structs_h.
5596  *)
5597 and generate_xdr () =
5598   generate_header CStyle LGPLv2plus;
5599
5600   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5601   pr "typedef string str<>;\n";
5602   pr "\n";
5603
5604   (* Internal structures. *)
5605   List.iter (
5606     function
5607     | typ, cols ->
5608         pr "struct guestfs_int_%s {\n" typ;
5609         List.iter (function
5610                    | name, FChar -> pr "  char %s;\n" name
5611                    | name, FString -> pr "  string %s<>;\n" name
5612                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5613                    | name, FUUID -> pr "  opaque %s[32];\n" name
5614                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5615                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5616                    | name, FOptPercent -> pr "  float %s;\n" name
5617                   ) cols;
5618         pr "};\n";
5619         pr "\n";
5620         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5621         pr "\n";
5622   ) structs;
5623
5624   List.iter (
5625     fun (shortname, style, _, _, _, _, _) ->
5626       let name = "guestfs_" ^ shortname in
5627
5628       (match snd style with
5629        | [] -> ()
5630        | args ->
5631            pr "struct %s_args {\n" name;
5632            List.iter (
5633              function
5634              | Pathname n | Device n | Dev_or_Path n | String n ->
5635                  pr "  string %s<>;\n" n
5636              | OptString n -> pr "  str *%s;\n" n
5637              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5638              | Bool n -> pr "  bool %s;\n" n
5639              | Int n -> pr "  int %s;\n" n
5640              | Int64 n -> pr "  hyper %s;\n" n
5641              | BufferIn n ->
5642                  pr "  opaque %s<>;\n" n
5643              | FileIn _ | FileOut _ -> ()
5644            ) args;
5645            pr "};\n\n"
5646       );
5647       (match fst style with
5648        | RErr -> ()
5649        | RInt n ->
5650            pr "struct %s_ret {\n" name;
5651            pr "  int %s;\n" n;
5652            pr "};\n\n"
5653        | RInt64 n ->
5654            pr "struct %s_ret {\n" name;
5655            pr "  hyper %s;\n" n;
5656            pr "};\n\n"
5657        | RBool n ->
5658            pr "struct %s_ret {\n" name;
5659            pr "  bool %s;\n" n;
5660            pr "};\n\n"
5661        | RConstString _ | RConstOptString _ ->
5662            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5663        | RString n ->
5664            pr "struct %s_ret {\n" name;
5665            pr "  string %s<>;\n" n;
5666            pr "};\n\n"
5667        | RStringList n ->
5668            pr "struct %s_ret {\n" name;
5669            pr "  str %s<>;\n" n;
5670            pr "};\n\n"
5671        | RStruct (n, typ) ->
5672            pr "struct %s_ret {\n" name;
5673            pr "  guestfs_int_%s %s;\n" typ n;
5674            pr "};\n\n"
5675        | RStructList (n, typ) ->
5676            pr "struct %s_ret {\n" name;
5677            pr "  guestfs_int_%s_list %s;\n" typ n;
5678            pr "};\n\n"
5679        | RHashtable n ->
5680            pr "struct %s_ret {\n" name;
5681            pr "  str %s<>;\n" n;
5682            pr "};\n\n"
5683        | RBufferOut n ->
5684            pr "struct %s_ret {\n" name;
5685            pr "  opaque %s<>;\n" n;
5686            pr "};\n\n"
5687       );
5688   ) daemon_functions;
5689
5690   (* Table of procedure numbers. *)
5691   pr "enum guestfs_procedure {\n";
5692   List.iter (
5693     fun (shortname, _, proc_nr, _, _, _, _) ->
5694       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5695   ) daemon_functions;
5696   pr "  GUESTFS_PROC_NR_PROCS\n";
5697   pr "};\n";
5698   pr "\n";
5699
5700   (* Having to choose a maximum message size is annoying for several
5701    * reasons (it limits what we can do in the API), but it (a) makes
5702    * the protocol a lot simpler, and (b) provides a bound on the size
5703    * of the daemon which operates in limited memory space.
5704    *)
5705   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5706   pr "\n";
5707
5708   (* Message header, etc. *)
5709   pr "\
5710 /* The communication protocol is now documented in the guestfs(3)
5711  * manpage.
5712  */
5713
5714 const GUESTFS_PROGRAM = 0x2000F5F5;
5715 const GUESTFS_PROTOCOL_VERSION = 1;
5716
5717 /* These constants must be larger than any possible message length. */
5718 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5719 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5720
5721 enum guestfs_message_direction {
5722   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5723   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5724 };
5725
5726 enum guestfs_message_status {
5727   GUESTFS_STATUS_OK = 0,
5728   GUESTFS_STATUS_ERROR = 1
5729 };
5730
5731 const GUESTFS_ERROR_LEN = 256;
5732
5733 struct guestfs_message_error {
5734   string error_message<GUESTFS_ERROR_LEN>;
5735 };
5736
5737 struct guestfs_message_header {
5738   unsigned prog;                     /* GUESTFS_PROGRAM */
5739   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5740   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5741   guestfs_message_direction direction;
5742   unsigned serial;                   /* message serial number */
5743   guestfs_message_status status;
5744 };
5745
5746 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5747
5748 struct guestfs_chunk {
5749   int cancel;                        /* if non-zero, transfer is cancelled */
5750   /* data size is 0 bytes if the transfer has finished successfully */
5751   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5752 };
5753 "
5754
5755 (* Generate the guestfs-structs.h file. *)
5756 and generate_structs_h () =
5757   generate_header CStyle LGPLv2plus;
5758
5759   (* This is a public exported header file containing various
5760    * structures.  The structures are carefully written to have
5761    * exactly the same in-memory format as the XDR structures that
5762    * we use on the wire to the daemon.  The reason for creating
5763    * copies of these structures here is just so we don't have to
5764    * export the whole of guestfs_protocol.h (which includes much
5765    * unrelated and XDR-dependent stuff that we don't want to be
5766    * public, or required by clients).
5767    *
5768    * To reiterate, we will pass these structures to and from the
5769    * client with a simple assignment or memcpy, so the format
5770    * must be identical to what rpcgen / the RFC defines.
5771    *)
5772
5773   (* Public structures. *)
5774   List.iter (
5775     fun (typ, cols) ->
5776       pr "struct guestfs_%s {\n" typ;
5777       List.iter (
5778         function
5779         | name, FChar -> pr "  char %s;\n" name
5780         | name, FString -> pr "  char *%s;\n" name
5781         | name, FBuffer ->
5782             pr "  uint32_t %s_len;\n" name;
5783             pr "  char *%s;\n" name
5784         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5785         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5786         | name, FInt32 -> pr "  int32_t %s;\n" name
5787         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5788         | name, FInt64 -> pr "  int64_t %s;\n" name
5789         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5790       ) cols;
5791       pr "};\n";
5792       pr "\n";
5793       pr "struct guestfs_%s_list {\n" typ;
5794       pr "  uint32_t len;\n";
5795       pr "  struct guestfs_%s *val;\n" typ;
5796       pr "};\n";
5797       pr "\n";
5798       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5799       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5800       pr "\n"
5801   ) structs
5802
5803 (* Generate the guestfs-actions.h file. *)
5804 and generate_actions_h () =
5805   generate_header CStyle LGPLv2plus;
5806   List.iter (
5807     fun (shortname, style, _, _, _, _, _) ->
5808       let name = "guestfs_" ^ shortname in
5809       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5810         name style
5811   ) all_functions
5812
5813 (* Generate the guestfs-internal-actions.h file. *)
5814 and generate_internal_actions_h () =
5815   generate_header CStyle LGPLv2plus;
5816   List.iter (
5817     fun (shortname, style, _, _, _, _, _) ->
5818       let name = "guestfs__" ^ shortname in
5819       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5820         name style
5821   ) non_daemon_functions
5822
5823 (* Generate the client-side dispatch stubs. *)
5824 and generate_client_actions () =
5825   generate_header CStyle LGPLv2plus;
5826
5827   pr "\
5828 #include <stdio.h>
5829 #include <stdlib.h>
5830 #include <stdint.h>
5831 #include <string.h>
5832 #include <inttypes.h>
5833
5834 #include \"guestfs.h\"
5835 #include \"guestfs-internal.h\"
5836 #include \"guestfs-internal-actions.h\"
5837 #include \"guestfs_protocol.h\"
5838
5839 #define error guestfs_error
5840 //#define perrorf guestfs_perrorf
5841 #define safe_malloc guestfs_safe_malloc
5842 #define safe_realloc guestfs_safe_realloc
5843 //#define safe_strdup guestfs_safe_strdup
5844 #define safe_memdup guestfs_safe_memdup
5845
5846 /* Check the return message from a call for validity. */
5847 static int
5848 check_reply_header (guestfs_h *g,
5849                     const struct guestfs_message_header *hdr,
5850                     unsigned int proc_nr, unsigned int serial)
5851 {
5852   if (hdr->prog != GUESTFS_PROGRAM) {
5853     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5854     return -1;
5855   }
5856   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5857     error (g, \"wrong protocol version (%%d/%%d)\",
5858            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5859     return -1;
5860   }
5861   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5862     error (g, \"unexpected message direction (%%d/%%d)\",
5863            hdr->direction, GUESTFS_DIRECTION_REPLY);
5864     return -1;
5865   }
5866   if (hdr->proc != proc_nr) {
5867     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5868     return -1;
5869   }
5870   if (hdr->serial != serial) {
5871     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5872     return -1;
5873   }
5874
5875   return 0;
5876 }
5877
5878 /* Check we are in the right state to run a high-level action. */
5879 static int
5880 check_state (guestfs_h *g, const char *caller)
5881 {
5882   if (!guestfs__is_ready (g)) {
5883     if (guestfs__is_config (g) || guestfs__is_launching (g))
5884       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5885         caller);
5886     else
5887       error (g, \"%%s called from the wrong state, %%d != READY\",
5888         caller, guestfs__get_state (g));
5889     return -1;
5890   }
5891   return 0;
5892 }
5893
5894 ";
5895
5896   let error_code_of = function
5897     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5898     | RConstString _ | RConstOptString _
5899     | RString _ | RStringList _
5900     | RStruct _ | RStructList _
5901     | RHashtable _ | RBufferOut _ -> "NULL"
5902   in
5903
5904   (* Generate code to check String-like parameters are not passed in
5905    * as NULL (returning an error if they are).
5906    *)
5907   let check_null_strings shortname style =
5908     let pr_newline = ref false in
5909     List.iter (
5910       function
5911       (* parameters which should not be NULL *)
5912       | String n
5913       | Device n
5914       | Pathname n
5915       | Dev_or_Path n
5916       | FileIn n
5917       | FileOut n
5918       | BufferIn n
5919       | StringList n
5920       | DeviceList n ->
5921           pr "  if (%s == NULL) {\n" n;
5922           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5923           pr "           \"%s\", \"%s\");\n" shortname n;
5924           pr "    return %s;\n" (error_code_of (fst style));
5925           pr "  }\n";
5926           pr_newline := true
5927
5928       (* can be NULL *)
5929       | OptString _
5930
5931       (* not applicable *)
5932       | Bool _
5933       | Int _
5934       | Int64 _ -> ()
5935     ) (snd style);
5936
5937     if !pr_newline then pr "\n";
5938   in
5939
5940   (* Generate code to generate guestfish call traces. *)
5941   let trace_call shortname style =
5942     pr "  if (guestfs__get_trace (g)) {\n";
5943
5944     let needs_i =
5945       List.exists (function
5946                    | StringList _ | DeviceList _ -> true
5947                    | _ -> false) (snd style) in
5948     if needs_i then (
5949       pr "    int i;\n";
5950       pr "\n"
5951     );
5952
5953     pr "    printf (\"%s\");\n" shortname;
5954     List.iter (
5955       function
5956       | String n                        (* strings *)
5957       | Device n
5958       | Pathname n
5959       | Dev_or_Path n
5960       | FileIn n
5961       | FileOut n
5962       | BufferIn n ->
5963           (* guestfish doesn't support string escaping, so neither do we *)
5964           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5965       | OptString n ->                  (* string option *)
5966           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5967           pr "    else printf (\" null\");\n"
5968       | StringList n
5969       | DeviceList n ->                 (* string list *)
5970           pr "    putchar (' ');\n";
5971           pr "    putchar ('\"');\n";
5972           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5973           pr "      if (i > 0) putchar (' ');\n";
5974           pr "      fputs (%s[i], stdout);\n" n;
5975           pr "    }\n";
5976           pr "    putchar ('\"');\n";
5977       | Bool n ->                       (* boolean *)
5978           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5979       | Int n ->                        (* int *)
5980           pr "    printf (\" %%d\", %s);\n" n
5981       | Int64 n ->
5982           pr "    printf (\" %%\" PRIi64, %s);\n" n
5983     ) (snd style);
5984     pr "    putchar ('\\n');\n";
5985     pr "  }\n";
5986     pr "\n";
5987   in
5988
5989   (* For non-daemon functions, generate a wrapper around each function. *)
5990   List.iter (
5991     fun (shortname, style, _, _, _, _, _) ->
5992       let name = "guestfs_" ^ shortname in
5993
5994       generate_prototype ~extern:false ~semicolon:false ~newline:true
5995         ~handle:"g" name style;
5996       pr "{\n";
5997       check_null_strings shortname style;
5998       trace_call shortname style;
5999       pr "  return guestfs__%s " shortname;
6000       generate_c_call_args ~handle:"g" style;
6001       pr ";\n";
6002       pr "}\n";
6003       pr "\n"
6004   ) non_daemon_functions;
6005
6006   (* Client-side stubs for each function. *)
6007   List.iter (
6008     fun (shortname, style, _, _, _, _, _) ->
6009       let name = "guestfs_" ^ shortname in
6010       let error_code = error_code_of (fst style) in
6011
6012       (* Generate the action stub. *)
6013       generate_prototype ~extern:false ~semicolon:false ~newline:true
6014         ~handle:"g" name style;
6015
6016       pr "{\n";
6017
6018       (match snd style with
6019        | [] -> ()
6020        | _ -> pr "  struct %s_args args;\n" name
6021       );
6022
6023       pr "  guestfs_message_header hdr;\n";
6024       pr "  guestfs_message_error err;\n";
6025       let has_ret =
6026         match fst style with
6027         | RErr -> false
6028         | RConstString _ | RConstOptString _ ->
6029             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6030         | RInt _ | RInt64 _
6031         | RBool _ | RString _ | RStringList _
6032         | RStruct _ | RStructList _
6033         | RHashtable _ | RBufferOut _ ->
6034             pr "  struct %s_ret ret;\n" name;
6035             true in
6036
6037       pr "  int serial;\n";
6038       pr "  int r;\n";
6039       pr "\n";
6040       check_null_strings shortname style;
6041       trace_call shortname style;
6042       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6043         shortname error_code;
6044       pr "  guestfs___set_busy (g);\n";
6045       pr "\n";
6046
6047       (* Send the main header and arguments. *)
6048       (match snd style with
6049        | [] ->
6050            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6051              (String.uppercase shortname)
6052        | args ->
6053            List.iter (
6054              function
6055              | Pathname n | Device n | Dev_or_Path n | String n ->
6056                  pr "  args.%s = (char *) %s;\n" n n
6057              | OptString n ->
6058                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6059              | StringList n | DeviceList n ->
6060                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6061                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6062              | Bool n ->
6063                  pr "  args.%s = %s;\n" n n
6064              | Int n ->
6065                  pr "  args.%s = %s;\n" n n
6066              | Int64 n ->
6067                  pr "  args.%s = %s;\n" n n
6068              | FileIn _ | FileOut _ -> ()
6069              | BufferIn n ->
6070                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6071                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6072                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6073                    shortname;
6074                  pr "    guestfs___end_busy (g);\n";
6075                  pr "    return %s;\n" error_code;
6076                  pr "  }\n";
6077                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6078                  pr "  args.%s.%s_len = %s_size;\n" n n n
6079            ) args;
6080            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6081              (String.uppercase shortname);
6082            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6083              name;
6084       );
6085       pr "  if (serial == -1) {\n";
6086       pr "    guestfs___end_busy (g);\n";
6087       pr "    return %s;\n" error_code;
6088       pr "  }\n";
6089       pr "\n";
6090
6091       (* Send any additional files (FileIn) requested. *)
6092       let need_read_reply_label = ref false in
6093       List.iter (
6094         function
6095         | FileIn n ->
6096             pr "  r = guestfs___send_file (g, %s);\n" n;
6097             pr "  if (r == -1) {\n";
6098             pr "    guestfs___end_busy (g);\n";
6099             pr "    return %s;\n" error_code;
6100             pr "  }\n";
6101             pr "  if (r == -2) /* daemon cancelled */\n";
6102             pr "    goto read_reply;\n";
6103             need_read_reply_label := true;
6104             pr "\n";
6105         | _ -> ()
6106       ) (snd style);
6107
6108       (* Wait for the reply from the remote end. *)
6109       if !need_read_reply_label then pr " read_reply:\n";
6110       pr "  memset (&hdr, 0, sizeof hdr);\n";
6111       pr "  memset (&err, 0, sizeof err);\n";
6112       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6113       pr "\n";
6114       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6115       if not has_ret then
6116         pr "NULL, NULL"
6117       else
6118         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6119       pr ");\n";
6120
6121       pr "  if (r == -1) {\n";
6122       pr "    guestfs___end_busy (g);\n";
6123       pr "    return %s;\n" error_code;
6124       pr "  }\n";
6125       pr "\n";
6126
6127       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6128         (String.uppercase shortname);
6129       pr "    guestfs___end_busy (g);\n";
6130       pr "    return %s;\n" error_code;
6131       pr "  }\n";
6132       pr "\n";
6133
6134       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6135       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6136       pr "    free (err.error_message);\n";
6137       pr "    guestfs___end_busy (g);\n";
6138       pr "    return %s;\n" error_code;
6139       pr "  }\n";
6140       pr "\n";
6141
6142       (* Expecting to receive further files (FileOut)? *)
6143       List.iter (
6144         function
6145         | FileOut n ->
6146             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6147             pr "    guestfs___end_busy (g);\n";
6148             pr "    return %s;\n" error_code;
6149             pr "  }\n";
6150             pr "\n";
6151         | _ -> ()
6152       ) (snd style);
6153
6154       pr "  guestfs___end_busy (g);\n";
6155
6156       (match fst style with
6157        | RErr -> pr "  return 0;\n"
6158        | RInt n | RInt64 n | RBool n ->
6159            pr "  return ret.%s;\n" n
6160        | RConstString _ | RConstOptString _ ->
6161            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6162        | RString n ->
6163            pr "  return ret.%s; /* caller will free */\n" n
6164        | RStringList n | RHashtable n ->
6165            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6166            pr "  ret.%s.%s_val =\n" n n;
6167            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6168            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6169              n n;
6170            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6171            pr "  return ret.%s.%s_val;\n" n n
6172        | RStruct (n, _) ->
6173            pr "  /* caller will free this */\n";
6174            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6175        | RStructList (n, _) ->
6176            pr "  /* caller will free this */\n";
6177            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6178        | RBufferOut n ->
6179            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6180            pr "   * _val might be NULL here.  To make the API saner for\n";
6181            pr "   * callers, we turn this case into a unique pointer (using\n";
6182            pr "   * malloc(1)).\n";
6183            pr "   */\n";
6184            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6185            pr "    *size_r = ret.%s.%s_len;\n" n n;
6186            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6187            pr "  } else {\n";
6188            pr "    free (ret.%s.%s_val);\n" n n;
6189            pr "    char *p = safe_malloc (g, 1);\n";
6190            pr "    *size_r = ret.%s.%s_len;\n" n n;
6191            pr "    return p;\n";
6192            pr "  }\n";
6193       );
6194
6195       pr "}\n\n"
6196   ) daemon_functions;
6197
6198   (* Functions to free structures. *)
6199   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6200   pr " * structure format is identical to the XDR format.  See note in\n";
6201   pr " * generator.ml.\n";
6202   pr " */\n";
6203   pr "\n";
6204
6205   List.iter (
6206     fun (typ, _) ->
6207       pr "void\n";
6208       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6209       pr "{\n";
6210       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6211       pr "  free (x);\n";
6212       pr "}\n";
6213       pr "\n";
6214
6215       pr "void\n";
6216       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6217       pr "{\n";
6218       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6219       pr "  free (x);\n";
6220       pr "}\n";
6221       pr "\n";
6222
6223   ) structs;
6224
6225 (* Generate daemon/actions.h. *)
6226 and generate_daemon_actions_h () =
6227   generate_header CStyle GPLv2plus;
6228
6229   pr "#include \"../src/guestfs_protocol.h\"\n";
6230   pr "\n";
6231
6232   List.iter (
6233     fun (name, style, _, _, _, _, _) ->
6234       generate_prototype
6235         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6236         name style;
6237   ) daemon_functions
6238
6239 (* Generate the linker script which controls the visibility of
6240  * symbols in the public ABI and ensures no other symbols get
6241  * exported accidentally.
6242  *)
6243 and generate_linker_script () =
6244   generate_header HashStyle GPLv2plus;
6245
6246   let globals = [
6247     "guestfs_create";
6248     "guestfs_close";
6249     "guestfs_get_error_handler";
6250     "guestfs_get_out_of_memory_handler";
6251     "guestfs_last_error";
6252     "guestfs_set_error_handler";
6253     "guestfs_set_launch_done_callback";
6254     "guestfs_set_log_message_callback";
6255     "guestfs_set_out_of_memory_handler";
6256     "guestfs_set_subprocess_quit_callback";
6257
6258     (* Unofficial parts of the API: the bindings code use these
6259      * functions, so it is useful to export them.
6260      *)
6261     "guestfs_safe_calloc";
6262     "guestfs_safe_malloc";
6263   ] in
6264   let functions =
6265     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6266       all_functions in
6267   let structs =
6268     List.concat (
6269       List.map (fun (typ, _) ->
6270                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6271         structs
6272     ) in
6273   let globals = List.sort compare (globals @ functions @ structs) in
6274
6275   pr "{\n";
6276   pr "    global:\n";
6277   List.iter (pr "        %s;\n") globals;
6278   pr "\n";
6279
6280   pr "    local:\n";
6281   pr "        *;\n";
6282   pr "};\n"
6283
6284 (* Generate the server-side stubs. *)
6285 and generate_daemon_actions () =
6286   generate_header CStyle GPLv2plus;
6287
6288   pr "#include <config.h>\n";
6289   pr "\n";
6290   pr "#include <stdio.h>\n";
6291   pr "#include <stdlib.h>\n";
6292   pr "#include <string.h>\n";
6293   pr "#include <inttypes.h>\n";
6294   pr "#include <rpc/types.h>\n";
6295   pr "#include <rpc/xdr.h>\n";
6296   pr "\n";
6297   pr "#include \"daemon.h\"\n";
6298   pr "#include \"c-ctype.h\"\n";
6299   pr "#include \"../src/guestfs_protocol.h\"\n";
6300   pr "#include \"actions.h\"\n";
6301   pr "\n";
6302
6303   List.iter (
6304     fun (name, style, _, _, _, _, _) ->
6305       (* Generate server-side stubs. *)
6306       pr "static void %s_stub (XDR *xdr_in)\n" name;
6307       pr "{\n";
6308       let error_code =
6309         match fst style with
6310         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6311         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6312         | RBool _ -> pr "  int r;\n"; "-1"
6313         | RConstString _ | RConstOptString _ ->
6314             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6315         | RString _ -> pr "  char *r;\n"; "NULL"
6316         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6317         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6318         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6319         | RBufferOut _ ->
6320             pr "  size_t size = 1;\n";
6321             pr "  char *r;\n";
6322             "NULL" in
6323
6324       (match snd style with
6325        | [] -> ()
6326        | args ->
6327            pr "  struct guestfs_%s_args args;\n" name;
6328            List.iter (
6329              function
6330              | Device n | Dev_or_Path n
6331              | Pathname n
6332              | String n -> ()
6333              | OptString n -> pr "  char *%s;\n" n
6334              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6335              | Bool n -> pr "  int %s;\n" n
6336              | Int n -> pr "  int %s;\n" n
6337              | Int64 n -> pr "  int64_t %s;\n" n
6338              | FileIn _ | FileOut _ -> ()
6339              | BufferIn n ->
6340                  pr "  const char *%s;\n" n;
6341                  pr "  size_t %s_size;\n" n
6342            ) args
6343       );
6344       pr "\n";
6345
6346       let is_filein =
6347         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6348
6349       (match snd style with
6350        | [] -> ()
6351        | args ->
6352            pr "  memset (&args, 0, sizeof args);\n";
6353            pr "\n";
6354            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6355            if is_filein then
6356              pr "    if (cancel_receive () != -2)\n";
6357            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6358            pr "    goto done;\n";
6359            pr "  }\n";
6360            let pr_args n =
6361              pr "  char *%s = args.%s;\n" n n
6362            in
6363            let pr_list_handling_code n =
6364              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6365              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6366              pr "  if (%s == NULL) {\n" n;
6367              if is_filein then
6368                pr "    if (cancel_receive () != -2)\n";
6369              pr "      reply_with_perror (\"realloc\");\n";
6370              pr "    goto done;\n";
6371              pr "  }\n";
6372              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6373              pr "  args.%s.%s_val = %s;\n" n n n;
6374            in
6375            List.iter (
6376              function
6377              | Pathname n ->
6378                  pr_args n;
6379                  pr "  ABS_PATH (%s, %s, goto done);\n"
6380                    n (if is_filein then "cancel_receive ()" else "0");
6381              | Device n ->
6382                  pr_args n;
6383                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6384                    n (if is_filein then "cancel_receive ()" else "0");
6385              | Dev_or_Path n ->
6386                  pr_args n;
6387                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6388                    n (if is_filein then "cancel_receive ()" else "0");
6389              | String n -> pr_args n
6390              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6391              | StringList n ->
6392                  pr_list_handling_code n;
6393              | DeviceList n ->
6394                  pr_list_handling_code n;
6395                  pr "  /* Ensure that each is a device,\n";
6396                  pr "   * and perform device name translation. */\n";
6397                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6398                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6399                    (if is_filein then "cancel_receive ()" else "0");
6400                  pr "  }\n";
6401              | Bool n -> pr "  %s = args.%s;\n" n n
6402              | Int n -> pr "  %s = args.%s;\n" n n
6403              | Int64 n -> pr "  %s = args.%s;\n" n n
6404              | FileIn _ | FileOut _ -> ()
6405              | BufferIn n ->
6406                  pr "  %s = args.%s.%s_val;\n" n n n;
6407                  pr "  %s_size = args.%s.%s_len;\n" n n n
6408            ) args;
6409            pr "\n"
6410       );
6411
6412       (* this is used at least for do_equal *)
6413       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6414         (* Emit NEED_ROOT just once, even when there are two or
6415            more Pathname args *)
6416         pr "  NEED_ROOT (%s, goto done);\n"
6417           (if is_filein then "cancel_receive ()" else "0");
6418       );
6419
6420       (* Don't want to call the impl with any FileIn or FileOut
6421        * parameters, since these go "outside" the RPC protocol.
6422        *)
6423       let args' =
6424         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6425           (snd style) in
6426       pr "  r = do_%s " name;
6427       generate_c_call_args (fst style, args');
6428       pr ";\n";
6429
6430       (match fst style with
6431        | RErr | RInt _ | RInt64 _ | RBool _
6432        | RConstString _ | RConstOptString _
6433        | RString _ | RStringList _ | RHashtable _
6434        | RStruct (_, _) | RStructList (_, _) ->
6435            pr "  if (r == %s)\n" error_code;
6436            pr "    /* do_%s has already called reply_with_error */\n" name;
6437            pr "    goto done;\n";
6438            pr "\n"
6439        | RBufferOut _ ->
6440            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6441            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6442            pr "   */\n";
6443            pr "  if (size == 1 && r == %s)\n" error_code;
6444            pr "    /* do_%s has already called reply_with_error */\n" name;
6445            pr "    goto done;\n";
6446            pr "\n"
6447       );
6448
6449       (* If there are any FileOut parameters, then the impl must
6450        * send its own reply.
6451        *)
6452       let no_reply =
6453         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6454       if no_reply then
6455         pr "  /* do_%s has already sent a reply */\n" name
6456       else (
6457         match fst style with
6458         | RErr -> pr "  reply (NULL, NULL);\n"
6459         | RInt n | RInt64 n | RBool n ->
6460             pr "  struct guestfs_%s_ret ret;\n" name;
6461             pr "  ret.%s = r;\n" n;
6462             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6463               name
6464         | RConstString _ | RConstOptString _ ->
6465             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6466         | RString n ->
6467             pr "  struct guestfs_%s_ret ret;\n" name;
6468             pr "  ret.%s = r;\n" n;
6469             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6470               name;
6471             pr "  free (r);\n"
6472         | RStringList n | RHashtable n ->
6473             pr "  struct guestfs_%s_ret ret;\n" name;
6474             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6475             pr "  ret.%s.%s_val = r;\n" n n;
6476             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6477               name;
6478             pr "  free_strings (r);\n"
6479         | RStruct (n, _) ->
6480             pr "  struct guestfs_%s_ret ret;\n" name;
6481             pr "  ret.%s = *r;\n" n;
6482             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6483               name;
6484             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6485               name
6486         | RStructList (n, _) ->
6487             pr "  struct guestfs_%s_ret ret;\n" name;
6488             pr "  ret.%s = *r;\n" n;
6489             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6490               name;
6491             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6492               name
6493         | RBufferOut n ->
6494             pr "  struct guestfs_%s_ret ret;\n" name;
6495             pr "  ret.%s.%s_val = r;\n" n n;
6496             pr "  ret.%s.%s_len = size;\n" n n;
6497             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6498               name;
6499             pr "  free (r);\n"
6500       );
6501
6502       (* Free the args. *)
6503       pr "done:\n";
6504       (match snd style with
6505        | [] -> ()
6506        | _ ->
6507            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6508              name
6509       );
6510       pr "  return;\n";
6511       pr "}\n\n";
6512   ) daemon_functions;
6513
6514   (* Dispatch function. *)
6515   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6516   pr "{\n";
6517   pr "  switch (proc_nr) {\n";
6518
6519   List.iter (
6520     fun (name, style, _, _, _, _, _) ->
6521       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6522       pr "      %s_stub (xdr_in);\n" name;
6523       pr "      break;\n"
6524   ) daemon_functions;
6525
6526   pr "    default:\n";
6527   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";
6528   pr "  }\n";
6529   pr "}\n";
6530   pr "\n";
6531
6532   (* LVM columns and tokenization functions. *)
6533   (* XXX This generates crap code.  We should rethink how we
6534    * do this parsing.
6535    *)
6536   List.iter (
6537     function
6538     | typ, cols ->
6539         pr "static const char *lvm_%s_cols = \"%s\";\n"
6540           typ (String.concat "," (List.map fst cols));
6541         pr "\n";
6542
6543         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6544         pr "{\n";
6545         pr "  char *tok, *p, *next;\n";
6546         pr "  int i, j;\n";
6547         pr "\n";
6548         (*
6549           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6550           pr "\n";
6551         *)
6552         pr "  if (!str) {\n";
6553         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6554         pr "    return -1;\n";
6555         pr "  }\n";
6556         pr "  if (!*str || c_isspace (*str)) {\n";
6557         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6558         pr "    return -1;\n";
6559         pr "  }\n";
6560         pr "  tok = str;\n";
6561         List.iter (
6562           fun (name, coltype) ->
6563             pr "  if (!tok) {\n";
6564             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6565             pr "    return -1;\n";
6566             pr "  }\n";
6567             pr "  p = strchrnul (tok, ',');\n";
6568             pr "  if (*p) next = p+1; else next = NULL;\n";
6569             pr "  *p = '\\0';\n";
6570             (match coltype with
6571              | FString ->
6572                  pr "  r->%s = strdup (tok);\n" name;
6573                  pr "  if (r->%s == NULL) {\n" name;
6574                  pr "    perror (\"strdup\");\n";
6575                  pr "    return -1;\n";
6576                  pr "  }\n"
6577              | FUUID ->
6578                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6579                  pr "    if (tok[j] == '\\0') {\n";
6580                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6581                  pr "      return -1;\n";
6582                  pr "    } else if (tok[j] != '-')\n";
6583                  pr "      r->%s[i++] = tok[j];\n" name;
6584                  pr "  }\n";
6585              | FBytes ->
6586                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6587                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6588                  pr "    return -1;\n";
6589                  pr "  }\n";
6590              | FInt64 ->
6591                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6592                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6593                  pr "    return -1;\n";
6594                  pr "  }\n";
6595              | FOptPercent ->
6596                  pr "  if (tok[0] == '\\0')\n";
6597                  pr "    r->%s = -1;\n" name;
6598                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6599                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6600                  pr "    return -1;\n";
6601                  pr "  }\n";
6602              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6603                  assert false (* can never be an LVM column *)
6604             );
6605             pr "  tok = next;\n";
6606         ) cols;
6607
6608         pr "  if (tok != NULL) {\n";
6609         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6610         pr "    return -1;\n";
6611         pr "  }\n";
6612         pr "  return 0;\n";
6613         pr "}\n";
6614         pr "\n";
6615
6616         pr "guestfs_int_lvm_%s_list *\n" typ;
6617         pr "parse_command_line_%ss (void)\n" typ;
6618         pr "{\n";
6619         pr "  char *out, *err;\n";
6620         pr "  char *p, *pend;\n";
6621         pr "  int r, i;\n";
6622         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6623         pr "  void *newp;\n";
6624         pr "\n";
6625         pr "  ret = malloc (sizeof *ret);\n";
6626         pr "  if (!ret) {\n";
6627         pr "    reply_with_perror (\"malloc\");\n";
6628         pr "    return NULL;\n";
6629         pr "  }\n";
6630         pr "\n";
6631         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6632         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6633         pr "\n";
6634         pr "  r = command (&out, &err,\n";
6635         pr "           \"lvm\", \"%ss\",\n" typ;
6636         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6637         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6638         pr "  if (r == -1) {\n";
6639         pr "    reply_with_error (\"%%s\", err);\n";
6640         pr "    free (out);\n";
6641         pr "    free (err);\n";
6642         pr "    free (ret);\n";
6643         pr "    return NULL;\n";
6644         pr "  }\n";
6645         pr "\n";
6646         pr "  free (err);\n";
6647         pr "\n";
6648         pr "  /* Tokenize each line of the output. */\n";
6649         pr "  p = out;\n";
6650         pr "  i = 0;\n";
6651         pr "  while (p) {\n";
6652         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6653         pr "    if (pend) {\n";
6654         pr "      *pend = '\\0';\n";
6655         pr "      pend++;\n";
6656         pr "    }\n";
6657         pr "\n";
6658         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6659         pr "      p++;\n";
6660         pr "\n";
6661         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6662         pr "      p = pend;\n";
6663         pr "      continue;\n";
6664         pr "    }\n";
6665         pr "\n";
6666         pr "    /* Allocate some space to store this next entry. */\n";
6667         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6668         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6669         pr "    if (newp == NULL) {\n";
6670         pr "      reply_with_perror (\"realloc\");\n";
6671         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6672         pr "      free (ret);\n";
6673         pr "      free (out);\n";
6674         pr "      return NULL;\n";
6675         pr "    }\n";
6676         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6677         pr "\n";
6678         pr "    /* Tokenize the next entry. */\n";
6679         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6680         pr "    if (r == -1) {\n";
6681         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6682         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6683         pr "      free (ret);\n";
6684         pr "      free (out);\n";
6685         pr "      return NULL;\n";
6686         pr "    }\n";
6687         pr "\n";
6688         pr "    ++i;\n";
6689         pr "    p = pend;\n";
6690         pr "  }\n";
6691         pr "\n";
6692         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6693         pr "\n";
6694         pr "  free (out);\n";
6695         pr "  return ret;\n";
6696         pr "}\n"
6697
6698   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6699
6700 (* Generate a list of function names, for debugging in the daemon.. *)
6701 and generate_daemon_names () =
6702   generate_header CStyle GPLv2plus;
6703
6704   pr "#include <config.h>\n";
6705   pr "\n";
6706   pr "#include \"daemon.h\"\n";
6707   pr "\n";
6708
6709   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6710   pr "const char *function_names[] = {\n";
6711   List.iter (
6712     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6713   ) daemon_functions;
6714   pr "};\n";
6715
6716 (* Generate the optional groups for the daemon to implement
6717  * guestfs_available.
6718  *)
6719 and generate_daemon_optgroups_c () =
6720   generate_header CStyle GPLv2plus;
6721
6722   pr "#include <config.h>\n";
6723   pr "\n";
6724   pr "#include \"daemon.h\"\n";
6725   pr "#include \"optgroups.h\"\n";
6726   pr "\n";
6727
6728   pr "struct optgroup optgroups[] = {\n";
6729   List.iter (
6730     fun (group, _) ->
6731       pr "  { \"%s\", optgroup_%s_available },\n" group group
6732   ) optgroups;
6733   pr "  { NULL, NULL }\n";
6734   pr "};\n"
6735
6736 and generate_daemon_optgroups_h () =
6737   generate_header CStyle GPLv2plus;
6738
6739   List.iter (
6740     fun (group, _) ->
6741       pr "extern int optgroup_%s_available (void);\n" group
6742   ) optgroups
6743
6744 (* Generate the tests. *)
6745 and generate_tests () =
6746   generate_header CStyle GPLv2plus;
6747
6748   pr "\
6749 #include <stdio.h>
6750 #include <stdlib.h>
6751 #include <string.h>
6752 #include <unistd.h>
6753 #include <sys/types.h>
6754 #include <fcntl.h>
6755
6756 #include \"guestfs.h\"
6757 #include \"guestfs-internal.h\"
6758
6759 static guestfs_h *g;
6760 static int suppress_error = 0;
6761
6762 static void print_error (guestfs_h *g, void *data, const char *msg)
6763 {
6764   if (!suppress_error)
6765     fprintf (stderr, \"%%s\\n\", msg);
6766 }
6767
6768 /* FIXME: nearly identical code appears in fish.c */
6769 static void print_strings (char *const *argv)
6770 {
6771   int argc;
6772
6773   for (argc = 0; argv[argc] != NULL; ++argc)
6774     printf (\"\\t%%s\\n\", argv[argc]);
6775 }
6776
6777 /*
6778 static void print_table (char const *const *argv)
6779 {
6780   int i;
6781
6782   for (i = 0; argv[i] != NULL; i += 2)
6783     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6784 }
6785 */
6786
6787 ";
6788
6789   (* Generate a list of commands which are not tested anywhere. *)
6790   pr "static void no_test_warnings (void)\n";
6791   pr "{\n";
6792
6793   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6794   List.iter (
6795     fun (_, _, _, _, tests, _, _) ->
6796       let tests = filter_map (
6797         function
6798         | (_, (Always|If _|Unless _), test) -> Some test
6799         | (_, Disabled, _) -> None
6800       ) tests in
6801       let seq = List.concat (List.map seq_of_test tests) in
6802       let cmds_tested = List.map List.hd seq in
6803       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6804   ) all_functions;
6805
6806   List.iter (
6807     fun (name, _, _, _, _, _, _) ->
6808       if not (Hashtbl.mem hash name) then
6809         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6810   ) all_functions;
6811
6812   pr "}\n";
6813   pr "\n";
6814
6815   (* Generate the actual tests.  Note that we generate the tests
6816    * in reverse order, deliberately, so that (in general) the
6817    * newest tests run first.  This makes it quicker and easier to
6818    * debug them.
6819    *)
6820   let test_names =
6821     List.map (
6822       fun (name, _, _, flags, tests, _, _) ->
6823         mapi (generate_one_test name flags) tests
6824     ) (List.rev all_functions) in
6825   let test_names = List.concat test_names in
6826   let nr_tests = List.length test_names in
6827
6828   pr "\
6829 int main (int argc, char *argv[])
6830 {
6831   char c = 0;
6832   unsigned long int n_failed = 0;
6833   const char *filename;
6834   int fd;
6835   int nr_tests, test_num = 0;
6836
6837   setbuf (stdout, NULL);
6838
6839   no_test_warnings ();
6840
6841   g = guestfs_create ();
6842   if (g == NULL) {
6843     printf (\"guestfs_create FAILED\\n\");
6844     exit (EXIT_FAILURE);
6845   }
6846
6847   guestfs_set_error_handler (g, print_error, NULL);
6848
6849   guestfs_set_path (g, \"../appliance\");
6850
6851   filename = \"test1.img\";
6852   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6853   if (fd == -1) {
6854     perror (filename);
6855     exit (EXIT_FAILURE);
6856   }
6857   if (lseek (fd, %d, SEEK_SET) == -1) {
6858     perror (\"lseek\");
6859     close (fd);
6860     unlink (filename);
6861     exit (EXIT_FAILURE);
6862   }
6863   if (write (fd, &c, 1) == -1) {
6864     perror (\"write\");
6865     close (fd);
6866     unlink (filename);
6867     exit (EXIT_FAILURE);
6868   }
6869   if (close (fd) == -1) {
6870     perror (filename);
6871     unlink (filename);
6872     exit (EXIT_FAILURE);
6873   }
6874   if (guestfs_add_drive (g, filename) == -1) {
6875     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6876     exit (EXIT_FAILURE);
6877   }
6878
6879   filename = \"test2.img\";
6880   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6881   if (fd == -1) {
6882     perror (filename);
6883     exit (EXIT_FAILURE);
6884   }
6885   if (lseek (fd, %d, SEEK_SET) == -1) {
6886     perror (\"lseek\");
6887     close (fd);
6888     unlink (filename);
6889     exit (EXIT_FAILURE);
6890   }
6891   if (write (fd, &c, 1) == -1) {
6892     perror (\"write\");
6893     close (fd);
6894     unlink (filename);
6895     exit (EXIT_FAILURE);
6896   }
6897   if (close (fd) == -1) {
6898     perror (filename);
6899     unlink (filename);
6900     exit (EXIT_FAILURE);
6901   }
6902   if (guestfs_add_drive (g, filename) == -1) {
6903     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6904     exit (EXIT_FAILURE);
6905   }
6906
6907   filename = \"test3.img\";
6908   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6909   if (fd == -1) {
6910     perror (filename);
6911     exit (EXIT_FAILURE);
6912   }
6913   if (lseek (fd, %d, SEEK_SET) == -1) {
6914     perror (\"lseek\");
6915     close (fd);
6916     unlink (filename);
6917     exit (EXIT_FAILURE);
6918   }
6919   if (write (fd, &c, 1) == -1) {
6920     perror (\"write\");
6921     close (fd);
6922     unlink (filename);
6923     exit (EXIT_FAILURE);
6924   }
6925   if (close (fd) == -1) {
6926     perror (filename);
6927     unlink (filename);
6928     exit (EXIT_FAILURE);
6929   }
6930   if (guestfs_add_drive (g, filename) == -1) {
6931     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6932     exit (EXIT_FAILURE);
6933   }
6934
6935   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6936     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6937     exit (EXIT_FAILURE);
6938   }
6939
6940   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6941   alarm (600);
6942
6943   if (guestfs_launch (g) == -1) {
6944     printf (\"guestfs_launch FAILED\\n\");
6945     exit (EXIT_FAILURE);
6946   }
6947
6948   /* Cancel previous alarm. */
6949   alarm (0);
6950
6951   nr_tests = %d;
6952
6953 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6954
6955   iteri (
6956     fun i test_name ->
6957       pr "  test_num++;\n";
6958       pr "  if (guestfs_get_verbose (g))\n";
6959       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6960       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6961       pr "  if (%s () == -1) {\n" test_name;
6962       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6963       pr "    n_failed++;\n";
6964       pr "  }\n";
6965   ) test_names;
6966   pr "\n";
6967
6968   pr "  guestfs_close (g);\n";
6969   pr "  unlink (\"test1.img\");\n";
6970   pr "  unlink (\"test2.img\");\n";
6971   pr "  unlink (\"test3.img\");\n";
6972   pr "\n";
6973
6974   pr "  if (n_failed > 0) {\n";
6975   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6976   pr "    exit (EXIT_FAILURE);\n";
6977   pr "  }\n";
6978   pr "\n";
6979
6980   pr "  exit (EXIT_SUCCESS);\n";
6981   pr "}\n"
6982
6983 and generate_one_test name flags i (init, prereq, test) =
6984   let test_name = sprintf "test_%s_%d" name i in
6985
6986   pr "\
6987 static int %s_skip (void)
6988 {
6989   const char *str;
6990
6991   str = getenv (\"TEST_ONLY\");
6992   if (str)
6993     return strstr (str, \"%s\") == NULL;
6994   str = getenv (\"SKIP_%s\");
6995   if (str && STREQ (str, \"1\")) return 1;
6996   str = getenv (\"SKIP_TEST_%s\");
6997   if (str && STREQ (str, \"1\")) return 1;
6998   return 0;
6999 }
7000
7001 " test_name name (String.uppercase test_name) (String.uppercase name);
7002
7003   (match prereq with
7004    | Disabled | Always -> ()
7005    | If code | Unless code ->
7006        pr "static int %s_prereq (void)\n" test_name;
7007        pr "{\n";
7008        pr "  %s\n" code;
7009        pr "}\n";
7010        pr "\n";
7011   );
7012
7013   pr "\
7014 static int %s (void)
7015 {
7016   if (%s_skip ()) {
7017     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7018     return 0;
7019   }
7020
7021 " test_name test_name test_name;
7022
7023   (* Optional functions should only be tested if the relevant
7024    * support is available in the daemon.
7025    *)
7026   List.iter (
7027     function
7028     | Optional group ->
7029         pr "  {\n";
7030         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7031         pr "    int r;\n";
7032         pr "    suppress_error = 1;\n";
7033         pr "    r = guestfs_available (g, (char **) groups);\n";
7034         pr "    suppress_error = 0;\n";
7035         pr "    if (r == -1) {\n";
7036         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7037         pr "      return 0;\n";
7038         pr "    }\n";
7039         pr "  }\n";
7040     | _ -> ()
7041   ) flags;
7042
7043   (match prereq with
7044    | Disabled ->
7045        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7046    | If _ ->
7047        pr "  if (! %s_prereq ()) {\n" test_name;
7048        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7049        pr "    return 0;\n";
7050        pr "  }\n";
7051        pr "\n";
7052        generate_one_test_body name i test_name init test;
7053    | Unless _ ->
7054        pr "  if (%s_prereq ()) {\n" test_name;
7055        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7056        pr "    return 0;\n";
7057        pr "  }\n";
7058        pr "\n";
7059        generate_one_test_body name i test_name init test;
7060    | Always ->
7061        generate_one_test_body name i test_name init test
7062   );
7063
7064   pr "  return 0;\n";
7065   pr "}\n";
7066   pr "\n";
7067   test_name
7068
7069 and generate_one_test_body name i test_name init test =
7070   (match init with
7071    | InitNone (* XXX at some point, InitNone and InitEmpty became
7072                * folded together as the same thing.  Really we should
7073                * make InitNone do nothing at all, but the tests may
7074                * need to be checked to make sure this is OK.
7075                *)
7076    | InitEmpty ->
7077        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7078        List.iter (generate_test_command_call test_name)
7079          [["blockdev_setrw"; "/dev/sda"];
7080           ["umount_all"];
7081           ["lvm_remove_all"]]
7082    | InitPartition ->
7083        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7084        List.iter (generate_test_command_call test_name)
7085          [["blockdev_setrw"; "/dev/sda"];
7086           ["umount_all"];
7087           ["lvm_remove_all"];
7088           ["part_disk"; "/dev/sda"; "mbr"]]
7089    | InitBasicFS ->
7090        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7091        List.iter (generate_test_command_call test_name)
7092          [["blockdev_setrw"; "/dev/sda"];
7093           ["umount_all"];
7094           ["lvm_remove_all"];
7095           ["part_disk"; "/dev/sda"; "mbr"];
7096           ["mkfs"; "ext2"; "/dev/sda1"];
7097           ["mount_options"; ""; "/dev/sda1"; "/"]]
7098    | InitBasicFSonLVM ->
7099        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7100          test_name;
7101        List.iter (generate_test_command_call test_name)
7102          [["blockdev_setrw"; "/dev/sda"];
7103           ["umount_all"];
7104           ["lvm_remove_all"];
7105           ["part_disk"; "/dev/sda"; "mbr"];
7106           ["pvcreate"; "/dev/sda1"];
7107           ["vgcreate"; "VG"; "/dev/sda1"];
7108           ["lvcreate"; "LV"; "VG"; "8"];
7109           ["mkfs"; "ext2"; "/dev/VG/LV"];
7110           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7111    | InitISOFS ->
7112        pr "  /* InitISOFS for %s */\n" test_name;
7113        List.iter (generate_test_command_call test_name)
7114          [["blockdev_setrw"; "/dev/sda"];
7115           ["umount_all"];
7116           ["lvm_remove_all"];
7117           ["mount_ro"; "/dev/sdd"; "/"]]
7118   );
7119
7120   let get_seq_last = function
7121     | [] ->
7122         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7123           test_name
7124     | seq ->
7125         let seq = List.rev seq in
7126         List.rev (List.tl seq), List.hd seq
7127   in
7128
7129   match test with
7130   | TestRun seq ->
7131       pr "  /* TestRun for %s (%d) */\n" name i;
7132       List.iter (generate_test_command_call test_name) seq
7133   | TestOutput (seq, expected) ->
7134       pr "  /* TestOutput for %s (%d) */\n" name i;
7135       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7136       let seq, last = get_seq_last seq in
7137       let test () =
7138         pr "    if (STRNEQ (r, expected)) {\n";
7139         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7140         pr "      return -1;\n";
7141         pr "    }\n"
7142       in
7143       List.iter (generate_test_command_call test_name) seq;
7144       generate_test_command_call ~test test_name last
7145   | TestOutputList (seq, expected) ->
7146       pr "  /* TestOutputList for %s (%d) */\n" name i;
7147       let seq, last = get_seq_last seq in
7148       let test () =
7149         iteri (
7150           fun i str ->
7151             pr "    if (!r[%d]) {\n" i;
7152             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7153             pr "      print_strings (r);\n";
7154             pr "      return -1;\n";
7155             pr "    }\n";
7156             pr "    {\n";
7157             pr "      const char *expected = \"%s\";\n" (c_quote str);
7158             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7159             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7160             pr "        return -1;\n";
7161             pr "      }\n";
7162             pr "    }\n"
7163         ) expected;
7164         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7165         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7166           test_name;
7167         pr "      print_strings (r);\n";
7168         pr "      return -1;\n";
7169         pr "    }\n"
7170       in
7171       List.iter (generate_test_command_call test_name) seq;
7172       generate_test_command_call ~test test_name last
7173   | TestOutputListOfDevices (seq, expected) ->
7174       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7175       let seq, last = get_seq_last seq in
7176       let test () =
7177         iteri (
7178           fun i str ->
7179             pr "    if (!r[%d]) {\n" i;
7180             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7181             pr "      print_strings (r);\n";
7182             pr "      return -1;\n";
7183             pr "    }\n";
7184             pr "    {\n";
7185             pr "      const char *expected = \"%s\";\n" (c_quote str);
7186             pr "      r[%d][5] = 's';\n" i;
7187             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7188             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7189             pr "        return -1;\n";
7190             pr "      }\n";
7191             pr "    }\n"
7192         ) expected;
7193         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7194         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7195           test_name;
7196         pr "      print_strings (r);\n";
7197         pr "      return -1;\n";
7198         pr "    }\n"
7199       in
7200       List.iter (generate_test_command_call test_name) seq;
7201       generate_test_command_call ~test test_name last
7202   | TestOutputInt (seq, expected) ->
7203       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7204       let seq, last = get_seq_last seq in
7205       let test () =
7206         pr "    if (r != %d) {\n" expected;
7207         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7208           test_name expected;
7209         pr "               (int) r);\n";
7210         pr "      return -1;\n";
7211         pr "    }\n"
7212       in
7213       List.iter (generate_test_command_call test_name) seq;
7214       generate_test_command_call ~test test_name last
7215   | TestOutputIntOp (seq, op, expected) ->
7216       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7217       let seq, last = get_seq_last seq in
7218       let test () =
7219         pr "    if (! (r %s %d)) {\n" op expected;
7220         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7221           test_name op expected;
7222         pr "               (int) r);\n";
7223         pr "      return -1;\n";
7224         pr "    }\n"
7225       in
7226       List.iter (generate_test_command_call test_name) seq;
7227       generate_test_command_call ~test test_name last
7228   | TestOutputTrue seq ->
7229       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7230       let seq, last = get_seq_last seq in
7231       let test () =
7232         pr "    if (!r) {\n";
7233         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7234           test_name;
7235         pr "      return -1;\n";
7236         pr "    }\n"
7237       in
7238       List.iter (generate_test_command_call test_name) seq;
7239       generate_test_command_call ~test test_name last
7240   | TestOutputFalse seq ->
7241       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7242       let seq, last = get_seq_last seq in
7243       let test () =
7244         pr "    if (r) {\n";
7245         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7246           test_name;
7247         pr "      return -1;\n";
7248         pr "    }\n"
7249       in
7250       List.iter (generate_test_command_call test_name) seq;
7251       generate_test_command_call ~test test_name last
7252   | TestOutputLength (seq, expected) ->
7253       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7254       let seq, last = get_seq_last seq in
7255       let test () =
7256         pr "    int j;\n";
7257         pr "    for (j = 0; j < %d; ++j)\n" expected;
7258         pr "      if (r[j] == NULL) {\n";
7259         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7260           test_name;
7261         pr "        print_strings (r);\n";
7262         pr "        return -1;\n";
7263         pr "      }\n";
7264         pr "    if (r[j] != NULL) {\n";
7265         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7266           test_name;
7267         pr "      print_strings (r);\n";
7268         pr "      return -1;\n";
7269         pr "    }\n"
7270       in
7271       List.iter (generate_test_command_call test_name) seq;
7272       generate_test_command_call ~test test_name last
7273   | TestOutputBuffer (seq, expected) ->
7274       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7275       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7276       let seq, last = get_seq_last seq in
7277       let len = String.length expected in
7278       let test () =
7279         pr "    if (size != %d) {\n" len;
7280         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7281         pr "      return -1;\n";
7282         pr "    }\n";
7283         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7284         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7285         pr "      return -1;\n";
7286         pr "    }\n"
7287       in
7288       List.iter (generate_test_command_call test_name) seq;
7289       generate_test_command_call ~test test_name last
7290   | TestOutputStruct (seq, checks) ->
7291       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7292       let seq, last = get_seq_last seq in
7293       let test () =
7294         List.iter (
7295           function
7296           | CompareWithInt (field, expected) ->
7297               pr "    if (r->%s != %d) {\n" field expected;
7298               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7299                 test_name field expected;
7300               pr "               (int) r->%s);\n" field;
7301               pr "      return -1;\n";
7302               pr "    }\n"
7303           | CompareWithIntOp (field, op, expected) ->
7304               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7305               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7306                 test_name field op expected;
7307               pr "               (int) r->%s);\n" field;
7308               pr "      return -1;\n";
7309               pr "    }\n"
7310           | CompareWithString (field, expected) ->
7311               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7312               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7313                 test_name field expected;
7314               pr "               r->%s);\n" field;
7315               pr "      return -1;\n";
7316               pr "    }\n"
7317           | CompareFieldsIntEq (field1, field2) ->
7318               pr "    if (r->%s != r->%s) {\n" field1 field2;
7319               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7320                 test_name field1 field2;
7321               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7322               pr "      return -1;\n";
7323               pr "    }\n"
7324           | CompareFieldsStrEq (field1, field2) ->
7325               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7326               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7327                 test_name field1 field2;
7328               pr "               r->%s, r->%s);\n" field1 field2;
7329               pr "      return -1;\n";
7330               pr "    }\n"
7331         ) checks
7332       in
7333       List.iter (generate_test_command_call test_name) seq;
7334       generate_test_command_call ~test test_name last
7335   | TestLastFail seq ->
7336       pr "  /* TestLastFail for %s (%d) */\n" name i;
7337       let seq, last = get_seq_last seq in
7338       List.iter (generate_test_command_call test_name) seq;
7339       generate_test_command_call test_name ~expect_error:true last
7340
7341 (* Generate the code to run a command, leaving the result in 'r'.
7342  * If you expect to get an error then you should set expect_error:true.
7343  *)
7344 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7345   match cmd with
7346   | [] -> assert false
7347   | name :: args ->
7348       (* Look up the command to find out what args/ret it has. *)
7349       let style =
7350         try
7351           let _, style, _, _, _, _, _ =
7352             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7353           style
7354         with Not_found ->
7355           failwithf "%s: in test, command %s was not found" test_name name in
7356
7357       if List.length (snd style) <> List.length args then
7358         failwithf "%s: in test, wrong number of args given to %s"
7359           test_name name;
7360
7361       pr "  {\n";
7362
7363       List.iter (
7364         function
7365         | OptString n, "NULL" -> ()
7366         | Pathname n, arg
7367         | Device n, arg
7368         | Dev_or_Path n, arg
7369         | String n, arg
7370         | OptString n, arg ->
7371             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7372         | BufferIn n, arg ->
7373             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7374             pr "    size_t %s_size = %d;\n" n (String.length arg)
7375         | Int _, _
7376         | Int64 _, _
7377         | Bool _, _
7378         | FileIn _, _ | FileOut _, _ -> ()
7379         | StringList n, "" | DeviceList n, "" ->
7380             pr "    const char *const %s[1] = { NULL };\n" n
7381         | StringList n, arg | DeviceList n, arg ->
7382             let strs = string_split " " arg in
7383             iteri (
7384               fun i str ->
7385                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7386             ) strs;
7387             pr "    const char *const %s[] = {\n" n;
7388             iteri (
7389               fun i _ -> pr "      %s_%d,\n" n i
7390             ) strs;
7391             pr "      NULL\n";
7392             pr "    };\n";
7393       ) (List.combine (snd style) args);
7394
7395       let error_code =
7396         match fst style with
7397         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7398         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7399         | RConstString _ | RConstOptString _ ->
7400             pr "    const char *r;\n"; "NULL"
7401         | RString _ -> pr "    char *r;\n"; "NULL"
7402         | RStringList _ | RHashtable _ ->
7403             pr "    char **r;\n";
7404             pr "    int i;\n";
7405             "NULL"
7406         | RStruct (_, typ) ->
7407             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7408         | RStructList (_, typ) ->
7409             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7410         | RBufferOut _ ->
7411             pr "    char *r;\n";
7412             pr "    size_t size;\n";
7413             "NULL" in
7414
7415       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7416       pr "    r = guestfs_%s (g" name;
7417
7418       (* Generate the parameters. *)
7419       List.iter (
7420         function
7421         | OptString _, "NULL" -> pr ", NULL"
7422         | Pathname n, _
7423         | Device n, _ | Dev_or_Path n, _
7424         | String n, _
7425         | OptString n, _ ->
7426             pr ", %s" n
7427         | BufferIn n, _ ->
7428             pr ", %s, %s_size" n n
7429         | FileIn _, arg | FileOut _, arg ->
7430             pr ", \"%s\"" (c_quote arg)
7431         | StringList n, _ | DeviceList n, _ ->
7432             pr ", (char **) %s" n
7433         | Int _, arg ->
7434             let i =
7435               try int_of_string arg
7436               with Failure "int_of_string" ->
7437                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7438             pr ", %d" i
7439         | Int64 _, arg ->
7440             let i =
7441               try Int64.of_string arg
7442               with Failure "int_of_string" ->
7443                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7444             pr ", %Ld" i
7445         | Bool _, arg ->
7446             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7447       ) (List.combine (snd style) args);
7448
7449       (match fst style with
7450        | RBufferOut _ -> pr ", &size"
7451        | _ -> ()
7452       );
7453
7454       pr ");\n";
7455
7456       if not expect_error then
7457         pr "    if (r == %s)\n" error_code
7458       else
7459         pr "    if (r != %s)\n" error_code;
7460       pr "      return -1;\n";
7461
7462       (* Insert the test code. *)
7463       (match test with
7464        | None -> ()
7465        | Some f -> f ()
7466       );
7467
7468       (match fst style with
7469        | RErr | RInt _ | RInt64 _ | RBool _
7470        | RConstString _ | RConstOptString _ -> ()
7471        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7472        | RStringList _ | RHashtable _ ->
7473            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7474            pr "      free (r[i]);\n";
7475            pr "    free (r);\n"
7476        | RStruct (_, typ) ->
7477            pr "    guestfs_free_%s (r);\n" typ
7478        | RStructList (_, typ) ->
7479            pr "    guestfs_free_%s_list (r);\n" typ
7480       );
7481
7482       pr "  }\n"
7483
7484 and c_quote str =
7485   let str = replace_str str "\r" "\\r" in
7486   let str = replace_str str "\n" "\\n" in
7487   let str = replace_str str "\t" "\\t" in
7488   let str = replace_str str "\000" "\\0" in
7489   str
7490
7491 (* Generate a lot of different functions for guestfish. *)
7492 and generate_fish_cmds () =
7493   generate_header CStyle GPLv2plus;
7494
7495   let all_functions =
7496     List.filter (
7497       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7498     ) all_functions in
7499   let all_functions_sorted =
7500     List.filter (
7501       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7502     ) all_functions_sorted in
7503
7504   pr "#include <config.h>\n";
7505   pr "\n";
7506   pr "#include <stdio.h>\n";
7507   pr "#include <stdlib.h>\n";
7508   pr "#include <string.h>\n";
7509   pr "#include <inttypes.h>\n";
7510   pr "\n";
7511   pr "#include <guestfs.h>\n";
7512   pr "#include \"c-ctype.h\"\n";
7513   pr "#include \"full-write.h\"\n";
7514   pr "#include \"xstrtol.h\"\n";
7515   pr "#include \"fish.h\"\n";
7516   pr "\n";
7517   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7518   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7519   pr "\n";
7520
7521   (* list_commands function, which implements guestfish -h *)
7522   pr "void list_commands (void)\n";
7523   pr "{\n";
7524   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7525   pr "  list_builtin_commands ();\n";
7526   List.iter (
7527     fun (name, _, _, flags, _, shortdesc, _) ->
7528       let name = replace_char name '_' '-' in
7529       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7530         name shortdesc
7531   ) all_functions_sorted;
7532   pr "  printf (\"    %%s\\n\",";
7533   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7534   pr "}\n";
7535   pr "\n";
7536
7537   (* display_command function, which implements guestfish -h cmd *)
7538   pr "void display_command (const char *cmd)\n";
7539   pr "{\n";
7540   List.iter (
7541     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7542       let name2 = replace_char name '_' '-' in
7543       let alias =
7544         try find_map (function FishAlias n -> Some n | _ -> None) flags
7545         with Not_found -> name in
7546       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7547       let synopsis =
7548         match snd style with
7549         | [] -> name2
7550         | args ->
7551             sprintf "%s %s"
7552               name2 (String.concat " " (List.map name_of_argt args)) in
7553
7554       let warnings =
7555         if List.mem ProtocolLimitWarning flags then
7556           ("\n\n" ^ protocol_limit_warning)
7557         else "" in
7558
7559       (* For DangerWillRobinson commands, we should probably have
7560        * guestfish prompt before allowing you to use them (especially
7561        * in interactive mode). XXX
7562        *)
7563       let warnings =
7564         warnings ^
7565           if List.mem DangerWillRobinson flags then
7566             ("\n\n" ^ danger_will_robinson)
7567           else "" in
7568
7569       let warnings =
7570         warnings ^
7571           match deprecation_notice flags with
7572           | None -> ""
7573           | Some txt -> "\n\n" ^ txt in
7574
7575       let describe_alias =
7576         if name <> alias then
7577           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7578         else "" in
7579
7580       pr "  if (";
7581       pr "STRCASEEQ (cmd, \"%s\")" name;
7582       if name <> name2 then
7583         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7584       if name <> alias then
7585         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7586       pr ")\n";
7587       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7588         name2 shortdesc
7589         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7590          "=head1 DESCRIPTION\n\n" ^
7591          longdesc ^ warnings ^ describe_alias);
7592       pr "  else\n"
7593   ) all_functions;
7594   pr "    display_builtin_command (cmd);\n";
7595   pr "}\n";
7596   pr "\n";
7597
7598   let emit_print_list_function typ =
7599     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7600       typ typ typ;
7601     pr "{\n";
7602     pr "  unsigned int i;\n";
7603     pr "\n";
7604     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7605     pr "    printf (\"[%%d] = {\\n\", i);\n";
7606     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7607     pr "    printf (\"}\\n\");\n";
7608     pr "  }\n";
7609     pr "}\n";
7610     pr "\n";
7611   in
7612
7613   (* print_* functions *)
7614   List.iter (
7615     fun (typ, cols) ->
7616       let needs_i =
7617         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7618
7619       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7620       pr "{\n";
7621       if needs_i then (
7622         pr "  unsigned int i;\n";
7623         pr "\n"
7624       );
7625       List.iter (
7626         function
7627         | name, FString ->
7628             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7629         | name, FUUID ->
7630             pr "  printf (\"%%s%s: \", indent);\n" name;
7631             pr "  for (i = 0; i < 32; ++i)\n";
7632             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7633             pr "  printf (\"\\n\");\n"
7634         | name, FBuffer ->
7635             pr "  printf (\"%%s%s: \", indent);\n" name;
7636             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7637             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7638             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7639             pr "    else\n";
7640             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7641             pr "  printf (\"\\n\");\n"
7642         | name, (FUInt64|FBytes) ->
7643             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7644               name typ name
7645         | name, FInt64 ->
7646             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7647               name typ name
7648         | name, FUInt32 ->
7649             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7650               name typ name
7651         | name, FInt32 ->
7652             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7653               name typ name
7654         | name, FChar ->
7655             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7656               name typ name
7657         | name, FOptPercent ->
7658             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7659               typ name name typ name;
7660             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7661       ) cols;
7662       pr "}\n";
7663       pr "\n";
7664   ) structs;
7665
7666   (* Emit a print_TYPE_list function definition only if that function is used. *)
7667   List.iter (
7668     function
7669     | typ, (RStructListOnly | RStructAndList) ->
7670         (* generate the function for typ *)
7671         emit_print_list_function typ
7672     | typ, _ -> () (* empty *)
7673   ) (rstructs_used_by all_functions);
7674
7675   (* Emit a print_TYPE function definition only if that function is used. *)
7676   List.iter (
7677     function
7678     | typ, (RStructOnly | RStructAndList) ->
7679         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7680         pr "{\n";
7681         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7682         pr "}\n";
7683         pr "\n";
7684     | typ, _ -> () (* empty *)
7685   ) (rstructs_used_by all_functions);
7686
7687   (* run_<action> actions *)
7688   List.iter (
7689     fun (name, style, _, flags, _, _, _) ->
7690       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7691       pr "{\n";
7692       (match fst style with
7693        | RErr
7694        | RInt _
7695        | RBool _ -> pr "  int r;\n"
7696        | RInt64 _ -> pr "  int64_t r;\n"
7697        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7698        | RString _ -> pr "  char *r;\n"
7699        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7700        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7701        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7702        | RBufferOut _ ->
7703            pr "  char *r;\n";
7704            pr "  size_t size;\n";
7705       );
7706       List.iter (
7707         function
7708         | Device n
7709         | String n
7710         | OptString n -> pr "  const char *%s;\n" n
7711         | Pathname n
7712         | Dev_or_Path n
7713         | FileIn n
7714         | FileOut n -> pr "  char *%s;\n" n
7715         | BufferIn n ->
7716             pr "  const char *%s;\n" n;
7717             pr "  size_t %s_size;\n" n
7718         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7719         | Bool n -> pr "  int %s;\n" n
7720         | Int n -> pr "  int %s;\n" n
7721         | Int64 n -> pr "  int64_t %s;\n" n
7722       ) (snd style);
7723
7724       (* Check and convert parameters. *)
7725       let argc_expected = List.length (snd style) in
7726       pr "  if (argc != %d) {\n" argc_expected;
7727       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7728         argc_expected;
7729       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7730       pr "    return -1;\n";
7731       pr "  }\n";
7732
7733       let parse_integer fn fntyp rtyp range name i =
7734         pr "  {\n";
7735         pr "    strtol_error xerr;\n";
7736         pr "    %s r;\n" fntyp;
7737         pr "\n";
7738         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7739         pr "    if (xerr != LONGINT_OK) {\n";
7740         pr "      fprintf (stderr,\n";
7741         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7742         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7743         pr "      return -1;\n";
7744         pr "    }\n";
7745         (match range with
7746          | None -> ()
7747          | Some (min, max, comment) ->
7748              pr "    /* %s */\n" comment;
7749              pr "    if (r < %s || r > %s) {\n" min max;
7750              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7751                name;
7752              pr "      return -1;\n";
7753              pr "    }\n";
7754              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7755         );
7756         pr "    %s = r;\n" name;
7757         pr "  }\n";
7758       in
7759
7760       iteri (
7761         fun i ->
7762           function
7763           | Device name
7764           | String name ->
7765               pr "  %s = argv[%d];\n" name i
7766           | Pathname name
7767           | Dev_or_Path name ->
7768               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7769               pr "  if (%s == NULL) return -1;\n" name
7770           | OptString name ->
7771               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7772                 name i i
7773           | BufferIn name ->
7774               pr "  %s = argv[%d];\n" name i;
7775               pr "  %s_size = strlen (argv[%d]);\n" name i
7776           | FileIn name ->
7777               pr "  %s = file_in (argv[%d]);\n" name i;
7778               pr "  if (%s == NULL) return -1;\n" name
7779           | FileOut name ->
7780               pr "  %s = file_out (argv[%d]);\n" name i;
7781               pr "  if (%s == NULL) return -1;\n" name
7782           | StringList name | DeviceList name ->
7783               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7784               pr "  if (%s == NULL) return -1;\n" name;
7785           | Bool name ->
7786               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7787           | Int name ->
7788               let range =
7789                 let min = "(-(2LL<<30))"
7790                 and max = "((2LL<<30)-1)"
7791                 and comment =
7792                   "The Int type in the generator is a signed 31 bit int." in
7793                 Some (min, max, comment) in
7794               parse_integer "xstrtoll" "long long" "int" range name i
7795           | Int64 name ->
7796               parse_integer "xstrtoll" "long long" "int64_t" None name i
7797       ) (snd style);
7798
7799       (* Call C API function. *)
7800       pr "  r = guestfs_%s " name;
7801       generate_c_call_args ~handle:"g" style;
7802       pr ";\n";
7803
7804       List.iter (
7805         function
7806         | Device name | String name
7807         | OptString name | Bool name
7808         | Int name | Int64 name
7809         | BufferIn name -> ()
7810         | Pathname name | Dev_or_Path name | FileOut name ->
7811             pr "  free (%s);\n" name
7812         | FileIn name ->
7813             pr "  free_file_in (%s);\n" name
7814         | StringList name | DeviceList name ->
7815             pr "  free_strings (%s);\n" name
7816       ) (snd style);
7817
7818       (* Any output flags? *)
7819       let fish_output =
7820         let flags = filter_map (
7821           function FishOutput flag -> Some flag | _ -> None
7822         ) flags in
7823         match flags with
7824         | [] -> None
7825         | [f] -> Some f
7826         | _ ->
7827             failwithf "%s: more than one FishOutput flag is not allowed" name in
7828
7829       (* Check return value for errors and display command results. *)
7830       (match fst style with
7831        | RErr -> pr "  return r;\n"
7832        | RInt _ ->
7833            pr "  if (r == -1) return -1;\n";
7834            (match fish_output with
7835             | None ->
7836                 pr "  printf (\"%%d\\n\", r);\n";
7837             | Some FishOutputOctal ->
7838                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7839             | Some FishOutputHexadecimal ->
7840                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7841            pr "  return 0;\n"
7842        | RInt64 _ ->
7843            pr "  if (r == -1) return -1;\n";
7844            (match fish_output with
7845             | None ->
7846                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7847             | Some FishOutputOctal ->
7848                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7849             | Some FishOutputHexadecimal ->
7850                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7851            pr "  return 0;\n"
7852        | RBool _ ->
7853            pr "  if (r == -1) return -1;\n";
7854            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7855            pr "  return 0;\n"
7856        | RConstString _ ->
7857            pr "  if (r == NULL) return -1;\n";
7858            pr "  printf (\"%%s\\n\", r);\n";
7859            pr "  return 0;\n"
7860        | RConstOptString _ ->
7861            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7862            pr "  return 0;\n"
7863        | RString _ ->
7864            pr "  if (r == NULL) return -1;\n";
7865            pr "  printf (\"%%s\\n\", r);\n";
7866            pr "  free (r);\n";
7867            pr "  return 0;\n"
7868        | RStringList _ ->
7869            pr "  if (r == NULL) return -1;\n";
7870            pr "  print_strings (r);\n";
7871            pr "  free_strings (r);\n";
7872            pr "  return 0;\n"
7873        | RStruct (_, typ) ->
7874            pr "  if (r == NULL) return -1;\n";
7875            pr "  print_%s (r);\n" typ;
7876            pr "  guestfs_free_%s (r);\n" typ;
7877            pr "  return 0;\n"
7878        | RStructList (_, typ) ->
7879            pr "  if (r == NULL) return -1;\n";
7880            pr "  print_%s_list (r);\n" typ;
7881            pr "  guestfs_free_%s_list (r);\n" typ;
7882            pr "  return 0;\n"
7883        | RHashtable _ ->
7884            pr "  if (r == NULL) return -1;\n";
7885            pr "  print_table (r);\n";
7886            pr "  free_strings (r);\n";
7887            pr "  return 0;\n"
7888        | RBufferOut _ ->
7889            pr "  if (r == NULL) return -1;\n";
7890            pr "  if (full_write (1, r, size) != size) {\n";
7891            pr "    perror (\"write\");\n";
7892            pr "    free (r);\n";
7893            pr "    return -1;\n";
7894            pr "  }\n";
7895            pr "  free (r);\n";
7896            pr "  return 0;\n"
7897       );
7898       pr "}\n";
7899       pr "\n"
7900   ) all_functions;
7901
7902   (* run_action function *)
7903   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7904   pr "{\n";
7905   List.iter (
7906     fun (name, _, _, flags, _, _, _) ->
7907       let name2 = replace_char name '_' '-' in
7908       let alias =
7909         try find_map (function FishAlias n -> Some n | _ -> None) flags
7910         with Not_found -> name in
7911       pr "  if (";
7912       pr "STRCASEEQ (cmd, \"%s\")" name;
7913       if name <> name2 then
7914         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7915       if name <> alias then
7916         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7917       pr ")\n";
7918       pr "    return run_%s (cmd, argc, argv);\n" name;
7919       pr "  else\n";
7920   ) all_functions;
7921   pr "    {\n";
7922   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7923   pr "      if (command_num == 1)\n";
7924   pr "        extended_help_message ();\n";
7925   pr "      return -1;\n";
7926   pr "    }\n";
7927   pr "  return 0;\n";
7928   pr "}\n";
7929   pr "\n"
7930
7931 (* Readline completion for guestfish. *)
7932 and generate_fish_completion () =
7933   generate_header CStyle GPLv2plus;
7934
7935   let all_functions =
7936     List.filter (
7937       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7938     ) all_functions in
7939
7940   pr "\
7941 #include <config.h>
7942
7943 #include <stdio.h>
7944 #include <stdlib.h>
7945 #include <string.h>
7946
7947 #ifdef HAVE_LIBREADLINE
7948 #include <readline/readline.h>
7949 #endif
7950
7951 #include \"fish.h\"
7952
7953 #ifdef HAVE_LIBREADLINE
7954
7955 static const char *const commands[] = {
7956   BUILTIN_COMMANDS_FOR_COMPLETION,
7957 ";
7958
7959   (* Get the commands, including the aliases.  They don't need to be
7960    * sorted - the generator() function just does a dumb linear search.
7961    *)
7962   let commands =
7963     List.map (
7964       fun (name, _, _, flags, _, _, _) ->
7965         let name2 = replace_char name '_' '-' in
7966         let alias =
7967           try find_map (function FishAlias n -> Some n | _ -> None) flags
7968           with Not_found -> name in
7969
7970         if name <> alias then [name2; alias] else [name2]
7971     ) all_functions in
7972   let commands = List.flatten commands in
7973
7974   List.iter (pr "  \"%s\",\n") commands;
7975
7976   pr "  NULL
7977 };
7978
7979 static char *
7980 generator (const char *text, int state)
7981 {
7982   static int index, len;
7983   const char *name;
7984
7985   if (!state) {
7986     index = 0;
7987     len = strlen (text);
7988   }
7989
7990   rl_attempted_completion_over = 1;
7991
7992   while ((name = commands[index]) != NULL) {
7993     index++;
7994     if (STRCASEEQLEN (name, text, len))
7995       return strdup (name);
7996   }
7997
7998   return NULL;
7999 }
8000
8001 #endif /* HAVE_LIBREADLINE */
8002
8003 #ifdef HAVE_RL_COMPLETION_MATCHES
8004 #define RL_COMPLETION_MATCHES rl_completion_matches
8005 #else
8006 #ifdef HAVE_COMPLETION_MATCHES
8007 #define RL_COMPLETION_MATCHES completion_matches
8008 #endif
8009 #endif /* else just fail if we don't have either symbol */
8010
8011 char **
8012 do_completion (const char *text, int start, int end)
8013 {
8014   char **matches = NULL;
8015
8016 #ifdef HAVE_LIBREADLINE
8017   rl_completion_append_character = ' ';
8018
8019   if (start == 0)
8020     matches = RL_COMPLETION_MATCHES (text, generator);
8021   else if (complete_dest_paths)
8022     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8023 #endif
8024
8025   return matches;
8026 }
8027 ";
8028
8029 (* Generate the POD documentation for guestfish. *)
8030 and generate_fish_actions_pod () =
8031   let all_functions_sorted =
8032     List.filter (
8033       fun (_, _, _, flags, _, _, _) ->
8034         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8035     ) all_functions_sorted in
8036
8037   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8038
8039   List.iter (
8040     fun (name, style, _, flags, _, _, longdesc) ->
8041       let longdesc =
8042         Str.global_substitute rex (
8043           fun s ->
8044             let sub =
8045               try Str.matched_group 1 s
8046               with Not_found ->
8047                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8048             "C<" ^ replace_char sub '_' '-' ^ ">"
8049         ) longdesc in
8050       let name = replace_char name '_' '-' in
8051       let alias =
8052         try find_map (function FishAlias n -> Some n | _ -> None) flags
8053         with Not_found -> name in
8054
8055       pr "=head2 %s" name;
8056       if name <> alias then
8057         pr " | %s" alias;
8058       pr "\n";
8059       pr "\n";
8060       pr " %s" name;
8061       List.iter (
8062         function
8063         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8064         | OptString n -> pr " %s" n
8065         | StringList n | DeviceList n -> pr " '%s ...'" n
8066         | Bool _ -> pr " true|false"
8067         | Int n -> pr " %s" n
8068         | Int64 n -> pr " %s" n
8069         | FileIn n | FileOut n -> pr " (%s|-)" n
8070         | BufferIn n -> pr " %s" n
8071       ) (snd style);
8072       pr "\n";
8073       pr "\n";
8074       pr "%s\n\n" longdesc;
8075
8076       if List.exists (function FileIn _ | FileOut _ -> true
8077                       | _ -> false) (snd style) then
8078         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8079
8080       if List.mem ProtocolLimitWarning flags then
8081         pr "%s\n\n" protocol_limit_warning;
8082
8083       if List.mem DangerWillRobinson flags then
8084         pr "%s\n\n" danger_will_robinson;
8085
8086       match deprecation_notice flags with
8087       | None -> ()
8088       | Some txt -> pr "%s\n\n" txt
8089   ) all_functions_sorted
8090
8091 (* Generate a C function prototype. *)
8092 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8093     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8094     ?(prefix = "")
8095     ?handle name style =
8096   if extern then pr "extern ";
8097   if static then pr "static ";
8098   (match fst style with
8099    | RErr -> pr "int "
8100    | RInt _ -> pr "int "
8101    | RInt64 _ -> pr "int64_t "
8102    | RBool _ -> pr "int "
8103    | RConstString _ | RConstOptString _ -> pr "const char *"
8104    | RString _ | RBufferOut _ -> pr "char *"
8105    | RStringList _ | RHashtable _ -> pr "char **"
8106    | RStruct (_, typ) ->
8107        if not in_daemon then pr "struct guestfs_%s *" typ
8108        else pr "guestfs_int_%s *" typ
8109    | RStructList (_, typ) ->
8110        if not in_daemon then pr "struct guestfs_%s_list *" typ
8111        else pr "guestfs_int_%s_list *" typ
8112   );
8113   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8114   pr "%s%s (" prefix name;
8115   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8116     pr "void"
8117   else (
8118     let comma = ref false in
8119     (match handle with
8120      | None -> ()
8121      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8122     );
8123     let next () =
8124       if !comma then (
8125         if single_line then pr ", " else pr ",\n\t\t"
8126       );
8127       comma := true
8128     in
8129     List.iter (
8130       function
8131       | Pathname n
8132       | Device n | Dev_or_Path n
8133       | String n
8134       | OptString n ->
8135           next ();
8136           pr "const char *%s" n
8137       | StringList n | DeviceList n ->
8138           next ();
8139           pr "char *const *%s" n
8140       | Bool n -> next (); pr "int %s" n
8141       | Int n -> next (); pr "int %s" n
8142       | Int64 n -> next (); pr "int64_t %s" n
8143       | FileIn n
8144       | FileOut n ->
8145           if not in_daemon then (next (); pr "const char *%s" n)
8146       | BufferIn n ->
8147           next ();
8148           pr "const char *%s" n;
8149           next ();
8150           pr "size_t %s_size" n
8151     ) (snd style);
8152     if is_RBufferOut then (next (); pr "size_t *size_r");
8153   );
8154   pr ")";
8155   if semicolon then pr ";";
8156   if newline then pr "\n"
8157
8158 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8159 and generate_c_call_args ?handle ?(decl = false) style =
8160   pr "(";
8161   let comma = ref false in
8162   let next () =
8163     if !comma then pr ", ";
8164     comma := true
8165   in
8166   (match handle with
8167    | None -> ()
8168    | Some handle -> pr "%s" handle; comma := true
8169   );
8170   List.iter (
8171     function
8172     | BufferIn n ->
8173         next ();
8174         pr "%s, %s_size" n n
8175     | arg ->
8176         next ();
8177         pr "%s" (name_of_argt arg)
8178   ) (snd style);
8179   (* For RBufferOut calls, add implicit &size parameter. *)
8180   if not decl then (
8181     match fst style with
8182     | RBufferOut _ ->
8183         next ();
8184         pr "&size"
8185     | _ -> ()
8186   );
8187   pr ")"
8188
8189 (* Generate the OCaml bindings interface. *)
8190 and generate_ocaml_mli () =
8191   generate_header OCamlStyle LGPLv2plus;
8192
8193   pr "\
8194 (** For API documentation you should refer to the C API
8195     in the guestfs(3) manual page.  The OCaml API uses almost
8196     exactly the same calls. *)
8197
8198 type t
8199 (** A [guestfs_h] handle. *)
8200
8201 exception Error of string
8202 (** This exception is raised when there is an error. *)
8203
8204 exception Handle_closed of string
8205 (** This exception is raised if you use a {!Guestfs.t} handle
8206     after calling {!close} on it.  The string is the name of
8207     the function. *)
8208
8209 val create : unit -> t
8210 (** Create a {!Guestfs.t} handle. *)
8211
8212 val close : t -> unit
8213 (** Close the {!Guestfs.t} handle and free up all resources used
8214     by it immediately.
8215
8216     Handles are closed by the garbage collector when they become
8217     unreferenced, but callers can call this in order to provide
8218     predictable cleanup. *)
8219
8220 ";
8221   generate_ocaml_structure_decls ();
8222
8223   (* The actions. *)
8224   List.iter (
8225     fun (name, style, _, _, _, shortdesc, _) ->
8226       generate_ocaml_prototype name style;
8227       pr "(** %s *)\n" shortdesc;
8228       pr "\n"
8229   ) all_functions_sorted
8230
8231 (* Generate the OCaml bindings implementation. *)
8232 and generate_ocaml_ml () =
8233   generate_header OCamlStyle LGPLv2plus;
8234
8235   pr "\
8236 type t
8237
8238 exception Error of string
8239 exception Handle_closed of string
8240
8241 external create : unit -> t = \"ocaml_guestfs_create\"
8242 external close : t -> unit = \"ocaml_guestfs_close\"
8243
8244 (* Give the exceptions names, so they can be raised from the C code. *)
8245 let () =
8246   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8247   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8248
8249 ";
8250
8251   generate_ocaml_structure_decls ();
8252
8253   (* The actions. *)
8254   List.iter (
8255     fun (name, style, _, _, _, shortdesc, _) ->
8256       generate_ocaml_prototype ~is_external:true name style;
8257   ) all_functions_sorted
8258
8259 (* Generate the OCaml bindings C implementation. *)
8260 and generate_ocaml_c () =
8261   generate_header CStyle LGPLv2plus;
8262
8263   pr "\
8264 #include <stdio.h>
8265 #include <stdlib.h>
8266 #include <string.h>
8267
8268 #include <caml/config.h>
8269 #include <caml/alloc.h>
8270 #include <caml/callback.h>
8271 #include <caml/fail.h>
8272 #include <caml/memory.h>
8273 #include <caml/mlvalues.h>
8274 #include <caml/signals.h>
8275
8276 #include <guestfs.h>
8277
8278 #include \"guestfs_c.h\"
8279
8280 /* Copy a hashtable of string pairs into an assoc-list.  We return
8281  * the list in reverse order, but hashtables aren't supposed to be
8282  * ordered anyway.
8283  */
8284 static CAMLprim value
8285 copy_table (char * const * argv)
8286 {
8287   CAMLparam0 ();
8288   CAMLlocal5 (rv, pairv, kv, vv, cons);
8289   int i;
8290
8291   rv = Val_int (0);
8292   for (i = 0; argv[i] != NULL; i += 2) {
8293     kv = caml_copy_string (argv[i]);
8294     vv = caml_copy_string (argv[i+1]);
8295     pairv = caml_alloc (2, 0);
8296     Store_field (pairv, 0, kv);
8297     Store_field (pairv, 1, vv);
8298     cons = caml_alloc (2, 0);
8299     Store_field (cons, 1, rv);
8300     rv = cons;
8301     Store_field (cons, 0, pairv);
8302   }
8303
8304   CAMLreturn (rv);
8305 }
8306
8307 ";
8308
8309   (* Struct copy functions. *)
8310
8311   let emit_ocaml_copy_list_function typ =
8312     pr "static CAMLprim value\n";
8313     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8314     pr "{\n";
8315     pr "  CAMLparam0 ();\n";
8316     pr "  CAMLlocal2 (rv, v);\n";
8317     pr "  unsigned int i;\n";
8318     pr "\n";
8319     pr "  if (%ss->len == 0)\n" typ;
8320     pr "    CAMLreturn (Atom (0));\n";
8321     pr "  else {\n";
8322     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8323     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8324     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8325     pr "      caml_modify (&Field (rv, i), v);\n";
8326     pr "    }\n";
8327     pr "    CAMLreturn (rv);\n";
8328     pr "  }\n";
8329     pr "}\n";
8330     pr "\n";
8331   in
8332
8333   List.iter (
8334     fun (typ, cols) ->
8335       let has_optpercent_col =
8336         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8337
8338       pr "static CAMLprim value\n";
8339       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8340       pr "{\n";
8341       pr "  CAMLparam0 ();\n";
8342       if has_optpercent_col then
8343         pr "  CAMLlocal3 (rv, v, v2);\n"
8344       else
8345         pr "  CAMLlocal2 (rv, v);\n";
8346       pr "\n";
8347       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8348       iteri (
8349         fun i col ->
8350           (match col with
8351            | name, FString ->
8352                pr "  v = caml_copy_string (%s->%s);\n" typ name
8353            | name, FBuffer ->
8354                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8355                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8356                  typ name typ name
8357            | name, FUUID ->
8358                pr "  v = caml_alloc_string (32);\n";
8359                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8360            | name, (FBytes|FInt64|FUInt64) ->
8361                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8362            | name, (FInt32|FUInt32) ->
8363                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8364            | name, FOptPercent ->
8365                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8366                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8367                pr "    v = caml_alloc (1, 0);\n";
8368                pr "    Store_field (v, 0, v2);\n";
8369                pr "  } else /* None */\n";
8370                pr "    v = Val_int (0);\n";
8371            | name, FChar ->
8372                pr "  v = Val_int (%s->%s);\n" typ name
8373           );
8374           pr "  Store_field (rv, %d, v);\n" i
8375       ) cols;
8376       pr "  CAMLreturn (rv);\n";
8377       pr "}\n";
8378       pr "\n";
8379   ) structs;
8380
8381   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8382   List.iter (
8383     function
8384     | typ, (RStructListOnly | RStructAndList) ->
8385         (* generate the function for typ *)
8386         emit_ocaml_copy_list_function typ
8387     | typ, _ -> () (* empty *)
8388   ) (rstructs_used_by all_functions);
8389
8390   (* The wrappers. *)
8391   List.iter (
8392     fun (name, style, _, _, _, _, _) ->
8393       pr "/* Automatically generated wrapper for function\n";
8394       pr " * ";
8395       generate_ocaml_prototype name style;
8396       pr " */\n";
8397       pr "\n";
8398
8399       let params =
8400         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8401
8402       let needs_extra_vs =
8403         match fst style with RConstOptString _ -> true | _ -> false in
8404
8405       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8406       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8407       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8408       pr "\n";
8409
8410       pr "CAMLprim value\n";
8411       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8412       List.iter (pr ", value %s") (List.tl params);
8413       pr ")\n";
8414       pr "{\n";
8415
8416       (match params with
8417        | [p1; p2; p3; p4; p5] ->
8418            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8419        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8420            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8421            pr "  CAMLxparam%d (%s);\n"
8422              (List.length rest) (String.concat ", " rest)
8423        | ps ->
8424            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8425       );
8426       if not needs_extra_vs then
8427         pr "  CAMLlocal1 (rv);\n"
8428       else
8429         pr "  CAMLlocal3 (rv, v, v2);\n";
8430       pr "\n";
8431
8432       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8433       pr "  if (g == NULL)\n";
8434       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8435       pr "\n";
8436
8437       List.iter (
8438         function
8439         | Pathname n
8440         | Device n | Dev_or_Path n
8441         | String n
8442         | FileIn n
8443         | FileOut n ->
8444             pr "  const char *%s = String_val (%sv);\n" n n
8445         | OptString n ->
8446             pr "  const char *%s =\n" n;
8447             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8448               n n
8449         | BufferIn n ->
8450             pr "  const char *%s = String_val (%sv);\n" n n;
8451             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8452         | StringList n | DeviceList n ->
8453             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8454         | Bool n ->
8455             pr "  int %s = Bool_val (%sv);\n" n n
8456         | Int n ->
8457             pr "  int %s = Int_val (%sv);\n" n n
8458         | Int64 n ->
8459             pr "  int64_t %s = Int64_val (%sv);\n" n n
8460       ) (snd style);
8461       let error_code =
8462         match fst style with
8463         | RErr -> pr "  int r;\n"; "-1"
8464         | RInt _ -> pr "  int r;\n"; "-1"
8465         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8466         | RBool _ -> pr "  int r;\n"; "-1"
8467         | RConstString _ | RConstOptString _ ->
8468             pr "  const char *r;\n"; "NULL"
8469         | RString _ -> pr "  char *r;\n"; "NULL"
8470         | RStringList _ ->
8471             pr "  int i;\n";
8472             pr "  char **r;\n";
8473             "NULL"
8474         | RStruct (_, typ) ->
8475             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8476         | RStructList (_, typ) ->
8477             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8478         | RHashtable _ ->
8479             pr "  int i;\n";
8480             pr "  char **r;\n";
8481             "NULL"
8482         | RBufferOut _ ->
8483             pr "  char *r;\n";
8484             pr "  size_t size;\n";
8485             "NULL" in
8486       pr "\n";
8487
8488       pr "  caml_enter_blocking_section ();\n";
8489       pr "  r = guestfs_%s " name;
8490       generate_c_call_args ~handle:"g" style;
8491       pr ";\n";
8492       pr "  caml_leave_blocking_section ();\n";
8493
8494       List.iter (
8495         function
8496         | StringList n | DeviceList n ->
8497             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8498         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8499         | Bool _ | Int _ | Int64 _
8500         | FileIn _ | FileOut _ | BufferIn _ -> ()
8501       ) (snd style);
8502
8503       pr "  if (r == %s)\n" error_code;
8504       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8505       pr "\n";
8506
8507       (match fst style with
8508        | RErr -> pr "  rv = Val_unit;\n"
8509        | RInt _ -> pr "  rv = Val_int (r);\n"
8510        | RInt64 _ ->
8511            pr "  rv = caml_copy_int64 (r);\n"
8512        | RBool _ -> pr "  rv = Val_bool (r);\n"
8513        | RConstString _ ->
8514            pr "  rv = caml_copy_string (r);\n"
8515        | RConstOptString _ ->
8516            pr "  if (r) { /* Some string */\n";
8517            pr "    v = caml_alloc (1, 0);\n";
8518            pr "    v2 = caml_copy_string (r);\n";
8519            pr "    Store_field (v, 0, v2);\n";
8520            pr "  } else /* None */\n";
8521            pr "    v = Val_int (0);\n";
8522        | RString _ ->
8523            pr "  rv = caml_copy_string (r);\n";
8524            pr "  free (r);\n"
8525        | RStringList _ ->
8526            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8527            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8528            pr "  free (r);\n"
8529        | RStruct (_, typ) ->
8530            pr "  rv = copy_%s (r);\n" typ;
8531            pr "  guestfs_free_%s (r);\n" typ;
8532        | RStructList (_, typ) ->
8533            pr "  rv = copy_%s_list (r);\n" typ;
8534            pr "  guestfs_free_%s_list (r);\n" typ;
8535        | RHashtable _ ->
8536            pr "  rv = copy_table (r);\n";
8537            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8538            pr "  free (r);\n";
8539        | RBufferOut _ ->
8540            pr "  rv = caml_alloc_string (size);\n";
8541            pr "  memcpy (String_val (rv), r, size);\n";
8542       );
8543
8544       pr "  CAMLreturn (rv);\n";
8545       pr "}\n";
8546       pr "\n";
8547
8548       if List.length params > 5 then (
8549         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8550         pr "CAMLprim value ";
8551         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8552         pr "CAMLprim value\n";
8553         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8554         pr "{\n";
8555         pr "  return ocaml_guestfs_%s (argv[0]" name;
8556         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8557         pr ");\n";
8558         pr "}\n";
8559         pr "\n"
8560       )
8561   ) all_functions_sorted
8562
8563 and generate_ocaml_structure_decls () =
8564   List.iter (
8565     fun (typ, cols) ->
8566       pr "type %s = {\n" typ;
8567       List.iter (
8568         function
8569         | name, FString -> pr "  %s : string;\n" name
8570         | name, FBuffer -> pr "  %s : string;\n" name
8571         | name, FUUID -> pr "  %s : string;\n" name
8572         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8573         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8574         | name, FChar -> pr "  %s : char;\n" name
8575         | name, FOptPercent -> pr "  %s : float option;\n" name
8576       ) cols;
8577       pr "}\n";
8578       pr "\n"
8579   ) structs
8580
8581 and generate_ocaml_prototype ?(is_external = false) name style =
8582   if is_external then pr "external " else pr "val ";
8583   pr "%s : t -> " name;
8584   List.iter (
8585     function
8586     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8587     | BufferIn _ -> pr "string -> "
8588     | OptString _ -> pr "string option -> "
8589     | StringList _ | DeviceList _ -> pr "string array -> "
8590     | Bool _ -> pr "bool -> "
8591     | Int _ -> pr "int -> "
8592     | Int64 _ -> pr "int64 -> "
8593   ) (snd style);
8594   (match fst style with
8595    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8596    | RInt _ -> pr "int"
8597    | RInt64 _ -> pr "int64"
8598    | RBool _ -> pr "bool"
8599    | RConstString _ -> pr "string"
8600    | RConstOptString _ -> pr "string option"
8601    | RString _ | RBufferOut _ -> pr "string"
8602    | RStringList _ -> pr "string array"
8603    | RStruct (_, typ) -> pr "%s" typ
8604    | RStructList (_, typ) -> pr "%s array" typ
8605    | RHashtable _ -> pr "(string * string) list"
8606   );
8607   if is_external then (
8608     pr " = ";
8609     if List.length (snd style) + 1 > 5 then
8610       pr "\"ocaml_guestfs_%s_byte\" " name;
8611     pr "\"ocaml_guestfs_%s\"" name
8612   );
8613   pr "\n"
8614
8615 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8616 and generate_perl_xs () =
8617   generate_header CStyle LGPLv2plus;
8618
8619   pr "\
8620 #include \"EXTERN.h\"
8621 #include \"perl.h\"
8622 #include \"XSUB.h\"
8623
8624 #include <guestfs.h>
8625
8626 #ifndef PRId64
8627 #define PRId64 \"lld\"
8628 #endif
8629
8630 static SV *
8631 my_newSVll(long long val) {
8632 #ifdef USE_64_BIT_ALL
8633   return newSViv(val);
8634 #else
8635   char buf[100];
8636   int len;
8637   len = snprintf(buf, 100, \"%%\" PRId64, val);
8638   return newSVpv(buf, len);
8639 #endif
8640 }
8641
8642 #ifndef PRIu64
8643 #define PRIu64 \"llu\"
8644 #endif
8645
8646 static SV *
8647 my_newSVull(unsigned long long val) {
8648 #ifdef USE_64_BIT_ALL
8649   return newSVuv(val);
8650 #else
8651   char buf[100];
8652   int len;
8653   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8654   return newSVpv(buf, len);
8655 #endif
8656 }
8657
8658 /* http://www.perlmonks.org/?node_id=680842 */
8659 static char **
8660 XS_unpack_charPtrPtr (SV *arg) {
8661   char **ret;
8662   AV *av;
8663   I32 i;
8664
8665   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8666     croak (\"array reference expected\");
8667
8668   av = (AV *)SvRV (arg);
8669   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8670   if (!ret)
8671     croak (\"malloc failed\");
8672
8673   for (i = 0; i <= av_len (av); i++) {
8674     SV **elem = av_fetch (av, i, 0);
8675
8676     if (!elem || !*elem)
8677       croak (\"missing element in list\");
8678
8679     ret[i] = SvPV_nolen (*elem);
8680   }
8681
8682   ret[i] = NULL;
8683
8684   return ret;
8685 }
8686
8687 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8688
8689 PROTOTYPES: ENABLE
8690
8691 guestfs_h *
8692 _create ()
8693    CODE:
8694       RETVAL = guestfs_create ();
8695       if (!RETVAL)
8696         croak (\"could not create guestfs handle\");
8697       guestfs_set_error_handler (RETVAL, NULL, NULL);
8698  OUTPUT:
8699       RETVAL
8700
8701 void
8702 DESTROY (g)
8703       guestfs_h *g;
8704  PPCODE:
8705       guestfs_close (g);
8706
8707 ";
8708
8709   List.iter (
8710     fun (name, style, _, _, _, _, _) ->
8711       (match fst style with
8712        | RErr -> pr "void\n"
8713        | RInt _ -> pr "SV *\n"
8714        | RInt64 _ -> pr "SV *\n"
8715        | RBool _ -> pr "SV *\n"
8716        | RConstString _ -> pr "SV *\n"
8717        | RConstOptString _ -> pr "SV *\n"
8718        | RString _ -> pr "SV *\n"
8719        | RBufferOut _ -> pr "SV *\n"
8720        | RStringList _
8721        | RStruct _ | RStructList _
8722        | RHashtable _ ->
8723            pr "void\n" (* all lists returned implictly on the stack *)
8724       );
8725       (* Call and arguments. *)
8726       pr "%s (g" name;
8727       List.iter (
8728         fun arg -> pr ", %s" (name_of_argt arg)
8729       ) (snd style);
8730       pr ")\n";
8731       pr "      guestfs_h *g;\n";
8732       iteri (
8733         fun i ->
8734           function
8735           | Pathname n | Device n | Dev_or_Path n | String n
8736           | FileIn n | FileOut n ->
8737               pr "      char *%s;\n" n
8738           | BufferIn n ->
8739               pr "      char *%s;\n" n;
8740               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8741           | OptString n ->
8742               (* http://www.perlmonks.org/?node_id=554277
8743                * Note that the implicit handle argument means we have
8744                * to add 1 to the ST(x) operator.
8745                *)
8746               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8747           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8748           | Bool n -> pr "      int %s;\n" n
8749           | Int n -> pr "      int %s;\n" n
8750           | Int64 n -> pr "      int64_t %s;\n" n
8751       ) (snd style);
8752
8753       let do_cleanups () =
8754         List.iter (
8755           function
8756           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8757           | Bool _ | Int _ | Int64 _
8758           | FileIn _ | FileOut _
8759           | BufferIn _ -> ()
8760           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8761         ) (snd style)
8762       in
8763
8764       (* Code. *)
8765       (match fst style with
8766        | RErr ->
8767            pr "PREINIT:\n";
8768            pr "      int r;\n";
8769            pr " PPCODE:\n";
8770            pr "      r = guestfs_%s " name;
8771            generate_c_call_args ~handle:"g" style;
8772            pr ";\n";
8773            do_cleanups ();
8774            pr "      if (r == -1)\n";
8775            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8776        | RInt n
8777        | RBool n ->
8778            pr "PREINIT:\n";
8779            pr "      int %s;\n" n;
8780            pr "   CODE:\n";
8781            pr "      %s = guestfs_%s " n name;
8782            generate_c_call_args ~handle:"g" style;
8783            pr ";\n";
8784            do_cleanups ();
8785            pr "      if (%s == -1)\n" n;
8786            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8787            pr "      RETVAL = newSViv (%s);\n" n;
8788            pr " OUTPUT:\n";
8789            pr "      RETVAL\n"
8790        | RInt64 n ->
8791            pr "PREINIT:\n";
8792            pr "      int64_t %s;\n" n;
8793            pr "   CODE:\n";
8794            pr "      %s = guestfs_%s " n name;
8795            generate_c_call_args ~handle:"g" style;
8796            pr ";\n";
8797            do_cleanups ();
8798            pr "      if (%s == -1)\n" n;
8799            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8800            pr "      RETVAL = my_newSVll (%s);\n" n;
8801            pr " OUTPUT:\n";
8802            pr "      RETVAL\n"
8803        | RConstString n ->
8804            pr "PREINIT:\n";
8805            pr "      const char *%s;\n" n;
8806            pr "   CODE:\n";
8807            pr "      %s = guestfs_%s " n name;
8808            generate_c_call_args ~handle:"g" style;
8809            pr ";\n";
8810            do_cleanups ();
8811            pr "      if (%s == NULL)\n" n;
8812            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8813            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8814            pr " OUTPUT:\n";
8815            pr "      RETVAL\n"
8816        | RConstOptString n ->
8817            pr "PREINIT:\n";
8818            pr "      const char *%s;\n" n;
8819            pr "   CODE:\n";
8820            pr "      %s = guestfs_%s " n name;
8821            generate_c_call_args ~handle:"g" style;
8822            pr ";\n";
8823            do_cleanups ();
8824            pr "      if (%s == NULL)\n" n;
8825            pr "        RETVAL = &PL_sv_undef;\n";
8826            pr "      else\n";
8827            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8828            pr " OUTPUT:\n";
8829            pr "      RETVAL\n"
8830        | RString n ->
8831            pr "PREINIT:\n";
8832            pr "      char *%s;\n" n;
8833            pr "   CODE:\n";
8834            pr "      %s = guestfs_%s " n name;
8835            generate_c_call_args ~handle:"g" style;
8836            pr ";\n";
8837            do_cleanups ();
8838            pr "      if (%s == NULL)\n" n;
8839            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8840            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8841            pr "      free (%s);\n" n;
8842            pr " OUTPUT:\n";
8843            pr "      RETVAL\n"
8844        | RStringList n | RHashtable n ->
8845            pr "PREINIT:\n";
8846            pr "      char **%s;\n" n;
8847            pr "      int i, n;\n";
8848            pr " PPCODE:\n";
8849            pr "      %s = guestfs_%s " n name;
8850            generate_c_call_args ~handle:"g" style;
8851            pr ";\n";
8852            do_cleanups ();
8853            pr "      if (%s == NULL)\n" n;
8854            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8855            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8856            pr "      EXTEND (SP, n);\n";
8857            pr "      for (i = 0; i < n; ++i) {\n";
8858            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8859            pr "        free (%s[i]);\n" n;
8860            pr "      }\n";
8861            pr "      free (%s);\n" n;
8862        | RStruct (n, typ) ->
8863            let cols = cols_of_struct typ in
8864            generate_perl_struct_code typ cols name style n do_cleanups
8865        | RStructList (n, typ) ->
8866            let cols = cols_of_struct typ in
8867            generate_perl_struct_list_code typ cols name style n do_cleanups
8868        | RBufferOut n ->
8869            pr "PREINIT:\n";
8870            pr "      char *%s;\n" n;
8871            pr "      size_t size;\n";
8872            pr "   CODE:\n";
8873            pr "      %s = guestfs_%s " n name;
8874            generate_c_call_args ~handle:"g" style;
8875            pr ";\n";
8876            do_cleanups ();
8877            pr "      if (%s == NULL)\n" n;
8878            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8879            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8880            pr "      free (%s);\n" n;
8881            pr " OUTPUT:\n";
8882            pr "      RETVAL\n"
8883       );
8884
8885       pr "\n"
8886   ) all_functions
8887
8888 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8889   pr "PREINIT:\n";
8890   pr "      struct guestfs_%s_list *%s;\n" typ n;
8891   pr "      int i;\n";
8892   pr "      HV *hv;\n";
8893   pr " PPCODE:\n";
8894   pr "      %s = guestfs_%s " n name;
8895   generate_c_call_args ~handle:"g" style;
8896   pr ";\n";
8897   do_cleanups ();
8898   pr "      if (%s == NULL)\n" n;
8899   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8900   pr "      EXTEND (SP, %s->len);\n" n;
8901   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8902   pr "        hv = newHV ();\n";
8903   List.iter (
8904     function
8905     | name, FString ->
8906         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8907           name (String.length name) n name
8908     | name, FUUID ->
8909         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8910           name (String.length name) n name
8911     | name, FBuffer ->
8912         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8913           name (String.length name) n name n name
8914     | name, (FBytes|FUInt64) ->
8915         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8916           name (String.length name) n name
8917     | name, FInt64 ->
8918         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8919           name (String.length name) n name
8920     | name, (FInt32|FUInt32) ->
8921         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8922           name (String.length name) n name
8923     | name, FChar ->
8924         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8925           name (String.length name) n name
8926     | name, FOptPercent ->
8927         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8928           name (String.length name) n name
8929   ) cols;
8930   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8931   pr "      }\n";
8932   pr "      guestfs_free_%s_list (%s);\n" typ n
8933
8934 and generate_perl_struct_code typ cols name style n do_cleanups =
8935   pr "PREINIT:\n";
8936   pr "      struct guestfs_%s *%s;\n" typ n;
8937   pr " PPCODE:\n";
8938   pr "      %s = guestfs_%s " n name;
8939   generate_c_call_args ~handle:"g" style;
8940   pr ";\n";
8941   do_cleanups ();
8942   pr "      if (%s == NULL)\n" n;
8943   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8944   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8945   List.iter (
8946     fun ((name, _) as col) ->
8947       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8948
8949       match col with
8950       | name, FString ->
8951           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8952             n name
8953       | name, FBuffer ->
8954           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8955             n name n name
8956       | name, FUUID ->
8957           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8958             n name
8959       | name, (FBytes|FUInt64) ->
8960           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8961             n name
8962       | name, FInt64 ->
8963           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8964             n name
8965       | name, (FInt32|FUInt32) ->
8966           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8967             n name
8968       | name, FChar ->
8969           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8970             n name
8971       | name, FOptPercent ->
8972           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8973             n name
8974   ) cols;
8975   pr "      free (%s);\n" n
8976
8977 (* Generate Sys/Guestfs.pm. *)
8978 and generate_perl_pm () =
8979   generate_header HashStyle LGPLv2plus;
8980
8981   pr "\
8982 =pod
8983
8984 =head1 NAME
8985
8986 Sys::Guestfs - Perl bindings for libguestfs
8987
8988 =head1 SYNOPSIS
8989
8990  use Sys::Guestfs;
8991
8992  my $h = Sys::Guestfs->new ();
8993  $h->add_drive ('guest.img');
8994  $h->launch ();
8995  $h->mount ('/dev/sda1', '/');
8996  $h->touch ('/hello');
8997  $h->sync ();
8998
8999 =head1 DESCRIPTION
9000
9001 The C<Sys::Guestfs> module provides a Perl XS binding to the
9002 libguestfs API for examining and modifying virtual machine
9003 disk images.
9004
9005 Amongst the things this is good for: making batch configuration
9006 changes to guests, getting disk used/free statistics (see also:
9007 virt-df), migrating between virtualization systems (see also:
9008 virt-p2v), performing partial backups, performing partial guest
9009 clones, cloning guests and changing registry/UUID/hostname info, and
9010 much else besides.
9011
9012 Libguestfs uses Linux kernel and qemu code, and can access any type of
9013 guest filesystem that Linux and qemu can, including but not limited
9014 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9015 schemes, qcow, qcow2, vmdk.
9016
9017 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9018 LVs, what filesystem is in each LV, etc.).  It can also run commands
9019 in the context of the guest.  Also you can access filesystems over
9020 FUSE.
9021
9022 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9023 functions for using libguestfs from Perl, including integration
9024 with libvirt.
9025
9026 =head1 ERRORS
9027
9028 All errors turn into calls to C<croak> (see L<Carp(3)>).
9029
9030 =head1 METHODS
9031
9032 =over 4
9033
9034 =cut
9035
9036 package Sys::Guestfs;
9037
9038 use strict;
9039 use warnings;
9040
9041 # This version number changes whenever a new function
9042 # is added to the libguestfs API.  It is not directly
9043 # related to the libguestfs version number.
9044 use vars qw($VERSION);
9045 $VERSION = '0.%d';
9046
9047 require XSLoader;
9048 XSLoader::load ('Sys::Guestfs');
9049
9050 =item $h = Sys::Guestfs->new ();
9051
9052 Create a new guestfs handle.
9053
9054 =cut
9055
9056 sub new {
9057   my $proto = shift;
9058   my $class = ref ($proto) || $proto;
9059
9060   my $self = Sys::Guestfs::_create ();
9061   bless $self, $class;
9062   return $self;
9063 }
9064
9065 " max_proc_nr;
9066
9067   (* Actions.  We only need to print documentation for these as
9068    * they are pulled in from the XS code automatically.
9069    *)
9070   List.iter (
9071     fun (name, style, _, flags, _, _, longdesc) ->
9072       if not (List.mem NotInDocs flags) then (
9073         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9074         pr "=item ";
9075         generate_perl_prototype name style;
9076         pr "\n\n";
9077         pr "%s\n\n" longdesc;
9078         if List.mem ProtocolLimitWarning flags then
9079           pr "%s\n\n" protocol_limit_warning;
9080         if List.mem DangerWillRobinson flags then
9081           pr "%s\n\n" danger_will_robinson;
9082         match deprecation_notice flags with
9083         | None -> ()
9084         | Some txt -> pr "%s\n\n" txt
9085       )
9086   ) all_functions_sorted;
9087
9088   (* End of file. *)
9089   pr "\
9090 =cut
9091
9092 1;
9093
9094 =back
9095
9096 =head1 COPYRIGHT
9097
9098 Copyright (C) %s Red Hat Inc.
9099
9100 =head1 LICENSE
9101
9102 Please see the file COPYING.LIB for the full license.
9103
9104 =head1 SEE ALSO
9105
9106 L<guestfs(3)>,
9107 L<guestfish(1)>,
9108 L<http://libguestfs.org>,
9109 L<Sys::Guestfs::Lib(3)>.
9110
9111 =cut
9112 " copyright_years
9113
9114 and generate_perl_prototype name style =
9115   (match fst style with
9116    | RErr -> ()
9117    | RBool n
9118    | RInt n
9119    | RInt64 n
9120    | RConstString n
9121    | RConstOptString n
9122    | RString n
9123    | RBufferOut n -> pr "$%s = " n
9124    | RStruct (n,_)
9125    | RHashtable n -> pr "%%%s = " n
9126    | RStringList n
9127    | RStructList (n,_) -> pr "@%s = " n
9128   );
9129   pr "$h->%s (" name;
9130   let comma = ref false in
9131   List.iter (
9132     fun arg ->
9133       if !comma then pr ", ";
9134       comma := true;
9135       match arg with
9136       | Pathname n | Device n | Dev_or_Path n | String n
9137       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9138       | BufferIn n ->
9139           pr "$%s" n
9140       | StringList n | DeviceList n ->
9141           pr "\\@%s" n
9142   ) (snd style);
9143   pr ");"
9144
9145 (* Generate Python C module. *)
9146 and generate_python_c () =
9147   generate_header CStyle LGPLv2plus;
9148
9149   pr "\
9150 #define PY_SSIZE_T_CLEAN 1
9151 #include <Python.h>
9152
9153 #if PY_VERSION_HEX < 0x02050000
9154 typedef int Py_ssize_t;
9155 #define PY_SSIZE_T_MAX INT_MAX
9156 #define PY_SSIZE_T_MIN INT_MIN
9157 #endif
9158
9159 #include <stdio.h>
9160 #include <stdlib.h>
9161 #include <assert.h>
9162
9163 #include \"guestfs.h\"
9164
9165 typedef struct {
9166   PyObject_HEAD
9167   guestfs_h *g;
9168 } Pyguestfs_Object;
9169
9170 static guestfs_h *
9171 get_handle (PyObject *obj)
9172 {
9173   assert (obj);
9174   assert (obj != Py_None);
9175   return ((Pyguestfs_Object *) obj)->g;
9176 }
9177
9178 static PyObject *
9179 put_handle (guestfs_h *g)
9180 {
9181   assert (g);
9182   return
9183     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9184 }
9185
9186 /* This list should be freed (but not the strings) after use. */
9187 static char **
9188 get_string_list (PyObject *obj)
9189 {
9190   int i, len;
9191   char **r;
9192
9193   assert (obj);
9194
9195   if (!PyList_Check (obj)) {
9196     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9197     return NULL;
9198   }
9199
9200   len = PyList_Size (obj);
9201   r = malloc (sizeof (char *) * (len+1));
9202   if (r == NULL) {
9203     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9204     return NULL;
9205   }
9206
9207   for (i = 0; i < len; ++i)
9208     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9209   r[len] = NULL;
9210
9211   return r;
9212 }
9213
9214 static PyObject *
9215 put_string_list (char * const * const argv)
9216 {
9217   PyObject *list;
9218   int argc, i;
9219
9220   for (argc = 0; argv[argc] != NULL; ++argc)
9221     ;
9222
9223   list = PyList_New (argc);
9224   for (i = 0; i < argc; ++i)
9225     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9226
9227   return list;
9228 }
9229
9230 static PyObject *
9231 put_table (char * const * const argv)
9232 {
9233   PyObject *list, *item;
9234   int argc, i;
9235
9236   for (argc = 0; argv[argc] != NULL; ++argc)
9237     ;
9238
9239   list = PyList_New (argc >> 1);
9240   for (i = 0; i < argc; i += 2) {
9241     item = PyTuple_New (2);
9242     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9243     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9244     PyList_SetItem (list, i >> 1, item);
9245   }
9246
9247   return list;
9248 }
9249
9250 static void
9251 free_strings (char **argv)
9252 {
9253   int argc;
9254
9255   for (argc = 0; argv[argc] != NULL; ++argc)
9256     free (argv[argc]);
9257   free (argv);
9258 }
9259
9260 static PyObject *
9261 py_guestfs_create (PyObject *self, PyObject *args)
9262 {
9263   guestfs_h *g;
9264
9265   g = guestfs_create ();
9266   if (g == NULL) {
9267     PyErr_SetString (PyExc_RuntimeError,
9268                      \"guestfs.create: failed to allocate handle\");
9269     return NULL;
9270   }
9271   guestfs_set_error_handler (g, NULL, NULL);
9272   return put_handle (g);
9273 }
9274
9275 static PyObject *
9276 py_guestfs_close (PyObject *self, PyObject *args)
9277 {
9278   PyObject *py_g;
9279   guestfs_h *g;
9280
9281   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9282     return NULL;
9283   g = get_handle (py_g);
9284
9285   guestfs_close (g);
9286
9287   Py_INCREF (Py_None);
9288   return Py_None;
9289 }
9290
9291 ";
9292
9293   let emit_put_list_function typ =
9294     pr "static PyObject *\n";
9295     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9296     pr "{\n";
9297     pr "  PyObject *list;\n";
9298     pr "  int i;\n";
9299     pr "\n";
9300     pr "  list = PyList_New (%ss->len);\n" typ;
9301     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9302     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9303     pr "  return list;\n";
9304     pr "};\n";
9305     pr "\n"
9306   in
9307
9308   (* Structures, turned into Python dictionaries. *)
9309   List.iter (
9310     fun (typ, cols) ->
9311       pr "static PyObject *\n";
9312       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9313       pr "{\n";
9314       pr "  PyObject *dict;\n";
9315       pr "\n";
9316       pr "  dict = PyDict_New ();\n";
9317       List.iter (
9318         function
9319         | name, FString ->
9320             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9321             pr "                        PyString_FromString (%s->%s));\n"
9322               typ name
9323         | name, FBuffer ->
9324             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9325             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9326               typ name typ name
9327         | name, FUUID ->
9328             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9329             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9330               typ name
9331         | name, (FBytes|FUInt64) ->
9332             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9333             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9334               typ name
9335         | name, FInt64 ->
9336             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9337             pr "                        PyLong_FromLongLong (%s->%s));\n"
9338               typ name
9339         | name, FUInt32 ->
9340             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9341             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9342               typ name
9343         | name, FInt32 ->
9344             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9345             pr "                        PyLong_FromLong (%s->%s));\n"
9346               typ name
9347         | name, FOptPercent ->
9348             pr "  if (%s->%s >= 0)\n" typ name;
9349             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9350             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9351               typ name;
9352             pr "  else {\n";
9353             pr "    Py_INCREF (Py_None);\n";
9354             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9355             pr "  }\n"
9356         | name, FChar ->
9357             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9358             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9359       ) cols;
9360       pr "  return dict;\n";
9361       pr "};\n";
9362       pr "\n";
9363
9364   ) structs;
9365
9366   (* Emit a put_TYPE_list function definition only if that function is used. *)
9367   List.iter (
9368     function
9369     | typ, (RStructListOnly | RStructAndList) ->
9370         (* generate the function for typ *)
9371         emit_put_list_function typ
9372     | typ, _ -> () (* empty *)
9373   ) (rstructs_used_by all_functions);
9374
9375   (* Python wrapper functions. *)
9376   List.iter (
9377     fun (name, style, _, _, _, _, _) ->
9378       pr "static PyObject *\n";
9379       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9380       pr "{\n";
9381
9382       pr "  PyObject *py_g;\n";
9383       pr "  guestfs_h *g;\n";
9384       pr "  PyObject *py_r;\n";
9385
9386       let error_code =
9387         match fst style with
9388         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9389         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9390         | RConstString _ | RConstOptString _ ->
9391             pr "  const char *r;\n"; "NULL"
9392         | RString _ -> pr "  char *r;\n"; "NULL"
9393         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9394         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9395         | RStructList (_, typ) ->
9396             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9397         | RBufferOut _ ->
9398             pr "  char *r;\n";
9399             pr "  size_t size;\n";
9400             "NULL" in
9401
9402       List.iter (
9403         function
9404         | Pathname n | Device n | Dev_or_Path n | String n
9405         | FileIn n | FileOut n ->
9406             pr "  const char *%s;\n" n
9407         | OptString n -> pr "  const char *%s;\n" n
9408         | BufferIn n ->
9409             pr "  const char *%s;\n" n;
9410             pr "  Py_ssize_t %s_size;\n" n
9411         | StringList n | DeviceList n ->
9412             pr "  PyObject *py_%s;\n" n;
9413             pr "  char **%s;\n" n
9414         | Bool n -> pr "  int %s;\n" n
9415         | Int n -> pr "  int %s;\n" n
9416         | Int64 n -> pr "  long long %s;\n" n
9417       ) (snd style);
9418
9419       pr "\n";
9420
9421       (* Convert the parameters. *)
9422       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9423       List.iter (
9424         function
9425         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9426         | OptString _ -> pr "z"
9427         | StringList _ | DeviceList _ -> pr "O"
9428         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9429         | Int _ -> pr "i"
9430         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9431                              * emulate C's int/long/long long in Python?
9432                              *)
9433         | BufferIn _ -> pr "s#"
9434       ) (snd style);
9435       pr ":guestfs_%s\",\n" name;
9436       pr "                         &py_g";
9437       List.iter (
9438         function
9439         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9440         | OptString n -> pr ", &%s" n
9441         | StringList n | DeviceList n -> pr ", &py_%s" n
9442         | Bool n -> pr ", &%s" n
9443         | Int n -> pr ", &%s" n
9444         | Int64 n -> pr ", &%s" n
9445         | BufferIn n -> pr ", &%s, &%s_size" n n
9446       ) (snd style);
9447
9448       pr "))\n";
9449       pr "    return NULL;\n";
9450
9451       pr "  g = get_handle (py_g);\n";
9452       List.iter (
9453         function
9454         | Pathname _ | Device _ | Dev_or_Path _ | String _
9455         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9456         | BufferIn _ -> ()
9457         | StringList n | DeviceList n ->
9458             pr "  %s = get_string_list (py_%s);\n" n n;
9459             pr "  if (!%s) return NULL;\n" n
9460       ) (snd style);
9461
9462       pr "\n";
9463
9464       pr "  r = guestfs_%s " name;
9465       generate_c_call_args ~handle:"g" style;
9466       pr ";\n";
9467
9468       List.iter (
9469         function
9470         | Pathname _ | Device _ | Dev_or_Path _ | String _
9471         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9472         | BufferIn _ -> ()
9473         | StringList n | DeviceList n ->
9474             pr "  free (%s);\n" n
9475       ) (snd style);
9476
9477       pr "  if (r == %s) {\n" error_code;
9478       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9479       pr "    return NULL;\n";
9480       pr "  }\n";
9481       pr "\n";
9482
9483       (match fst style with
9484        | RErr ->
9485            pr "  Py_INCREF (Py_None);\n";
9486            pr "  py_r = Py_None;\n"
9487        | RInt _
9488        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9489        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9490        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9491        | RConstOptString _ ->
9492            pr "  if (r)\n";
9493            pr "    py_r = PyString_FromString (r);\n";
9494            pr "  else {\n";
9495            pr "    Py_INCREF (Py_None);\n";
9496            pr "    py_r = Py_None;\n";
9497            pr "  }\n"
9498        | RString _ ->
9499            pr "  py_r = PyString_FromString (r);\n";
9500            pr "  free (r);\n"
9501        | RStringList _ ->
9502            pr "  py_r = put_string_list (r);\n";
9503            pr "  free_strings (r);\n"
9504        | RStruct (_, typ) ->
9505            pr "  py_r = put_%s (r);\n" typ;
9506            pr "  guestfs_free_%s (r);\n" typ
9507        | RStructList (_, typ) ->
9508            pr "  py_r = put_%s_list (r);\n" typ;
9509            pr "  guestfs_free_%s_list (r);\n" typ
9510        | RHashtable n ->
9511            pr "  py_r = put_table (r);\n";
9512            pr "  free_strings (r);\n"
9513        | RBufferOut _ ->
9514            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9515            pr "  free (r);\n"
9516       );
9517
9518       pr "  return py_r;\n";
9519       pr "}\n";
9520       pr "\n"
9521   ) all_functions;
9522
9523   (* Table of functions. *)
9524   pr "static PyMethodDef methods[] = {\n";
9525   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9526   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9527   List.iter (
9528     fun (name, _, _, _, _, _, _) ->
9529       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9530         name name
9531   ) all_functions;
9532   pr "  { NULL, NULL, 0, NULL }\n";
9533   pr "};\n";
9534   pr "\n";
9535
9536   (* Init function. *)
9537   pr "\
9538 void
9539 initlibguestfsmod (void)
9540 {
9541   static int initialized = 0;
9542
9543   if (initialized) return;
9544   Py_InitModule ((char *) \"libguestfsmod\", methods);
9545   initialized = 1;
9546 }
9547 "
9548
9549 (* Generate Python module. *)
9550 and generate_python_py () =
9551   generate_header HashStyle LGPLv2plus;
9552
9553   pr "\
9554 u\"\"\"Python bindings for libguestfs
9555
9556 import guestfs
9557 g = guestfs.GuestFS ()
9558 g.add_drive (\"guest.img\")
9559 g.launch ()
9560 parts = g.list_partitions ()
9561
9562 The guestfs module provides a Python binding to the libguestfs API
9563 for examining and modifying virtual machine disk images.
9564
9565 Amongst the things this is good for: making batch configuration
9566 changes to guests, getting disk used/free statistics (see also:
9567 virt-df), migrating between virtualization systems (see also:
9568 virt-p2v), performing partial backups, performing partial guest
9569 clones, cloning guests and changing registry/UUID/hostname info, and
9570 much else besides.
9571
9572 Libguestfs uses Linux kernel and qemu code, and can access any type of
9573 guest filesystem that Linux and qemu can, including but not limited
9574 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9575 schemes, qcow, qcow2, vmdk.
9576
9577 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9578 LVs, what filesystem is in each LV, etc.).  It can also run commands
9579 in the context of the guest.  Also you can access filesystems over
9580 FUSE.
9581
9582 Errors which happen while using the API are turned into Python
9583 RuntimeError exceptions.
9584
9585 To create a guestfs handle you usually have to perform the following
9586 sequence of calls:
9587
9588 # Create the handle, call add_drive at least once, and possibly
9589 # several times if the guest has multiple block devices:
9590 g = guestfs.GuestFS ()
9591 g.add_drive (\"guest.img\")
9592
9593 # Launch the qemu subprocess and wait for it to become ready:
9594 g.launch ()
9595
9596 # Now you can issue commands, for example:
9597 logvols = g.lvs ()
9598
9599 \"\"\"
9600
9601 import libguestfsmod
9602
9603 class GuestFS:
9604     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9605
9606     def __init__ (self):
9607         \"\"\"Create a new libguestfs handle.\"\"\"
9608         self._o = libguestfsmod.create ()
9609
9610     def __del__ (self):
9611         libguestfsmod.close (self._o)
9612
9613 ";
9614
9615   List.iter (
9616     fun (name, style, _, flags, _, _, longdesc) ->
9617       pr "    def %s " name;
9618       generate_py_call_args ~handle:"self" (snd style);
9619       pr ":\n";
9620
9621       if not (List.mem NotInDocs flags) then (
9622         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9623         let doc =
9624           match fst style with
9625           | RErr | RInt _ | RInt64 _ | RBool _
9626           | RConstOptString _ | RConstString _
9627           | RString _ | RBufferOut _ -> doc
9628           | RStringList _ ->
9629               doc ^ "\n\nThis function returns a list of strings."
9630           | RStruct (_, typ) ->
9631               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9632           | RStructList (_, typ) ->
9633               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9634           | RHashtable _ ->
9635               doc ^ "\n\nThis function returns a dictionary." in
9636         let doc =
9637           if List.mem ProtocolLimitWarning flags then
9638             doc ^ "\n\n" ^ protocol_limit_warning
9639           else doc in
9640         let doc =
9641           if List.mem DangerWillRobinson flags then
9642             doc ^ "\n\n" ^ danger_will_robinson
9643           else doc in
9644         let doc =
9645           match deprecation_notice flags with
9646           | None -> doc
9647           | Some txt -> doc ^ "\n\n" ^ txt in
9648         let doc = pod2text ~width:60 name doc in
9649         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9650         let doc = String.concat "\n        " doc in
9651         pr "        u\"\"\"%s\"\"\"\n" doc;
9652       );
9653       pr "        return libguestfsmod.%s " name;
9654       generate_py_call_args ~handle:"self._o" (snd style);
9655       pr "\n";
9656       pr "\n";
9657   ) all_functions
9658
9659 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9660 and generate_py_call_args ~handle args =
9661   pr "(%s" handle;
9662   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9663   pr ")"
9664
9665 (* Useful if you need the longdesc POD text as plain text.  Returns a
9666  * list of lines.
9667  *
9668  * Because this is very slow (the slowest part of autogeneration),
9669  * we memoize the results.
9670  *)
9671 and pod2text ~width name longdesc =
9672   let key = width, name, longdesc in
9673   try Hashtbl.find pod2text_memo key
9674   with Not_found ->
9675     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9676     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9677     close_out chan;
9678     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9679     let chan = open_process_in cmd in
9680     let lines = ref [] in
9681     let rec loop i =
9682       let line = input_line chan in
9683       if i = 1 then             (* discard the first line of output *)
9684         loop (i+1)
9685       else (
9686         let line = triml line in
9687         lines := line :: !lines;
9688         loop (i+1)
9689       ) in
9690     let lines = try loop 1 with End_of_file -> List.rev !lines in
9691     unlink filename;
9692     (match close_process_in chan with
9693      | WEXITED 0 -> ()
9694      | WEXITED i ->
9695          failwithf "pod2text: process exited with non-zero status (%d)" i
9696      | WSIGNALED i | WSTOPPED i ->
9697          failwithf "pod2text: process signalled or stopped by signal %d" i
9698     );
9699     Hashtbl.add pod2text_memo key lines;
9700     pod2text_memo_updated ();
9701     lines
9702
9703 (* Generate ruby bindings. *)
9704 and generate_ruby_c () =
9705   generate_header CStyle LGPLv2plus;
9706
9707   pr "\
9708 #include <stdio.h>
9709 #include <stdlib.h>
9710
9711 #include <ruby.h>
9712
9713 #include \"guestfs.h\"
9714
9715 #include \"extconf.h\"
9716
9717 /* For Ruby < 1.9 */
9718 #ifndef RARRAY_LEN
9719 #define RARRAY_LEN(r) (RARRAY((r))->len)
9720 #endif
9721
9722 static VALUE m_guestfs;                 /* guestfs module */
9723 static VALUE c_guestfs;                 /* guestfs_h handle */
9724 static VALUE e_Error;                   /* used for all errors */
9725
9726 static void ruby_guestfs_free (void *p)
9727 {
9728   if (!p) return;
9729   guestfs_close ((guestfs_h *) p);
9730 }
9731
9732 static VALUE ruby_guestfs_create (VALUE m)
9733 {
9734   guestfs_h *g;
9735
9736   g = guestfs_create ();
9737   if (!g)
9738     rb_raise (e_Error, \"failed to create guestfs handle\");
9739
9740   /* Don't print error messages to stderr by default. */
9741   guestfs_set_error_handler (g, NULL, NULL);
9742
9743   /* Wrap it, and make sure the close function is called when the
9744    * handle goes away.
9745    */
9746   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9747 }
9748
9749 static VALUE ruby_guestfs_close (VALUE gv)
9750 {
9751   guestfs_h *g;
9752   Data_Get_Struct (gv, guestfs_h, g);
9753
9754   ruby_guestfs_free (g);
9755   DATA_PTR (gv) = NULL;
9756
9757   return Qnil;
9758 }
9759
9760 ";
9761
9762   List.iter (
9763     fun (name, style, _, _, _, _, _) ->
9764       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9765       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9766       pr ")\n";
9767       pr "{\n";
9768       pr "  guestfs_h *g;\n";
9769       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9770       pr "  if (!g)\n";
9771       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9772         name;
9773       pr "\n";
9774
9775       List.iter (
9776         function
9777         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9778             pr "  Check_Type (%sv, T_STRING);\n" n;
9779             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9780             pr "  if (!%s)\n" n;
9781             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9782             pr "              \"%s\", \"%s\");\n" n name
9783         | BufferIn n ->
9784             pr "  Check_Type (%sv, T_STRING);\n" n;
9785             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9786             pr "  if (!%s)\n" n;
9787             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9788             pr "              \"%s\", \"%s\");\n" n name;
9789             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9790         | OptString n ->
9791             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9792         | StringList n | DeviceList n ->
9793             pr "  char **%s;\n" n;
9794             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9795             pr "  {\n";
9796             pr "    int i, len;\n";
9797             pr "    len = RARRAY_LEN (%sv);\n" n;
9798             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9799               n;
9800             pr "    for (i = 0; i < len; ++i) {\n";
9801             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9802             pr "      %s[i] = StringValueCStr (v);\n" n;
9803             pr "    }\n";
9804             pr "    %s[len] = NULL;\n" n;
9805             pr "  }\n";
9806         | Bool n ->
9807             pr "  int %s = RTEST (%sv);\n" n n
9808         | Int n ->
9809             pr "  int %s = NUM2INT (%sv);\n" n n
9810         | Int64 n ->
9811             pr "  long long %s = NUM2LL (%sv);\n" n n
9812       ) (snd style);
9813       pr "\n";
9814
9815       let error_code =
9816         match fst style with
9817         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9818         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9819         | RConstString _ | RConstOptString _ ->
9820             pr "  const char *r;\n"; "NULL"
9821         | RString _ -> pr "  char *r;\n"; "NULL"
9822         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9823         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9824         | RStructList (_, typ) ->
9825             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9826         | RBufferOut _ ->
9827             pr "  char *r;\n";
9828             pr "  size_t size;\n";
9829             "NULL" in
9830       pr "\n";
9831
9832       pr "  r = guestfs_%s " name;
9833       generate_c_call_args ~handle:"g" style;
9834       pr ";\n";
9835
9836       List.iter (
9837         function
9838         | Pathname _ | Device _ | Dev_or_Path _ | String _
9839         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9840         | BufferIn _ -> ()
9841         | StringList n | DeviceList n ->
9842             pr "  free (%s);\n" n
9843       ) (snd style);
9844
9845       pr "  if (r == %s)\n" error_code;
9846       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9847       pr "\n";
9848
9849       (match fst style with
9850        | RErr ->
9851            pr "  return Qnil;\n"
9852        | RInt _ | RBool _ ->
9853            pr "  return INT2NUM (r);\n"
9854        | RInt64 _ ->
9855            pr "  return ULL2NUM (r);\n"
9856        | RConstString _ ->
9857            pr "  return rb_str_new2 (r);\n";
9858        | RConstOptString _ ->
9859            pr "  if (r)\n";
9860            pr "    return rb_str_new2 (r);\n";
9861            pr "  else\n";
9862            pr "    return Qnil;\n";
9863        | RString _ ->
9864            pr "  VALUE rv = rb_str_new2 (r);\n";
9865            pr "  free (r);\n";
9866            pr "  return rv;\n";
9867        | RStringList _ ->
9868            pr "  int i, len = 0;\n";
9869            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9870            pr "  VALUE rv = rb_ary_new2 (len);\n";
9871            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9872            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9873            pr "    free (r[i]);\n";
9874            pr "  }\n";
9875            pr "  free (r);\n";
9876            pr "  return rv;\n"
9877        | RStruct (_, typ) ->
9878            let cols = cols_of_struct typ in
9879            generate_ruby_struct_code typ cols
9880        | RStructList (_, typ) ->
9881            let cols = cols_of_struct typ in
9882            generate_ruby_struct_list_code typ cols
9883        | RHashtable _ ->
9884            pr "  VALUE rv = rb_hash_new ();\n";
9885            pr "  int i;\n";
9886            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9887            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9888            pr "    free (r[i]);\n";
9889            pr "    free (r[i+1]);\n";
9890            pr "  }\n";
9891            pr "  free (r);\n";
9892            pr "  return rv;\n"
9893        | RBufferOut _ ->
9894            pr "  VALUE rv = rb_str_new (r, size);\n";
9895            pr "  free (r);\n";
9896            pr "  return rv;\n";
9897       );
9898
9899       pr "}\n";
9900       pr "\n"
9901   ) all_functions;
9902
9903   pr "\
9904 /* Initialize the module. */
9905 void Init__guestfs ()
9906 {
9907   m_guestfs = rb_define_module (\"Guestfs\");
9908   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9909   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9910
9911   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9912   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9913
9914 ";
9915   (* Define the rest of the methods. *)
9916   List.iter (
9917     fun (name, style, _, _, _, _, _) ->
9918       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9919       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9920   ) all_functions;
9921
9922   pr "}\n"
9923
9924 (* Ruby code to return a struct. *)
9925 and generate_ruby_struct_code typ cols =
9926   pr "  VALUE rv = rb_hash_new ();\n";
9927   List.iter (
9928     function
9929     | name, FString ->
9930         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9931     | name, FBuffer ->
9932         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9933     | name, FUUID ->
9934         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9935     | name, (FBytes|FUInt64) ->
9936         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9937     | name, FInt64 ->
9938         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9939     | name, FUInt32 ->
9940         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9941     | name, FInt32 ->
9942         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9943     | name, FOptPercent ->
9944         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9945     | name, FChar -> (* XXX wrong? *)
9946         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9947   ) cols;
9948   pr "  guestfs_free_%s (r);\n" typ;
9949   pr "  return rv;\n"
9950
9951 (* Ruby code to return a struct list. *)
9952 and generate_ruby_struct_list_code typ cols =
9953   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9954   pr "  int i;\n";
9955   pr "  for (i = 0; i < r->len; ++i) {\n";
9956   pr "    VALUE hv = rb_hash_new ();\n";
9957   List.iter (
9958     function
9959     | name, FString ->
9960         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9961     | name, FBuffer ->
9962         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
9963     | name, FUUID ->
9964         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9965     | name, (FBytes|FUInt64) ->
9966         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9967     | name, FInt64 ->
9968         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9969     | name, FUInt32 ->
9970         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9971     | name, FInt32 ->
9972         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9973     | name, FOptPercent ->
9974         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9975     | name, FChar -> (* XXX wrong? *)
9976         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9977   ) cols;
9978   pr "    rb_ary_push (rv, hv);\n";
9979   pr "  }\n";
9980   pr "  guestfs_free_%s_list (r);\n" typ;
9981   pr "  return rv;\n"
9982
9983 (* Generate Java bindings GuestFS.java file. *)
9984 and generate_java_java () =
9985   generate_header CStyle LGPLv2plus;
9986
9987   pr "\
9988 package com.redhat.et.libguestfs;
9989
9990 import java.util.HashMap;
9991 import com.redhat.et.libguestfs.LibGuestFSException;
9992 import com.redhat.et.libguestfs.PV;
9993 import com.redhat.et.libguestfs.VG;
9994 import com.redhat.et.libguestfs.LV;
9995 import com.redhat.et.libguestfs.Stat;
9996 import com.redhat.et.libguestfs.StatVFS;
9997 import com.redhat.et.libguestfs.IntBool;
9998 import com.redhat.et.libguestfs.Dirent;
9999
10000 /**
10001  * The GuestFS object is a libguestfs handle.
10002  *
10003  * @author rjones
10004  */
10005 public class GuestFS {
10006   // Load the native code.
10007   static {
10008     System.loadLibrary (\"guestfs_jni\");
10009   }
10010
10011   /**
10012    * The native guestfs_h pointer.
10013    */
10014   long g;
10015
10016   /**
10017    * Create a libguestfs handle.
10018    *
10019    * @throws LibGuestFSException
10020    */
10021   public GuestFS () throws LibGuestFSException
10022   {
10023     g = _create ();
10024   }
10025   private native long _create () throws LibGuestFSException;
10026
10027   /**
10028    * Close a libguestfs handle.
10029    *
10030    * You can also leave handles to be collected by the garbage
10031    * collector, but this method ensures that the resources used
10032    * by the handle are freed up immediately.  If you call any
10033    * other methods after closing the handle, you will get an
10034    * exception.
10035    *
10036    * @throws LibGuestFSException
10037    */
10038   public void close () throws LibGuestFSException
10039   {
10040     if (g != 0)
10041       _close (g);
10042     g = 0;
10043   }
10044   private native void _close (long g) throws LibGuestFSException;
10045
10046   public void finalize () throws LibGuestFSException
10047   {
10048     close ();
10049   }
10050
10051 ";
10052
10053   List.iter (
10054     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10055       if not (List.mem NotInDocs flags); then (
10056         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10057         let doc =
10058           if List.mem ProtocolLimitWarning flags then
10059             doc ^ "\n\n" ^ protocol_limit_warning
10060           else doc in
10061         let doc =
10062           if List.mem DangerWillRobinson flags then
10063             doc ^ "\n\n" ^ danger_will_robinson
10064           else doc in
10065         let doc =
10066           match deprecation_notice flags with
10067           | None -> doc
10068           | Some txt -> doc ^ "\n\n" ^ txt in
10069         let doc = pod2text ~width:60 name doc in
10070         let doc = List.map (            (* RHBZ#501883 *)
10071           function
10072           | "" -> "<p>"
10073           | nonempty -> nonempty
10074         ) doc in
10075         let doc = String.concat "\n   * " doc in
10076
10077         pr "  /**\n";
10078         pr "   * %s\n" shortdesc;
10079         pr "   * <p>\n";
10080         pr "   * %s\n" doc;
10081         pr "   * @throws LibGuestFSException\n";
10082         pr "   */\n";
10083         pr "  ";
10084       );
10085       generate_java_prototype ~public:true ~semicolon:false name style;
10086       pr "\n";
10087       pr "  {\n";
10088       pr "    if (g == 0)\n";
10089       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10090         name;
10091       pr "    ";
10092       if fst style <> RErr then pr "return ";
10093       pr "_%s " name;
10094       generate_java_call_args ~handle:"g" (snd style);
10095       pr ";\n";
10096       pr "  }\n";
10097       pr "  ";
10098       generate_java_prototype ~privat:true ~native:true name style;
10099       pr "\n";
10100       pr "\n";
10101   ) all_functions;
10102
10103   pr "}\n"
10104
10105 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10106 and generate_java_call_args ~handle args =
10107   pr "(%s" handle;
10108   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10109   pr ")"
10110
10111 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10112     ?(semicolon=true) name style =
10113   if privat then pr "private ";
10114   if public then pr "public ";
10115   if native then pr "native ";
10116
10117   (* return type *)
10118   (match fst style with
10119    | RErr -> pr "void ";
10120    | RInt _ -> pr "int ";
10121    | RInt64 _ -> pr "long ";
10122    | RBool _ -> pr "boolean ";
10123    | RConstString _ | RConstOptString _ | RString _
10124    | RBufferOut _ -> pr "String ";
10125    | RStringList _ -> pr "String[] ";
10126    | RStruct (_, typ) ->
10127        let name = java_name_of_struct typ in
10128        pr "%s " name;
10129    | RStructList (_, typ) ->
10130        let name = java_name_of_struct typ in
10131        pr "%s[] " name;
10132    | RHashtable _ -> pr "HashMap<String,String> ";
10133   );
10134
10135   if native then pr "_%s " name else pr "%s " name;
10136   pr "(";
10137   let needs_comma = ref false in
10138   if native then (
10139     pr "long g";
10140     needs_comma := true
10141   );
10142
10143   (* args *)
10144   List.iter (
10145     fun arg ->
10146       if !needs_comma then pr ", ";
10147       needs_comma := true;
10148
10149       match arg with
10150       | Pathname n
10151       | Device n | Dev_or_Path n
10152       | String n
10153       | OptString n
10154       | FileIn n
10155       | FileOut n ->
10156           pr "String %s" n
10157       | BufferIn n ->
10158           pr "byte[] %s" n
10159       | StringList n | DeviceList n ->
10160           pr "String[] %s" n
10161       | Bool n ->
10162           pr "boolean %s" n
10163       | Int n ->
10164           pr "int %s" n
10165       | Int64 n ->
10166           pr "long %s" n
10167   ) (snd style);
10168
10169   pr ")\n";
10170   pr "    throws LibGuestFSException";
10171   if semicolon then pr ";"
10172
10173 and generate_java_struct jtyp cols () =
10174   generate_header CStyle LGPLv2plus;
10175
10176   pr "\
10177 package com.redhat.et.libguestfs;
10178
10179 /**
10180  * Libguestfs %s structure.
10181  *
10182  * @author rjones
10183  * @see GuestFS
10184  */
10185 public class %s {
10186 " jtyp jtyp;
10187
10188   List.iter (
10189     function
10190     | name, FString
10191     | name, FUUID
10192     | name, FBuffer -> pr "  public String %s;\n" name
10193     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10194     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10195     | name, FChar -> pr "  public char %s;\n" name
10196     | name, FOptPercent ->
10197         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10198         pr "  public float %s;\n" name
10199   ) cols;
10200
10201   pr "}\n"
10202
10203 and generate_java_c () =
10204   generate_header CStyle LGPLv2plus;
10205
10206   pr "\
10207 #include <stdio.h>
10208 #include <stdlib.h>
10209 #include <string.h>
10210
10211 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10212 #include \"guestfs.h\"
10213
10214 /* Note that this function returns.  The exception is not thrown
10215  * until after the wrapper function returns.
10216  */
10217 static void
10218 throw_exception (JNIEnv *env, const char *msg)
10219 {
10220   jclass cl;
10221   cl = (*env)->FindClass (env,
10222                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10223   (*env)->ThrowNew (env, cl, msg);
10224 }
10225
10226 JNIEXPORT jlong JNICALL
10227 Java_com_redhat_et_libguestfs_GuestFS__1create
10228   (JNIEnv *env, jobject obj)
10229 {
10230   guestfs_h *g;
10231
10232   g = guestfs_create ();
10233   if (g == NULL) {
10234     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10235     return 0;
10236   }
10237   guestfs_set_error_handler (g, NULL, NULL);
10238   return (jlong) (long) g;
10239 }
10240
10241 JNIEXPORT void JNICALL
10242 Java_com_redhat_et_libguestfs_GuestFS__1close
10243   (JNIEnv *env, jobject obj, jlong jg)
10244 {
10245   guestfs_h *g = (guestfs_h *) (long) jg;
10246   guestfs_close (g);
10247 }
10248
10249 ";
10250
10251   List.iter (
10252     fun (name, style, _, _, _, _, _) ->
10253       pr "JNIEXPORT ";
10254       (match fst style with
10255        | RErr -> pr "void ";
10256        | RInt _ -> pr "jint ";
10257        | RInt64 _ -> pr "jlong ";
10258        | RBool _ -> pr "jboolean ";
10259        | RConstString _ | RConstOptString _ | RString _
10260        | RBufferOut _ -> pr "jstring ";
10261        | RStruct _ | RHashtable _ ->
10262            pr "jobject ";
10263        | RStringList _ | RStructList _ ->
10264            pr "jobjectArray ";
10265       );
10266       pr "JNICALL\n";
10267       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10268       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10269       pr "\n";
10270       pr "  (JNIEnv *env, jobject obj, jlong jg";
10271       List.iter (
10272         function
10273         | Pathname n
10274         | Device n | Dev_or_Path n
10275         | String n
10276         | OptString n
10277         | FileIn n
10278         | FileOut n ->
10279             pr ", jstring j%s" n
10280         | BufferIn n ->
10281             pr ", jbyteArray j%s" n
10282         | StringList n | DeviceList n ->
10283             pr ", jobjectArray j%s" n
10284         | Bool n ->
10285             pr ", jboolean j%s" n
10286         | Int n ->
10287             pr ", jint j%s" n
10288         | Int64 n ->
10289             pr ", jlong j%s" n
10290       ) (snd style);
10291       pr ")\n";
10292       pr "{\n";
10293       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10294       let error_code, no_ret =
10295         match fst style with
10296         | RErr -> pr "  int r;\n"; "-1", ""
10297         | RBool _
10298         | RInt _ -> pr "  int r;\n"; "-1", "0"
10299         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10300         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10301         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10302         | RString _ ->
10303             pr "  jstring jr;\n";
10304             pr "  char *r;\n"; "NULL", "NULL"
10305         | RStringList _ ->
10306             pr "  jobjectArray jr;\n";
10307             pr "  int r_len;\n";
10308             pr "  jclass cl;\n";
10309             pr "  jstring jstr;\n";
10310             pr "  char **r;\n"; "NULL", "NULL"
10311         | RStruct (_, typ) ->
10312             pr "  jobject jr;\n";
10313             pr "  jclass cl;\n";
10314             pr "  jfieldID fl;\n";
10315             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10316         | RStructList (_, typ) ->
10317             pr "  jobjectArray jr;\n";
10318             pr "  jclass cl;\n";
10319             pr "  jfieldID fl;\n";
10320             pr "  jobject jfl;\n";
10321             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10322         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10323         | RBufferOut _ ->
10324             pr "  jstring jr;\n";
10325             pr "  char *r;\n";
10326             pr "  size_t size;\n";
10327             "NULL", "NULL" in
10328       List.iter (
10329         function
10330         | Pathname n
10331         | Device n | Dev_or_Path n
10332         | String n
10333         | OptString n
10334         | FileIn n
10335         | FileOut n ->
10336             pr "  const char *%s;\n" n
10337         | BufferIn n ->
10338             pr "  jbyte *%s;\n" n;
10339             pr "  size_t %s_size;\n" n
10340         | StringList n | DeviceList n ->
10341             pr "  int %s_len;\n" n;
10342             pr "  const char **%s;\n" n
10343         | Bool n
10344         | Int n ->
10345             pr "  int %s;\n" n
10346         | Int64 n ->
10347             pr "  int64_t %s;\n" n
10348       ) (snd style);
10349
10350       let needs_i =
10351         (match fst style with
10352          | RStringList _ | RStructList _ -> true
10353          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10354          | RConstOptString _
10355          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10356           List.exists (function
10357                        | StringList _ -> true
10358                        | DeviceList _ -> true
10359                        | _ -> false) (snd style) in
10360       if needs_i then
10361         pr "  int i;\n";
10362
10363       pr "\n";
10364
10365       (* Get the parameters. *)
10366       List.iter (
10367         function
10368         | Pathname n
10369         | Device n | Dev_or_Path n
10370         | String n
10371         | FileIn n
10372         | FileOut n ->
10373             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10374         | OptString n ->
10375             (* This is completely undocumented, but Java null becomes
10376              * a NULL parameter.
10377              *)
10378             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10379         | BufferIn n ->
10380             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10381             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10382         | StringList n | DeviceList n ->
10383             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10384             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10385             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10386             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10387               n;
10388             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10389             pr "  }\n";
10390             pr "  %s[%s_len] = NULL;\n" n n;
10391         | Bool n
10392         | Int n
10393         | Int64 n ->
10394             pr "  %s = j%s;\n" n n
10395       ) (snd style);
10396
10397       (* Make the call. *)
10398       pr "  r = guestfs_%s " name;
10399       generate_c_call_args ~handle:"g" style;
10400       pr ";\n";
10401
10402       (* Release the parameters. *)
10403       List.iter (
10404         function
10405         | Pathname n
10406         | Device n | Dev_or_Path n
10407         | String n
10408         | FileIn n
10409         | FileOut n ->
10410             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10411         | OptString n ->
10412             pr "  if (j%s)\n" n;
10413             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10414         | BufferIn n ->
10415             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10416         | StringList n | DeviceList n ->
10417             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10418             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10419               n;
10420             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10421             pr "  }\n";
10422             pr "  free (%s);\n" n
10423         | Bool n
10424         | Int n
10425         | Int64 n -> ()
10426       ) (snd style);
10427
10428       (* Check for errors. *)
10429       pr "  if (r == %s) {\n" error_code;
10430       pr "    throw_exception (env, guestfs_last_error (g));\n";
10431       pr "    return %s;\n" no_ret;
10432       pr "  }\n";
10433
10434       (* Return value. *)
10435       (match fst style with
10436        | RErr -> ()
10437        | RInt _ -> pr "  return (jint) r;\n"
10438        | RBool _ -> pr "  return (jboolean) r;\n"
10439        | RInt64 _ -> pr "  return (jlong) r;\n"
10440        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10441        | RConstOptString _ ->
10442            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10443        | RString _ ->
10444            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10445            pr "  free (r);\n";
10446            pr "  return jr;\n"
10447        | RStringList _ ->
10448            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10449            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10450            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10451            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10452            pr "  for (i = 0; i < r_len; ++i) {\n";
10453            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10454            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10455            pr "    free (r[i]);\n";
10456            pr "  }\n";
10457            pr "  free (r);\n";
10458            pr "  return jr;\n"
10459        | RStruct (_, typ) ->
10460            let jtyp = java_name_of_struct typ in
10461            let cols = cols_of_struct typ in
10462            generate_java_struct_return typ jtyp cols
10463        | RStructList (_, typ) ->
10464            let jtyp = java_name_of_struct typ in
10465            let cols = cols_of_struct typ in
10466            generate_java_struct_list_return typ jtyp cols
10467        | RHashtable _ ->
10468            (* XXX *)
10469            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10470            pr "  return NULL;\n"
10471        | RBufferOut _ ->
10472            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10473            pr "  free (r);\n";
10474            pr "  return jr;\n"
10475       );
10476
10477       pr "}\n";
10478       pr "\n"
10479   ) all_functions
10480
10481 and generate_java_struct_return typ jtyp cols =
10482   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10483   pr "  jr = (*env)->AllocObject (env, cl);\n";
10484   List.iter (
10485     function
10486     | name, FString ->
10487         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10488         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10489     | name, FUUID ->
10490         pr "  {\n";
10491         pr "    char s[33];\n";
10492         pr "    memcpy (s, r->%s, 32);\n" name;
10493         pr "    s[32] = 0;\n";
10494         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10495         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10496         pr "  }\n";
10497     | name, FBuffer ->
10498         pr "  {\n";
10499         pr "    int len = r->%s_len;\n" name;
10500         pr "    char s[len+1];\n";
10501         pr "    memcpy (s, r->%s, len);\n" name;
10502         pr "    s[len] = 0;\n";
10503         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10504         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10505         pr "  }\n";
10506     | name, (FBytes|FUInt64|FInt64) ->
10507         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10508         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10509     | name, (FUInt32|FInt32) ->
10510         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10511         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10512     | name, FOptPercent ->
10513         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10514         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10515     | name, FChar ->
10516         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10517         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10518   ) cols;
10519   pr "  free (r);\n";
10520   pr "  return jr;\n"
10521
10522 and generate_java_struct_list_return typ jtyp cols =
10523   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10524   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10525   pr "  for (i = 0; i < r->len; ++i) {\n";
10526   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10527   List.iter (
10528     function
10529     | name, FString ->
10530         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10531         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10532     | name, FUUID ->
10533         pr "    {\n";
10534         pr "      char s[33];\n";
10535         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10536         pr "      s[32] = 0;\n";
10537         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10538         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10539         pr "    }\n";
10540     | name, FBuffer ->
10541         pr "    {\n";
10542         pr "      int len = r->val[i].%s_len;\n" name;
10543         pr "      char s[len+1];\n";
10544         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10545         pr "      s[len] = 0;\n";
10546         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10547         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10548         pr "    }\n";
10549     | name, (FBytes|FUInt64|FInt64) ->
10550         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10551         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10552     | name, (FUInt32|FInt32) ->
10553         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10554         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10555     | name, FOptPercent ->
10556         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10557         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10558     | name, FChar ->
10559         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10560         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10561   ) cols;
10562   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10563   pr "  }\n";
10564   pr "  guestfs_free_%s_list (r);\n" typ;
10565   pr "  return jr;\n"
10566
10567 and generate_java_makefile_inc () =
10568   generate_header HashStyle GPLv2plus;
10569
10570   pr "java_built_sources = \\\n";
10571   List.iter (
10572     fun (typ, jtyp) ->
10573         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10574   ) java_structs;
10575   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10576
10577 and generate_haskell_hs () =
10578   generate_header HaskellStyle LGPLv2plus;
10579
10580   (* XXX We only know how to generate partial FFI for Haskell
10581    * at the moment.  Please help out!
10582    *)
10583   let can_generate style =
10584     match style with
10585     | RErr, _
10586     | RInt _, _
10587     | RInt64 _, _ -> true
10588     | RBool _, _
10589     | RConstString _, _
10590     | RConstOptString _, _
10591     | RString _, _
10592     | RStringList _, _
10593     | RStruct _, _
10594     | RStructList _, _
10595     | RHashtable _, _
10596     | RBufferOut _, _ -> false in
10597
10598   pr "\
10599 {-# INCLUDE <guestfs.h> #-}
10600 {-# LANGUAGE ForeignFunctionInterface #-}
10601
10602 module Guestfs (
10603   create";
10604
10605   (* List out the names of the actions we want to export. *)
10606   List.iter (
10607     fun (name, style, _, _, _, _, _) ->
10608       if can_generate style then pr ",\n  %s" name
10609   ) all_functions;
10610
10611   pr "
10612   ) where
10613
10614 -- Unfortunately some symbols duplicate ones already present
10615 -- in Prelude.  We don't know which, so we hard-code a list
10616 -- here.
10617 import Prelude hiding (truncate)
10618
10619 import Foreign
10620 import Foreign.C
10621 import Foreign.C.Types
10622 import IO
10623 import Control.Exception
10624 import Data.Typeable
10625
10626 data GuestfsS = GuestfsS            -- represents the opaque C struct
10627 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10628 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10629
10630 -- XXX define properly later XXX
10631 data PV = PV
10632 data VG = VG
10633 data LV = LV
10634 data IntBool = IntBool
10635 data Stat = Stat
10636 data StatVFS = StatVFS
10637 data Hashtable = Hashtable
10638
10639 foreign import ccall unsafe \"guestfs_create\" c_create
10640   :: IO GuestfsP
10641 foreign import ccall unsafe \"&guestfs_close\" c_close
10642   :: FunPtr (GuestfsP -> IO ())
10643 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10644   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10645
10646 create :: IO GuestfsH
10647 create = do
10648   p <- c_create
10649   c_set_error_handler p nullPtr nullPtr
10650   h <- newForeignPtr c_close p
10651   return h
10652
10653 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10654   :: GuestfsP -> IO CString
10655
10656 -- last_error :: GuestfsH -> IO (Maybe String)
10657 -- last_error h = do
10658 --   str <- withForeignPtr h (\\p -> c_last_error p)
10659 --   maybePeek peekCString str
10660
10661 last_error :: GuestfsH -> IO (String)
10662 last_error h = do
10663   str <- withForeignPtr h (\\p -> c_last_error p)
10664   if (str == nullPtr)
10665     then return \"no error\"
10666     else peekCString str
10667
10668 ";
10669
10670   (* Generate wrappers for each foreign function. *)
10671   List.iter (
10672     fun (name, style, _, _, _, _, _) ->
10673       if can_generate style then (
10674         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10675         pr "  :: ";
10676         generate_haskell_prototype ~handle:"GuestfsP" style;
10677         pr "\n";
10678         pr "\n";
10679         pr "%s :: " name;
10680         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10681         pr "\n";
10682         pr "%s %s = do\n" name
10683           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10684         pr "  r <- ";
10685         (* Convert pointer arguments using with* functions. *)
10686         List.iter (
10687           function
10688           | FileIn n
10689           | FileOut n
10690           | Pathname n | Device n | Dev_or_Path n | String n ->
10691               pr "withCString %s $ \\%s -> " n n
10692           | BufferIn n ->
10693               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10694           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10695           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10696           | Bool _ | Int _ | Int64 _ -> ()
10697         ) (snd style);
10698         (* Convert integer arguments. *)
10699         let args =
10700           List.map (
10701             function
10702             | Bool n -> sprintf "(fromBool %s)" n
10703             | Int n -> sprintf "(fromIntegral %s)" n
10704             | Int64 n -> sprintf "(fromIntegral %s)" n
10705             | FileIn n | FileOut n
10706             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10707             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10708           ) (snd style) in
10709         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10710           (String.concat " " ("p" :: args));
10711         (match fst style with
10712          | RErr | RInt _ | RInt64 _ | RBool _ ->
10713              pr "  if (r == -1)\n";
10714              pr "    then do\n";
10715              pr "      err <- last_error h\n";
10716              pr "      fail err\n";
10717          | RConstString _ | RConstOptString _ | RString _
10718          | RStringList _ | RStruct _
10719          | RStructList _ | RHashtable _ | RBufferOut _ ->
10720              pr "  if (r == nullPtr)\n";
10721              pr "    then do\n";
10722              pr "      err <- last_error h\n";
10723              pr "      fail err\n";
10724         );
10725         (match fst style with
10726          | RErr ->
10727              pr "    else return ()\n"
10728          | RInt _ ->
10729              pr "    else return (fromIntegral r)\n"
10730          | RInt64 _ ->
10731              pr "    else return (fromIntegral r)\n"
10732          | RBool _ ->
10733              pr "    else return (toBool r)\n"
10734          | RConstString _
10735          | RConstOptString _
10736          | RString _
10737          | RStringList _
10738          | RStruct _
10739          | RStructList _
10740          | RHashtable _
10741          | RBufferOut _ ->
10742              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10743         );
10744         pr "\n";
10745       )
10746   ) all_functions
10747
10748 and generate_haskell_prototype ~handle ?(hs = false) style =
10749   pr "%s -> " handle;
10750   let string = if hs then "String" else "CString" in
10751   let int = if hs then "Int" else "CInt" in
10752   let bool = if hs then "Bool" else "CInt" in
10753   let int64 = if hs then "Integer" else "Int64" in
10754   List.iter (
10755     fun arg ->
10756       (match arg with
10757        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10758        | BufferIn _ ->
10759            if hs then pr "String"
10760            else pr "CString -> CInt"
10761        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10762        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10763        | Bool _ -> pr "%s" bool
10764        | Int _ -> pr "%s" int
10765        | Int64 _ -> pr "%s" int
10766        | FileIn _ -> pr "%s" string
10767        | FileOut _ -> pr "%s" string
10768       );
10769       pr " -> ";
10770   ) (snd style);
10771   pr "IO (";
10772   (match fst style with
10773    | RErr -> if not hs then pr "CInt"
10774    | RInt _ -> pr "%s" int
10775    | RInt64 _ -> pr "%s" int64
10776    | RBool _ -> pr "%s" bool
10777    | RConstString _ -> pr "%s" string
10778    | RConstOptString _ -> pr "Maybe %s" string
10779    | RString _ -> pr "%s" string
10780    | RStringList _ -> pr "[%s]" string
10781    | RStruct (_, typ) ->
10782        let name = java_name_of_struct typ in
10783        pr "%s" name
10784    | RStructList (_, typ) ->
10785        let name = java_name_of_struct typ in
10786        pr "[%s]" name
10787    | RHashtable _ -> pr "Hashtable"
10788    | RBufferOut _ -> pr "%s" string
10789   );
10790   pr ")"
10791
10792 and generate_csharp () =
10793   generate_header CPlusPlusStyle LGPLv2plus;
10794
10795   (* XXX Make this configurable by the C# assembly users. *)
10796   let library = "libguestfs.so.0" in
10797
10798   pr "\
10799 // These C# bindings are highly experimental at present.
10800 //
10801 // Firstly they only work on Linux (ie. Mono).  In order to get them
10802 // to work on Windows (ie. .Net) you would need to port the library
10803 // itself to Windows first.
10804 //
10805 // The second issue is that some calls are known to be incorrect and
10806 // can cause Mono to segfault.  Particularly: calls which pass or
10807 // return string[], or return any structure value.  This is because
10808 // we haven't worked out the correct way to do this from C#.
10809 //
10810 // The third issue is that when compiling you get a lot of warnings.
10811 // We are not sure whether the warnings are important or not.
10812 //
10813 // Fourthly we do not routinely build or test these bindings as part
10814 // of the make && make check cycle, which means that regressions might
10815 // go unnoticed.
10816 //
10817 // Suggestions and patches are welcome.
10818
10819 // To compile:
10820 //
10821 // gmcs Libguestfs.cs
10822 // mono Libguestfs.exe
10823 //
10824 // (You'll probably want to add a Test class / static main function
10825 // otherwise this won't do anything useful).
10826
10827 using System;
10828 using System.IO;
10829 using System.Runtime.InteropServices;
10830 using System.Runtime.Serialization;
10831 using System.Collections;
10832
10833 namespace Guestfs
10834 {
10835   class Error : System.ApplicationException
10836   {
10837     public Error (string message) : base (message) {}
10838     protected Error (SerializationInfo info, StreamingContext context) {}
10839   }
10840
10841   class Guestfs
10842   {
10843     IntPtr _handle;
10844
10845     [DllImport (\"%s\")]
10846     static extern IntPtr guestfs_create ();
10847
10848     public Guestfs ()
10849     {
10850       _handle = guestfs_create ();
10851       if (_handle == IntPtr.Zero)
10852         throw new Error (\"could not create guestfs handle\");
10853     }
10854
10855     [DllImport (\"%s\")]
10856     static extern void guestfs_close (IntPtr h);
10857
10858     ~Guestfs ()
10859     {
10860       guestfs_close (_handle);
10861     }
10862
10863     [DllImport (\"%s\")]
10864     static extern string guestfs_last_error (IntPtr h);
10865
10866 " library library library;
10867
10868   (* Generate C# structure bindings.  We prefix struct names with
10869    * underscore because C# cannot have conflicting struct names and
10870    * method names (eg. "class stat" and "stat").
10871    *)
10872   List.iter (
10873     fun (typ, cols) ->
10874       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10875       pr "    public class _%s {\n" typ;
10876       List.iter (
10877         function
10878         | name, FChar -> pr "      char %s;\n" name
10879         | name, FString -> pr "      string %s;\n" name
10880         | name, FBuffer ->
10881             pr "      uint %s_len;\n" name;
10882             pr "      string %s;\n" name
10883         | name, FUUID ->
10884             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10885             pr "      string %s;\n" name
10886         | name, FUInt32 -> pr "      uint %s;\n" name
10887         | name, FInt32 -> pr "      int %s;\n" name
10888         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10889         | name, FInt64 -> pr "      long %s;\n" name
10890         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10891       ) cols;
10892       pr "    }\n";
10893       pr "\n"
10894   ) structs;
10895
10896   (* Generate C# function bindings. *)
10897   List.iter (
10898     fun (name, style, _, _, _, shortdesc, _) ->
10899       let rec csharp_return_type () =
10900         match fst style with
10901         | RErr -> "void"
10902         | RBool n -> "bool"
10903         | RInt n -> "int"
10904         | RInt64 n -> "long"
10905         | RConstString n
10906         | RConstOptString n
10907         | RString n
10908         | RBufferOut n -> "string"
10909         | RStruct (_,n) -> "_" ^ n
10910         | RHashtable n -> "Hashtable"
10911         | RStringList n -> "string[]"
10912         | RStructList (_,n) -> sprintf "_%s[]" n
10913
10914       and c_return_type () =
10915         match fst style with
10916         | RErr
10917         | RBool _
10918         | RInt _ -> "int"
10919         | RInt64 _ -> "long"
10920         | RConstString _
10921         | RConstOptString _
10922         | RString _
10923         | RBufferOut _ -> "string"
10924         | RStruct (_,n) -> "_" ^ n
10925         | RHashtable _
10926         | RStringList _ -> "string[]"
10927         | RStructList (_,n) -> sprintf "_%s[]" n
10928
10929       and c_error_comparison () =
10930         match fst style with
10931         | RErr
10932         | RBool _
10933         | RInt _
10934         | RInt64 _ -> "== -1"
10935         | RConstString _
10936         | RConstOptString _
10937         | RString _
10938         | RBufferOut _
10939         | RStruct (_,_)
10940         | RHashtable _
10941         | RStringList _
10942         | RStructList (_,_) -> "== null"
10943
10944       and generate_extern_prototype () =
10945         pr "    static extern %s guestfs_%s (IntPtr h"
10946           (c_return_type ()) name;
10947         List.iter (
10948           function
10949           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10950           | FileIn n | FileOut n
10951           | BufferIn n ->
10952               pr ", [In] string %s" n
10953           | StringList n | DeviceList n ->
10954               pr ", [In] string[] %s" n
10955           | Bool n ->
10956               pr ", bool %s" n
10957           | Int n ->
10958               pr ", int %s" n
10959           | Int64 n ->
10960               pr ", long %s" n
10961         ) (snd style);
10962         pr ");\n"
10963
10964       and generate_public_prototype () =
10965         pr "    public %s %s (" (csharp_return_type ()) name;
10966         let comma = ref false in
10967         let next () =
10968           if !comma then pr ", ";
10969           comma := true
10970         in
10971         List.iter (
10972           function
10973           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10974           | FileIn n | FileOut n
10975           | BufferIn n ->
10976               next (); pr "string %s" n
10977           | StringList n | DeviceList n ->
10978               next (); pr "string[] %s" n
10979           | Bool n ->
10980               next (); pr "bool %s" n
10981           | Int n ->
10982               next (); pr "int %s" n
10983           | Int64 n ->
10984               next (); pr "long %s" n
10985         ) (snd style);
10986         pr ")\n"
10987
10988       and generate_call () =
10989         pr "guestfs_%s (_handle" name;
10990         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10991         pr ");\n";
10992       in
10993
10994       pr "    [DllImport (\"%s\")]\n" library;
10995       generate_extern_prototype ();
10996       pr "\n";
10997       pr "    /// <summary>\n";
10998       pr "    /// %s\n" shortdesc;
10999       pr "    /// </summary>\n";
11000       generate_public_prototype ();
11001       pr "    {\n";
11002       pr "      %s r;\n" (c_return_type ());
11003       pr "      r = ";
11004       generate_call ();
11005       pr "      if (r %s)\n" (c_error_comparison ());
11006       pr "        throw new Error (guestfs_last_error (_handle));\n";
11007       (match fst style with
11008        | RErr -> ()
11009        | RBool _ ->
11010            pr "      return r != 0 ? true : false;\n"
11011        | RHashtable _ ->
11012            pr "      Hashtable rr = new Hashtable ();\n";
11013            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11014            pr "        rr.Add (r[i], r[i+1]);\n";
11015            pr "      return rr;\n"
11016        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11017        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11018        | RStructList _ ->
11019            pr "      return r;\n"
11020       );
11021       pr "    }\n";
11022       pr "\n";
11023   ) all_functions_sorted;
11024
11025   pr "  }
11026 }
11027 "
11028
11029 and generate_bindtests () =
11030   generate_header CStyle LGPLv2plus;
11031
11032   pr "\
11033 #include <stdio.h>
11034 #include <stdlib.h>
11035 #include <inttypes.h>
11036 #include <string.h>
11037
11038 #include \"guestfs.h\"
11039 #include \"guestfs-internal.h\"
11040 #include \"guestfs-internal-actions.h\"
11041 #include \"guestfs_protocol.h\"
11042
11043 #define error guestfs_error
11044 #define safe_calloc guestfs_safe_calloc
11045 #define safe_malloc guestfs_safe_malloc
11046
11047 static void
11048 print_strings (char *const *argv)
11049 {
11050   int argc;
11051
11052   printf (\"[\");
11053   for (argc = 0; argv[argc] != NULL; ++argc) {
11054     if (argc > 0) printf (\", \");
11055     printf (\"\\\"%%s\\\"\", argv[argc]);
11056   }
11057   printf (\"]\\n\");
11058 }
11059
11060 /* The test0 function prints its parameters to stdout. */
11061 ";
11062
11063   let test0, tests =
11064     match test_functions with
11065     | [] -> assert false
11066     | test0 :: tests -> test0, tests in
11067
11068   let () =
11069     let (name, style, _, _, _, _, _) = test0 in
11070     generate_prototype ~extern:false ~semicolon:false ~newline:true
11071       ~handle:"g" ~prefix:"guestfs__" name style;
11072     pr "{\n";
11073     List.iter (
11074       function
11075       | Pathname n
11076       | Device n | Dev_or_Path n
11077       | String n
11078       | FileIn n
11079       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11080       | BufferIn n ->
11081           pr "  {\n";
11082           pr "    size_t i;\n";
11083           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11084           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11085           pr "    printf (\"\\n\");\n";
11086           pr "  }\n";
11087       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11088       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11089       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11090       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11091       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11092     ) (snd style);
11093     pr "  /* Java changes stdout line buffering so we need this: */\n";
11094     pr "  fflush (stdout);\n";
11095     pr "  return 0;\n";
11096     pr "}\n";
11097     pr "\n" in
11098
11099   List.iter (
11100     fun (name, style, _, _, _, _, _) ->
11101       if String.sub name (String.length name - 3) 3 <> "err" then (
11102         pr "/* Test normal return. */\n";
11103         generate_prototype ~extern:false ~semicolon:false ~newline:true
11104           ~handle:"g" ~prefix:"guestfs__" name style;
11105         pr "{\n";
11106         (match fst style with
11107          | RErr ->
11108              pr "  return 0;\n"
11109          | RInt _ ->
11110              pr "  int r;\n";
11111              pr "  sscanf (val, \"%%d\", &r);\n";
11112              pr "  return r;\n"
11113          | RInt64 _ ->
11114              pr "  int64_t r;\n";
11115              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11116              pr "  return r;\n"
11117          | RBool _ ->
11118              pr "  return STREQ (val, \"true\");\n"
11119          | RConstString _
11120          | RConstOptString _ ->
11121              (* Can't return the input string here.  Return a static
11122               * string so we ensure we get a segfault if the caller
11123               * tries to free it.
11124               *)
11125              pr "  return \"static string\";\n"
11126          | RString _ ->
11127              pr "  return strdup (val);\n"
11128          | RStringList _ ->
11129              pr "  char **strs;\n";
11130              pr "  int n, i;\n";
11131              pr "  sscanf (val, \"%%d\", &n);\n";
11132              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11133              pr "  for (i = 0; i < n; ++i) {\n";
11134              pr "    strs[i] = safe_malloc (g, 16);\n";
11135              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11136              pr "  }\n";
11137              pr "  strs[n] = NULL;\n";
11138              pr "  return strs;\n"
11139          | RStruct (_, typ) ->
11140              pr "  struct guestfs_%s *r;\n" typ;
11141              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11142              pr "  return r;\n"
11143          | RStructList (_, typ) ->
11144              pr "  struct guestfs_%s_list *r;\n" typ;
11145              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11146              pr "  sscanf (val, \"%%d\", &r->len);\n";
11147              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11148              pr "  return r;\n"
11149          | RHashtable _ ->
11150              pr "  char **strs;\n";
11151              pr "  int n, i;\n";
11152              pr "  sscanf (val, \"%%d\", &n);\n";
11153              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11154              pr "  for (i = 0; i < n; ++i) {\n";
11155              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11156              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11157              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11158              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11159              pr "  }\n";
11160              pr "  strs[n*2] = NULL;\n";
11161              pr "  return strs;\n"
11162          | RBufferOut _ ->
11163              pr "  return strdup (val);\n"
11164         );
11165         pr "}\n";
11166         pr "\n"
11167       ) else (
11168         pr "/* Test error return. */\n";
11169         generate_prototype ~extern:false ~semicolon:false ~newline:true
11170           ~handle:"g" ~prefix:"guestfs__" name style;
11171         pr "{\n";
11172         pr "  error (g, \"error\");\n";
11173         (match fst style with
11174          | RErr | RInt _ | RInt64 _ | RBool _ ->
11175              pr "  return -1;\n"
11176          | RConstString _ | RConstOptString _
11177          | RString _ | RStringList _ | RStruct _
11178          | RStructList _
11179          | RHashtable _
11180          | RBufferOut _ ->
11181              pr "  return NULL;\n"
11182         );
11183         pr "}\n";
11184         pr "\n"
11185       )
11186   ) tests
11187
11188 and generate_ocaml_bindtests () =
11189   generate_header OCamlStyle GPLv2plus;
11190
11191   pr "\
11192 let () =
11193   let g = Guestfs.create () in
11194 ";
11195
11196   let mkargs args =
11197     String.concat " " (
11198       List.map (
11199         function
11200         | CallString s -> "\"" ^ s ^ "\""
11201         | CallOptString None -> "None"
11202         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11203         | CallStringList xs ->
11204             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11205         | CallInt i when i >= 0 -> string_of_int i
11206         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11207         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11208         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11209         | CallBool b -> string_of_bool b
11210         | CallBuffer s -> sprintf "%S" s
11211       ) args
11212     )
11213   in
11214
11215   generate_lang_bindtests (
11216     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11217   );
11218
11219   pr "print_endline \"EOF\"\n"
11220
11221 and generate_perl_bindtests () =
11222   pr "#!/usr/bin/perl -w\n";
11223   generate_header HashStyle GPLv2plus;
11224
11225   pr "\
11226 use strict;
11227
11228 use Sys::Guestfs;
11229
11230 my $g = Sys::Guestfs->new ();
11231 ";
11232
11233   let mkargs args =
11234     String.concat ", " (
11235       List.map (
11236         function
11237         | CallString s -> "\"" ^ s ^ "\""
11238         | CallOptString None -> "undef"
11239         | CallOptString (Some s) -> sprintf "\"%s\"" s
11240         | CallStringList xs ->
11241             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11242         | CallInt i -> string_of_int i
11243         | CallInt64 i -> Int64.to_string i
11244         | CallBool b -> if b then "1" else "0"
11245         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11246       ) args
11247     )
11248   in
11249
11250   generate_lang_bindtests (
11251     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11252   );
11253
11254   pr "print \"EOF\\n\"\n"
11255
11256 and generate_python_bindtests () =
11257   generate_header HashStyle GPLv2plus;
11258
11259   pr "\
11260 import guestfs
11261
11262 g = guestfs.GuestFS ()
11263 ";
11264
11265   let mkargs args =
11266     String.concat ", " (
11267       List.map (
11268         function
11269         | CallString s -> "\"" ^ s ^ "\""
11270         | CallOptString None -> "None"
11271         | CallOptString (Some s) -> sprintf "\"%s\"" s
11272         | CallStringList xs ->
11273             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11274         | CallInt i -> string_of_int i
11275         | CallInt64 i -> Int64.to_string i
11276         | CallBool b -> if b then "1" else "0"
11277         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11278       ) args
11279     )
11280   in
11281
11282   generate_lang_bindtests (
11283     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11284   );
11285
11286   pr "print \"EOF\"\n"
11287
11288 and generate_ruby_bindtests () =
11289   generate_header HashStyle GPLv2plus;
11290
11291   pr "\
11292 require 'guestfs'
11293
11294 g = Guestfs::create()
11295 ";
11296
11297   let mkargs args =
11298     String.concat ", " (
11299       List.map (
11300         function
11301         | CallString s -> "\"" ^ s ^ "\""
11302         | CallOptString None -> "nil"
11303         | CallOptString (Some s) -> sprintf "\"%s\"" s
11304         | CallStringList xs ->
11305             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11306         | CallInt i -> string_of_int i
11307         | CallInt64 i -> Int64.to_string i
11308         | CallBool b -> string_of_bool b
11309         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11310       ) args
11311     )
11312   in
11313
11314   generate_lang_bindtests (
11315     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11316   );
11317
11318   pr "print \"EOF\\n\"\n"
11319
11320 and generate_java_bindtests () =
11321   generate_header CStyle GPLv2plus;
11322
11323   pr "\
11324 import com.redhat.et.libguestfs.*;
11325
11326 public class Bindtests {
11327     public static void main (String[] argv)
11328     {
11329         try {
11330             GuestFS g = new GuestFS ();
11331 ";
11332
11333   let mkargs args =
11334     String.concat ", " (
11335       List.map (
11336         function
11337         | CallString s -> "\"" ^ s ^ "\""
11338         | CallOptString None -> "null"
11339         | CallOptString (Some s) -> sprintf "\"%s\"" s
11340         | CallStringList xs ->
11341             "new String[]{" ^
11342               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11343         | CallInt i -> string_of_int i
11344         | CallInt64 i -> Int64.to_string i
11345         | CallBool b -> string_of_bool b
11346         | CallBuffer s ->
11347             "new byte[] { " ^ String.concat "," (
11348               map_chars (fun c -> string_of_int (Char.code c)) s
11349             ) ^ " }"
11350       ) args
11351     )
11352   in
11353
11354   generate_lang_bindtests (
11355     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11356   );
11357
11358   pr "
11359             System.out.println (\"EOF\");
11360         }
11361         catch (Exception exn) {
11362             System.err.println (exn);
11363             System.exit (1);
11364         }
11365     }
11366 }
11367 "
11368
11369 and generate_haskell_bindtests () =
11370   generate_header HaskellStyle GPLv2plus;
11371
11372   pr "\
11373 module Bindtests where
11374 import qualified Guestfs
11375
11376 main = do
11377   g <- Guestfs.create
11378 ";
11379
11380   let mkargs args =
11381     String.concat " " (
11382       List.map (
11383         function
11384         | CallString s -> "\"" ^ s ^ "\""
11385         | CallOptString None -> "Nothing"
11386         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11387         | CallStringList xs ->
11388             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11389         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11390         | CallInt i -> string_of_int i
11391         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11392         | CallInt64 i -> Int64.to_string i
11393         | CallBool true -> "True"
11394         | CallBool false -> "False"
11395         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11396       ) args
11397     )
11398   in
11399
11400   generate_lang_bindtests (
11401     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11402   );
11403
11404   pr "  putStrLn \"EOF\"\n"
11405
11406 (* Language-independent bindings tests - we do it this way to
11407  * ensure there is parity in testing bindings across all languages.
11408  *)
11409 and generate_lang_bindtests call =
11410   call "test0" [CallString "abc"; CallOptString (Some "def");
11411                 CallStringList []; CallBool false;
11412                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11413                 CallBuffer "abc\000abc"];
11414   call "test0" [CallString "abc"; CallOptString None;
11415                 CallStringList []; CallBool false;
11416                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11417                 CallBuffer "abc\000abc"];
11418   call "test0" [CallString ""; CallOptString (Some "def");
11419                 CallStringList []; CallBool false;
11420                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11421                 CallBuffer "abc\000abc"];
11422   call "test0" [CallString ""; CallOptString (Some "");
11423                 CallStringList []; CallBool false;
11424                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11425                 CallBuffer "abc\000abc"];
11426   call "test0" [CallString "abc"; CallOptString (Some "def");
11427                 CallStringList ["1"]; CallBool false;
11428                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11429                 CallBuffer "abc\000abc"];
11430   call "test0" [CallString "abc"; CallOptString (Some "def");
11431                 CallStringList ["1"; "2"]; CallBool false;
11432                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11433                 CallBuffer "abc\000abc"];
11434   call "test0" [CallString "abc"; CallOptString (Some "def");
11435                 CallStringList ["1"]; CallBool true;
11436                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11437                 CallBuffer "abc\000abc"];
11438   call "test0" [CallString "abc"; CallOptString (Some "def");
11439                 CallStringList ["1"]; CallBool false;
11440                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11441                 CallBuffer "abc\000abc"];
11442   call "test0" [CallString "abc"; CallOptString (Some "def");
11443                 CallStringList ["1"]; CallBool false;
11444                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11445                 CallBuffer "abc\000abc"];
11446   call "test0" [CallString "abc"; CallOptString (Some "def");
11447                 CallStringList ["1"]; CallBool false;
11448                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11449                 CallBuffer "abc\000abc"];
11450   call "test0" [CallString "abc"; CallOptString (Some "def");
11451                 CallStringList ["1"]; CallBool false;
11452                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11453                 CallBuffer "abc\000abc"];
11454   call "test0" [CallString "abc"; CallOptString (Some "def");
11455                 CallStringList ["1"]; CallBool false;
11456                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11457                 CallBuffer "abc\000abc"];
11458   call "test0" [CallString "abc"; CallOptString (Some "def");
11459                 CallStringList ["1"]; CallBool false;
11460                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11461                 CallBuffer "abc\000abc"]
11462
11463 (* XXX Add here tests of the return and error functions. *)
11464
11465 (* Code to generator bindings for virt-inspector.  Currently only
11466  * implemented for OCaml code (for virt-p2v 2.0).
11467  *)
11468 let rng_input = "inspector/virt-inspector.rng"
11469
11470 (* Read the input file and parse it into internal structures.  This is
11471  * by no means a complete RELAX NG parser, but is just enough to be
11472  * able to parse the specific input file.
11473  *)
11474 type rng =
11475   | Element of string * rng list        (* <element name=name/> *)
11476   | Attribute of string * rng list        (* <attribute name=name/> *)
11477   | Interleave of rng list                (* <interleave/> *)
11478   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11479   | OneOrMore of rng                        (* <oneOrMore/> *)
11480   | Optional of rng                        (* <optional/> *)
11481   | Choice of string list                (* <choice><value/>*</choice> *)
11482   | Value of string                        (* <value>str</value> *)
11483   | Text                                (* <text/> *)
11484
11485 let rec string_of_rng = function
11486   | Element (name, xs) ->
11487       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11488   | Attribute (name, xs) ->
11489       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11490   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11491   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11492   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11493   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11494   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11495   | Value value -> "Value \"" ^ value ^ "\""
11496   | Text -> "Text"
11497
11498 and string_of_rng_list xs =
11499   String.concat ", " (List.map string_of_rng xs)
11500
11501 let rec parse_rng ?defines context = function
11502   | [] -> []
11503   | Xml.Element ("element", ["name", name], children) :: rest ->
11504       Element (name, parse_rng ?defines context children)
11505       :: parse_rng ?defines context rest
11506   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11507       Attribute (name, parse_rng ?defines context children)
11508       :: parse_rng ?defines context rest
11509   | Xml.Element ("interleave", [], children) :: rest ->
11510       Interleave (parse_rng ?defines context children)
11511       :: parse_rng ?defines context rest
11512   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11513       let rng = parse_rng ?defines context [child] in
11514       (match rng with
11515        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11516        | _ ->
11517            failwithf "%s: <zeroOrMore> contains more than one child element"
11518              context
11519       )
11520   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11521       let rng = parse_rng ?defines context [child] in
11522       (match rng with
11523        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11524        | _ ->
11525            failwithf "%s: <oneOrMore> contains more than one child element"
11526              context
11527       )
11528   | Xml.Element ("optional", [], [child]) :: rest ->
11529       let rng = parse_rng ?defines context [child] in
11530       (match rng with
11531        | [child] -> Optional child :: parse_rng ?defines context rest
11532        | _ ->
11533            failwithf "%s: <optional> contains more than one child element"
11534              context
11535       )
11536   | Xml.Element ("choice", [], children) :: rest ->
11537       let values = List.map (
11538         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11539         | _ ->
11540             failwithf "%s: can't handle anything except <value> in <choice>"
11541               context
11542       ) children in
11543       Choice values
11544       :: parse_rng ?defines context rest
11545   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11546       Value value :: parse_rng ?defines context rest
11547   | Xml.Element ("text", [], []) :: rest ->
11548       Text :: parse_rng ?defines context rest
11549   | Xml.Element ("ref", ["name", name], []) :: rest ->
11550       (* Look up the reference.  Because of limitations in this parser,
11551        * we can't handle arbitrarily nested <ref> yet.  You can only
11552        * use <ref> from inside <start>.
11553        *)
11554       (match defines with
11555        | None ->
11556            failwithf "%s: contains <ref>, but no refs are defined yet" context
11557        | Some map ->
11558            let rng = StringMap.find name map in
11559            rng @ parse_rng ?defines context rest
11560       )
11561   | x :: _ ->
11562       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11563
11564 let grammar =
11565   let xml = Xml.parse_file rng_input in
11566   match xml with
11567   | Xml.Element ("grammar", _,
11568                  Xml.Element ("start", _, gram) :: defines) ->
11569       (* The <define/> elements are referenced in the <start> section,
11570        * so build a map of those first.
11571        *)
11572       let defines = List.fold_left (
11573         fun map ->
11574           function Xml.Element ("define", ["name", name], defn) ->
11575             StringMap.add name defn map
11576           | _ ->
11577               failwithf "%s: expected <define name=name/>" rng_input
11578       ) StringMap.empty defines in
11579       let defines = StringMap.mapi parse_rng defines in
11580
11581       (* Parse the <start> clause, passing the defines. *)
11582       parse_rng ~defines "<start>" gram
11583   | _ ->
11584       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11585         rng_input
11586
11587 let name_of_field = function
11588   | Element (name, _) | Attribute (name, _)
11589   | ZeroOrMore (Element (name, _))
11590   | OneOrMore (Element (name, _))
11591   | Optional (Element (name, _)) -> name
11592   | Optional (Attribute (name, _)) -> name
11593   | Text -> (* an unnamed field in an element *)
11594       "data"
11595   | rng ->
11596       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11597
11598 (* At the moment this function only generates OCaml types.  However we
11599  * should parameterize it later so it can generate types/structs in a
11600  * variety of languages.
11601  *)
11602 let generate_types xs =
11603   (* A simple type is one that can be printed out directly, eg.
11604    * "string option".  A complex type is one which has a name and has
11605    * to be defined via another toplevel definition, eg. a struct.
11606    *
11607    * generate_type generates code for either simple or complex types.
11608    * In the simple case, it returns the string ("string option").  In
11609    * the complex case, it returns the name ("mountpoint").  In the
11610    * complex case it has to print out the definition before returning,
11611    * so it should only be called when we are at the beginning of a
11612    * new line (BOL context).
11613    *)
11614   let rec generate_type = function
11615     | Text ->                                (* string *)
11616         "string", true
11617     | Choice values ->                        (* [`val1|`val2|...] *)
11618         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11619     | ZeroOrMore rng ->                        (* <rng> list *)
11620         let t, is_simple = generate_type rng in
11621         t ^ " list (* 0 or more *)", is_simple
11622     | OneOrMore rng ->                        (* <rng> list *)
11623         let t, is_simple = generate_type rng in
11624         t ^ " list (* 1 or more *)", is_simple
11625                                         (* virt-inspector hack: bool *)
11626     | Optional (Attribute (name, [Value "1"])) ->
11627         "bool", true
11628     | Optional rng ->                        (* <rng> list *)
11629         let t, is_simple = generate_type rng in
11630         t ^ " option", is_simple
11631                                         (* type name = { fields ... } *)
11632     | Element (name, fields) when is_attrs_interleave fields ->
11633         generate_type_struct name (get_attrs_interleave fields)
11634     | Element (name, [field])                (* type name = field *)
11635     | Attribute (name, [field]) ->
11636         let t, is_simple = generate_type field in
11637         if is_simple then (t, true)
11638         else (
11639           pr "type %s = %s\n" name t;
11640           name, false
11641         )
11642     | Element (name, fields) ->              (* type name = { fields ... } *)
11643         generate_type_struct name fields
11644     | rng ->
11645         failwithf "generate_type failed at: %s" (string_of_rng rng)
11646
11647   and is_attrs_interleave = function
11648     | [Interleave _] -> true
11649     | Attribute _ :: fields -> is_attrs_interleave fields
11650     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11651     | _ -> false
11652
11653   and get_attrs_interleave = function
11654     | [Interleave fields] -> fields
11655     | ((Attribute _) as field) :: fields
11656     | ((Optional (Attribute _)) as field) :: fields ->
11657         field :: get_attrs_interleave fields
11658     | _ -> assert false
11659
11660   and generate_types xs =
11661     List.iter (fun x -> ignore (generate_type x)) xs
11662
11663   and generate_type_struct name fields =
11664     (* Calculate the types of the fields first.  We have to do this
11665      * before printing anything so we are still in BOL context.
11666      *)
11667     let types = List.map fst (List.map generate_type fields) in
11668
11669     (* Special case of a struct containing just a string and another
11670      * field.  Turn it into an assoc list.
11671      *)
11672     match types with
11673     | ["string"; other] ->
11674         let fname1, fname2 =
11675           match fields with
11676           | [f1; f2] -> name_of_field f1, name_of_field f2
11677           | _ -> assert false in
11678         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11679         name, false
11680
11681     | types ->
11682         pr "type %s = {\n" name;
11683         List.iter (
11684           fun (field, ftype) ->
11685             let fname = name_of_field field in
11686             pr "  %s_%s : %s;\n" name fname ftype
11687         ) (List.combine fields types);
11688         pr "}\n";
11689         (* Return the name of this type, and
11690          * false because it's not a simple type.
11691          *)
11692         name, false
11693   in
11694
11695   generate_types xs
11696
11697 let generate_parsers xs =
11698   (* As for generate_type above, generate_parser makes a parser for
11699    * some type, and returns the name of the parser it has generated.
11700    * Because it (may) need to print something, it should always be
11701    * called in BOL context.
11702    *)
11703   let rec generate_parser = function
11704     | Text ->                                (* string *)
11705         "string_child_or_empty"
11706     | Choice values ->                        (* [`val1|`val2|...] *)
11707         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11708           (String.concat "|"
11709              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11710     | ZeroOrMore rng ->                        (* <rng> list *)
11711         let pa = generate_parser rng in
11712         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11713     | OneOrMore rng ->                        (* <rng> list *)
11714         let pa = generate_parser rng in
11715         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11716                                         (* virt-inspector hack: bool *)
11717     | Optional (Attribute (name, [Value "1"])) ->
11718         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11719     | Optional rng ->                        (* <rng> list *)
11720         let pa = generate_parser rng in
11721         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11722                                         (* type name = { fields ... } *)
11723     | Element (name, fields) when is_attrs_interleave fields ->
11724         generate_parser_struct name (get_attrs_interleave fields)
11725     | Element (name, [field]) ->        (* type name = field *)
11726         let pa = generate_parser field in
11727         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11728         pr "let %s =\n" parser_name;
11729         pr "  %s\n" pa;
11730         pr "let parse_%s = %s\n" name parser_name;
11731         parser_name
11732     | Attribute (name, [field]) ->
11733         let pa = generate_parser field in
11734         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11735         pr "let %s =\n" parser_name;
11736         pr "  %s\n" pa;
11737         pr "let parse_%s = %s\n" name parser_name;
11738         parser_name
11739     | Element (name, fields) ->              (* type name = { fields ... } *)
11740         generate_parser_struct name ([], fields)
11741     | rng ->
11742         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11743
11744   and is_attrs_interleave = function
11745     | [Interleave _] -> true
11746     | Attribute _ :: fields -> is_attrs_interleave fields
11747     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11748     | _ -> false
11749
11750   and get_attrs_interleave = function
11751     | [Interleave fields] -> [], fields
11752     | ((Attribute _) as field) :: fields
11753     | ((Optional (Attribute _)) as field) :: fields ->
11754         let attrs, interleaves = get_attrs_interleave fields in
11755         (field :: attrs), interleaves
11756     | _ -> assert false
11757
11758   and generate_parsers xs =
11759     List.iter (fun x -> ignore (generate_parser x)) xs
11760
11761   and generate_parser_struct name (attrs, interleaves) =
11762     (* Generate parsers for the fields first.  We have to do this
11763      * before printing anything so we are still in BOL context.
11764      *)
11765     let fields = attrs @ interleaves in
11766     let pas = List.map generate_parser fields in
11767
11768     (* Generate an intermediate tuple from all the fields first.
11769      * If the type is just a string + another field, then we will
11770      * return this directly, otherwise it is turned into a record.
11771      *
11772      * RELAX NG note: This code treats <interleave> and plain lists of
11773      * fields the same.  In other words, it doesn't bother enforcing
11774      * any ordering of fields in the XML.
11775      *)
11776     pr "let parse_%s x =\n" name;
11777     pr "  let t = (\n    ";
11778     let comma = ref false in
11779     List.iter (
11780       fun x ->
11781         if !comma then pr ",\n    ";
11782         comma := true;
11783         match x with
11784         | Optional (Attribute (fname, [field])), pa ->
11785             pr "%s x" pa
11786         | Optional (Element (fname, [field])), pa ->
11787             pr "%s (optional_child %S x)" pa fname
11788         | Attribute (fname, [Text]), _ ->
11789             pr "attribute %S x" fname
11790         | (ZeroOrMore _ | OneOrMore _), pa ->
11791             pr "%s x" pa
11792         | Text, pa ->
11793             pr "%s x" pa
11794         | (field, pa) ->
11795             let fname = name_of_field field in
11796             pr "%s (child %S x)" pa fname
11797     ) (List.combine fields pas);
11798     pr "\n  ) in\n";
11799
11800     (match fields with
11801      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11802          pr "  t\n"
11803
11804      | _ ->
11805          pr "  (Obj.magic t : %s)\n" name
11806 (*
11807          List.iter (
11808            function
11809            | (Optional (Attribute (fname, [field])), pa) ->
11810                pr "  %s_%s =\n" name fname;
11811                pr "    %s x;\n" pa
11812            | (Optional (Element (fname, [field])), pa) ->
11813                pr "  %s_%s =\n" name fname;
11814                pr "    (let x = optional_child %S x in\n" fname;
11815                pr "     %s x);\n" pa
11816            | (field, pa) ->
11817                let fname = name_of_field field in
11818                pr "  %s_%s =\n" name fname;
11819                pr "    (let x = child %S x in\n" fname;
11820                pr "     %s x);\n" pa
11821          ) (List.combine fields pas);
11822          pr "}\n"
11823 *)
11824     );
11825     sprintf "parse_%s" name
11826   in
11827
11828   generate_parsers xs
11829
11830 (* Generate ocaml/guestfs_inspector.mli. *)
11831 let generate_ocaml_inspector_mli () =
11832   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11833
11834   pr "\
11835 (** This is an OCaml language binding to the external [virt-inspector]
11836     program.
11837
11838     For more information, please read the man page [virt-inspector(1)].
11839 *)
11840
11841 ";
11842
11843   generate_types grammar;
11844   pr "(** The nested information returned from the {!inspect} function. *)\n";
11845   pr "\n";
11846
11847   pr "\
11848 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11849 (** To inspect a libvirt domain called [name], pass a singleton
11850     list: [inspect [name]].  When using libvirt only, you may
11851     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11852
11853     To inspect a disk image or images, pass a list of the filenames
11854     of the disk images: [inspect filenames]
11855
11856     This function inspects the given guest or disk images and
11857     returns a list of operating system(s) found and a large amount
11858     of information about them.  In the vast majority of cases,
11859     a virtual machine only contains a single operating system.
11860
11861     If the optional [~xml] parameter is given, then this function
11862     skips running the external virt-inspector program and just
11863     parses the given XML directly (which is expected to be XML
11864     produced from a previous run of virt-inspector).  The list of
11865     names and connect URI are ignored in this case.
11866
11867     This function can throw a wide variety of exceptions, for example
11868     if the external virt-inspector program cannot be found, or if
11869     it doesn't generate valid XML.
11870 *)
11871 "
11872
11873 (* Generate ocaml/guestfs_inspector.ml. *)
11874 let generate_ocaml_inspector_ml () =
11875   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11876
11877   pr "open Unix\n";
11878   pr "\n";
11879
11880   generate_types grammar;
11881   pr "\n";
11882
11883   pr "\
11884 (* Misc functions which are used by the parser code below. *)
11885 let first_child = function
11886   | Xml.Element (_, _, c::_) -> c
11887   | Xml.Element (name, _, []) ->
11888       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11889   | Xml.PCData str ->
11890       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11891
11892 let string_child_or_empty = function
11893   | Xml.Element (_, _, [Xml.PCData s]) -> s
11894   | Xml.Element (_, _, []) -> \"\"
11895   | Xml.Element (x, _, _) ->
11896       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11897                 x ^ \" instead\")
11898   | Xml.PCData str ->
11899       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11900
11901 let optional_child name xml =
11902   let children = Xml.children xml in
11903   try
11904     Some (List.find (function
11905                      | Xml.Element (n, _, _) when n = name -> true
11906                      | _ -> false) children)
11907   with
11908     Not_found -> None
11909
11910 let child name xml =
11911   match optional_child name xml with
11912   | Some c -> c
11913   | None ->
11914       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11915
11916 let attribute name xml =
11917   try Xml.attrib xml name
11918   with Xml.No_attribute _ ->
11919     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11920
11921 ";
11922
11923   generate_parsers grammar;
11924   pr "\n";
11925
11926   pr "\
11927 (* Run external virt-inspector, then use parser to parse the XML. *)
11928 let inspect ?connect ?xml names =
11929   let xml =
11930     match xml with
11931     | None ->
11932         if names = [] then invalid_arg \"inspect: no names given\";
11933         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11934           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11935           names in
11936         let cmd = List.map Filename.quote cmd in
11937         let cmd = String.concat \" \" cmd in
11938         let chan = open_process_in cmd in
11939         let xml = Xml.parse_in chan in
11940         (match close_process_in chan with
11941          | WEXITED 0 -> ()
11942          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11943          | WSIGNALED i | WSTOPPED i ->
11944              failwith (\"external virt-inspector command died or stopped on sig \" ^
11945                        string_of_int i)
11946         );
11947         xml
11948     | Some doc ->
11949         Xml.parse_string doc in
11950   parse_operatingsystems xml
11951 "
11952
11953 and generate_max_proc_nr () =
11954   pr "%d\n" max_proc_nr
11955
11956 let output_to filename k =
11957   let filename_new = filename ^ ".new" in
11958   chan := open_out filename_new;
11959   k ();
11960   close_out !chan;
11961   chan := Pervasives.stdout;
11962
11963   (* Is the new file different from the current file? *)
11964   if Sys.file_exists filename && files_equal filename filename_new then
11965     unlink filename_new                 (* same, so skip it *)
11966   else (
11967     (* different, overwrite old one *)
11968     (try chmod filename 0o644 with Unix_error _ -> ());
11969     rename filename_new filename;
11970     chmod filename 0o444;
11971     printf "written %s\n%!" filename;
11972   )
11973
11974 let perror msg = function
11975   | Unix_error (err, _, _) ->
11976       eprintf "%s: %s\n" msg (error_message err)
11977   | exn ->
11978       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11979
11980 (* Main program. *)
11981 let () =
11982   let lock_fd =
11983     try openfile "HACKING" [O_RDWR] 0
11984     with
11985     | Unix_error (ENOENT, _, _) ->
11986         eprintf "\
11987 You are probably running this from the wrong directory.
11988 Run it from the top source directory using the command
11989   src/generator.ml
11990 ";
11991         exit 1
11992     | exn ->
11993         perror "open: HACKING" exn;
11994         exit 1 in
11995
11996   (* Acquire a lock so parallel builds won't try to run the generator
11997    * twice at the same time.  Subsequent builds will wait for the first
11998    * one to finish.  Note the lock is released implicitly when the
11999    * program exits.
12000    *)
12001   (try lockf lock_fd F_LOCK 1
12002    with exn ->
12003      perror "lock: HACKING" exn;
12004      exit 1);
12005
12006   check_functions ();
12007
12008   output_to "src/guestfs_protocol.x" generate_xdr;
12009   output_to "src/guestfs-structs.h" generate_structs_h;
12010   output_to "src/guestfs-actions.h" generate_actions_h;
12011   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12012   output_to "src/guestfs-actions.c" generate_client_actions;
12013   output_to "src/guestfs-bindtests.c" generate_bindtests;
12014   output_to "src/guestfs-structs.pod" generate_structs_pod;
12015   output_to "src/guestfs-actions.pod" generate_actions_pod;
12016   output_to "src/guestfs-availability.pod" generate_availability_pod;
12017   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12018   output_to "src/libguestfs.syms" generate_linker_script;
12019   output_to "daemon/actions.h" generate_daemon_actions_h;
12020   output_to "daemon/stubs.c" generate_daemon_actions;
12021   output_to "daemon/names.c" generate_daemon_names;
12022   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12023   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12024   output_to "capitests/tests.c" generate_tests;
12025   output_to "fish/cmds.c" generate_fish_cmds;
12026   output_to "fish/completion.c" generate_fish_completion;
12027   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12028   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12029   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12030   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12031   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12032   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12033   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12034   output_to "perl/Guestfs.xs" generate_perl_xs;
12035   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12036   output_to "perl/bindtests.pl" generate_perl_bindtests;
12037   output_to "python/guestfs-py.c" generate_python_c;
12038   output_to "python/guestfs.py" generate_python_py;
12039   output_to "python/bindtests.py" generate_python_bindtests;
12040   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12041   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12042   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12043
12044   List.iter (
12045     fun (typ, jtyp) ->
12046       let cols = cols_of_struct typ in
12047       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12048       output_to filename (generate_java_struct jtyp cols);
12049   ) java_structs;
12050
12051   output_to "java/Makefile.inc" generate_java_makefile_inc;
12052   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12053   output_to "java/Bindtests.java" generate_java_bindtests;
12054   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12055   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12056   output_to "csharp/Libguestfs.cs" generate_csharp;
12057
12058   (* Always generate this file last, and unconditionally.  It's used
12059    * by the Makefile to know when we must re-run the generator.
12060    *)
12061   let chan = open_out "src/stamp-generator" in
12062   fprintf chan "1\n";
12063   close_out chan;
12064
12065   printf "generated %d lines of code\n" !lines