perl: Document handle is a hashref.
[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     (* Run the test only if 'string' is available in the daemon. *)
313   | IfAvailable of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388   BufferIn "bufferin";
389 ]
390
391 let test_all_rets = [
392   (* except for RErr, which is tested thoroughly elsewhere *)
393   "test0rint",         RInt "valout";
394   "test0rint64",       RInt64 "valout";
395   "test0rbool",        RBool "valout";
396   "test0rconststring", RConstString "valout";
397   "test0rconstoptstring", RConstOptString "valout";
398   "test0rstring",      RString "valout";
399   "test0rstringlist",  RStringList "valout";
400   "test0rstruct",      RStruct ("valout", "lvm_pv");
401   "test0rstructlist",  RStructList ("valout", "lvm_pv");
402   "test0rhashtable",   RHashtable "valout";
403 ]
404
405 let test_functions = [
406   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407    [],
408    "internal test function - do not use",
409    "\
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
413
414 It echos the contents of each parameter to stdout.
415
416 You probably don't want to call this function.");
417 ] @ List.flatten (
418   List.map (
419     fun (name, ret) ->
420       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421         [],
422         "internal test function - do not use",
423         "\
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
427
428 It converts string C<val> to the return type.
429
430 You probably don't want to call this function.");
431        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432         [],
433         "internal test function - do not use",
434         "\
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
438
439 This function always returns an error.
440
441 You probably don't want to call this function.")]
442   ) test_all_rets
443 )
444
445 (* non_daemon_functions are any functions which don't get processed
446  * in the daemon, eg. functions for setting and getting local
447  * configuration values.
448  *)
449
450 let non_daemon_functions = test_functions @ [
451   ("launch", (RErr, []), -1, [FishAlias "run"],
452    [],
453    "launch the qemu subprocess",
454    "\
455 Internally libguestfs is implemented by running a virtual machine
456 using L<qemu(1)>.
457
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
460
461   ("wait_ready", (RErr, []), -1, [NotInFish],
462    [],
463    "wait until the qemu subprocess launches (no op)",
464    "\
465 This function is a no op.
466
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete.  However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
471
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
475
476   ("kill_subprocess", (RErr, []), -1, [],
477    [],
478    "kill the qemu subprocess",
479    "\
480 This kills the qemu subprocess.  You should never need to call this.");
481
482   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483    [],
484    "add an image to examine or modify",
485    "\
486 This function adds a virtual machine disk image C<filename> to the
487 guest.  The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
489 so on.
490
491 You don't necessarily need to be root when using libguestfs.  However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
495 image).
496
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
499
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
502
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>.  In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
507
508 Note that this call checks for the existence of C<filename>.  This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
511 the general C<guestfs_config> call instead.");
512
513   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514    [],
515    "add a CD-ROM disk image to examine",
516    "\
517 This function adds a virtual CD-ROM disk image to the guest.
518
519 This is equivalent to the qemu parameter C<-cdrom filename>.
520
521 Notes:
522
523 =over 4
524
525 =item *
526
527 This call checks for the existence of C<filename>.  This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
530 the general C<guestfs_config> call instead.
531
532 =item *
533
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
537
538 =back");
539
540   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541    [],
542    "add a drive in snapshot mode (read-only)",
543    "\
544 This adds a drive in snapshot mode, making it effectively
545 read-only.
546
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed.  We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
552
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,if=...>.
555
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>.  In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
560
561 Note that this call checks for the existence of C<filename>.  This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
564 the general C<guestfs_config> call instead.");
565
566   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567    [],
568    "add qemu parameters",
569    "\
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>.  Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
574
575 The first character of C<param> string must be a C<-> (dash).
576
577 C<value> can be NULL.");
578
579   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
580    [],
581    "set the qemu binary",
582    "\
583 Set the qemu binary that we will use.
584
585 The default is chosen when the library was compiled by the
586 configure script.
587
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
590
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
592
593 Note that you should call this function as early as possible
594 after creating the handle.  This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results.  Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
600
601   ("get_qemu", (RConstString "qemu", []), -1, [],
602    [InitNone, Always, TestRun (
603       [["get_qemu"]])],
604    "get the qemu binary",
605    "\
606 Return the current qemu binary.
607
608 This is always non-NULL.  If it wasn't set already, then this will
609 return the default qemu binary name.");
610
611   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
612    [],
613    "set the search path",
614    "\
615 Set the path that libguestfs searches for kernel and initrd.img.
616
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
619
620 Setting C<path> to C<NULL> restores the default path.");
621
622   ("get_path", (RConstString "path", []), -1, [],
623    [InitNone, Always, TestRun (
624       [["get_path"]])],
625    "get the search path",
626    "\
627 Return the current search path.
628
629 This is always non-NULL.  If it wasn't set already, then this will
630 return the default path.");
631
632   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633    [],
634    "add options to kernel command line",
635    "\
636 This function is used to add additional options to the
637 guest kernel command line.
638
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
641
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
644
645   ("get_append", (RConstOptString "append", []), -1, [],
646    (* This cannot be tested with the current framework.  The
647     * function can return NULL in normal operations, which the
648     * test framework interprets as an error.
649     *)
650    [],
651    "get the additional kernel options",
652    "\
653 Return the additional kernel options which are added to the
654 guest kernel command line.
655
656 If C<NULL> then no options are added.");
657
658   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
659    [],
660    "set autosync mode",
661    "\
662 If C<autosync> is true, this enables autosync.  Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
666
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
669
670   ("get_autosync", (RBool "autosync", []), -1, [],
671    [InitNone, Always, TestRun (
672       [["get_autosync"]])],
673    "get autosync mode",
674    "\
675 Get the autosync flag.");
676
677   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
678    [],
679    "set verbose mode",
680    "\
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685
686   ("get_verbose", (RBool "verbose", []), -1, [],
687    [],
688    "get verbose mode",
689    "\
690 This returns the verbose messages flag.");
691
692   ("is_ready", (RBool "ready", []), -1, [],
693    [InitNone, Always, TestOutputTrue (
694       [["is_ready"]])],
695    "is ready to accept commands",
696    "\
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
699
700 For more information on states, see L<guestfs(3)>.");
701
702   ("is_config", (RBool "config", []), -1, [],
703    [InitNone, Always, TestOutputFalse (
704       [["is_config"]])],
705    "is in configuration state",
706    "\
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
709
710 For more information on states, see L<guestfs(3)>.");
711
712   ("is_launching", (RBool "launching", []), -1, [],
713    [InitNone, Always, TestOutputFalse (
714       [["is_launching"]])],
715    "is launching subprocess",
716    "\
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
719
720 For more information on states, see L<guestfs(3)>.");
721
722   ("is_busy", (RBool "busy", []), -1, [],
723    [InitNone, Always, TestOutputFalse (
724       [["is_busy"]])],
725    "is busy processing a command",
726    "\
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
729
730 For more information on states, see L<guestfs(3)>.");
731
732   ("get_state", (RInt "state", []), -1, [],
733    [],
734    "get the current state",
735    "\
736 This returns the current state as an opaque integer.  This is
737 only useful for printing debug and internal error messages.
738
739 For more information on states, see L<guestfs(3)>.");
740
741   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742    [InitNone, Always, TestOutputInt (
743       [["set_memsize"; "500"];
744        ["get_memsize"]], 500)],
745    "set memory allocated to the qemu subprocess",
746    "\
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess.  This only has any effect if called before
749 C<guestfs_launch>.
750
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
753 created.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_memsize", (RInt "memsize", []), -1, [],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_memsize"]], ">=", 256)],
761    "get memory allocated to the qemu subprocess",
762    "\
763 This gets the memory size in megabytes allocated to the
764 qemu subprocess.
765
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
769
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
772
773   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774    [InitNone, Always, TestOutputIntOp (
775       [["get_pid"]], ">=", 1)],
776    "get PID of qemu subprocess",
777    "\
778 Return the process ID of the qemu subprocess.  If there is no
779 qemu subprocess, then this will return an error.
780
781 This is an internal call used for debugging and testing.");
782
783   ("version", (RStruct ("version", "version"), []), -1, [],
784    [InitNone, Always, TestOutputStruct (
785       [["version"]], [CompareWithInt ("major", 1)])],
786    "get the library version number",
787    "\
788 Return the libguestfs version number that the program is linked
789 against.
790
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against.  You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
795
796 This call was added in version C<1.0.58>.  In previous
797 versions of libguestfs there was no way to get the version
798 number.  From C code you can use dynamic linker functions
799 to find out if this symbol exists (if it doesn't, then
800 it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
812
813 I<Note:> Don't use this call to test for availability
814 of features.  In enterprise distributions we backport
815 features from later versions into earlier versions,
816 making this an unreliable way to test for features.
817 Use C<guestfs_available> instead.");
818
819   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
820    [InitNone, Always, TestOutputTrue (
821       [["set_selinux"; "true"];
822        ["get_selinux"]])],
823    "set SELinux enabled or disabled at appliance boot",
824    "\
825 This sets the selinux flag that is passed to the appliance
826 at boot time.  The default is C<selinux=0> (disabled).
827
828 Note that if SELinux is enabled, it is always in
829 Permissive mode (C<enforcing=0>).
830
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
833
834   ("get_selinux", (RBool "selinux", []), -1, [],
835    [],
836    "get SELinux enabled flag",
837    "\
838 This returns the current setting of the selinux flag which
839 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
840
841 For more information on the architecture of libguestfs,
842 see L<guestfs(3)>.");
843
844   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
845    [InitNone, Always, TestOutputFalse (
846       [["set_trace"; "false"];
847        ["get_trace"]])],
848    "enable or disable command traces",
849    "\
850 If the command trace flag is set to 1, then commands are
851 printed on stdout before they are executed in a format
852 which is very similar to the one used by guestfish.  In
853 other words, you can run a program with this enabled, and
854 you will get out a script which you can feed to guestfish
855 to perform the same set of actions.
856
857 If you want to trace C API calls into libguestfs (and
858 other libraries) then possibly a better way is to use
859 the external ltrace(1) command.
860
861 Command traces are disabled unless the environment variable
862 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
863
864   ("get_trace", (RBool "trace", []), -1, [],
865    [],
866    "get command trace enabled flag",
867    "\
868 Return the command trace flag.");
869
870   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
871    [InitNone, Always, TestOutputFalse (
872       [["set_direct"; "false"];
873        ["get_direct"]])],
874    "enable or disable direct appliance mode",
875    "\
876 If the direct appliance mode flag is enabled, then stdin and
877 stdout are passed directly through to the appliance once it
878 is launched.
879
880 One consequence of this is that log messages aren't caught
881 by the library and handled by C<guestfs_set_log_message_callback>,
882 but go straight to stdout.
883
884 You probably don't want to use this unless you know what you
885 are doing.
886
887 The default is disabled.");
888
889   ("get_direct", (RBool "direct", []), -1, [],
890    [],
891    "get direct appliance mode flag",
892    "\
893 Return the direct appliance mode flag.");
894
895   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
896    [InitNone, Always, TestOutputTrue (
897       [["set_recovery_proc"; "true"];
898        ["get_recovery_proc"]])],
899    "enable or disable the recovery process",
900    "\
901 If this is called with the parameter C<false> then
902 C<guestfs_launch> does not create a recovery process.  The
903 purpose of the recovery process is to stop runaway qemu
904 processes in the case where the main program aborts abruptly.
905
906 This only has any effect if called before C<guestfs_launch>,
907 and the default is true.
908
909 About the only time when you would want to disable this is
910 if the main process will fork itself into the background
911 (\"daemonize\" itself).  In this case the recovery process
912 thinks that the main program has disappeared and so kills
913 qemu, which is not very helpful.");
914
915   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
916    [],
917    "get recovery process enabled flag",
918    "\
919 Return the recovery process enabled flag.");
920
921   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
922    [],
923    "add a drive specifying the QEMU block emulation to use",
924    "\
925 This is the same as C<guestfs_add_drive> but it allows you
926 to specify the QEMU interface emulation to use at run time.");
927
928   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
929    [],
930    "add a drive read-only specifying the QEMU block emulation to use",
931    "\
932 This is the same as C<guestfs_add_drive_ro> but it allows you
933 to specify the QEMU interface emulation to use at run time.");
934
935 ]
936
937 (* daemon_functions are any functions which cause some action
938  * to take place in the daemon.
939  *)
940
941 let daemon_functions = [
942   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
943    [InitEmpty, Always, TestOutput (
944       [["part_disk"; "/dev/sda"; "mbr"];
945        ["mkfs"; "ext2"; "/dev/sda1"];
946        ["mount"; "/dev/sda1"; "/"];
947        ["write"; "/new"; "new file contents"];
948        ["cat"; "/new"]], "new file contents")],
949    "mount a guest disk at a position in the filesystem",
950    "\
951 Mount a guest disk at a position in the filesystem.  Block devices
952 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
953 the guest.  If those block devices contain partitions, they will have
954 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
955 names can be used.
956
957 The rules are the same as for L<mount(2)>:  A filesystem must
958 first be mounted on C</> before others can be mounted.  Other
959 filesystems can only be mounted on directories which already
960 exist.
961
962 The mounted filesystem is writable, if we have sufficient permissions
963 on the underlying device.
964
965 B<Important note:>
966 When you use this call, the filesystem options C<sync> and C<noatime>
967 are set implicitly.  This was originally done because we thought it
968 would improve reliability, but it turns out that I<-o sync> has a
969 very large negative performance impact and negligible effect on
970 reliability.  Therefore we recommend that you avoid using
971 C<guestfs_mount> in any code that needs performance, and instead
972 use C<guestfs_mount_options> (use an empty string for the first
973 parameter if you don't want any options).");
974
975   ("sync", (RErr, []), 2, [],
976    [ InitEmpty, Always, TestRun [["sync"]]],
977    "sync disks, writes are flushed through to the disk image",
978    "\
979 This syncs the disk, so that any writes are flushed through to the
980 underlying disk image.
981
982 You should always call this if you have modified a disk image, before
983 closing the handle.");
984
985   ("touch", (RErr, [Pathname "path"]), 3, [],
986    [InitBasicFS, Always, TestOutputTrue (
987       [["touch"; "/new"];
988        ["exists"; "/new"]])],
989    "update file timestamps or create a new file",
990    "\
991 Touch acts like the L<touch(1)> command.  It can be used to
992 update the timestamps on a file, or, if the file does not exist,
993 to create a new zero-length file.
994
995 This command only works on regular files, and will fail on other
996 file types such as directories, symbolic links, block special etc.");
997
998   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
999    [InitISOFS, Always, TestOutput (
1000       [["cat"; "/known-2"]], "abcdef\n")],
1001    "list the contents of a file",
1002    "\
1003 Return the contents of the file named C<path>.
1004
1005 Note that this function cannot correctly handle binary files
1006 (specifically, files containing C<\\0> character which is treated
1007 as end of string).  For those you need to use the C<guestfs_read_file>
1008 or C<guestfs_download> functions which have a more complex interface.");
1009
1010   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1011    [], (* XXX Tricky to test because it depends on the exact format
1012         * of the 'ls -l' command, which changes between F10 and F11.
1013         *)
1014    "list the files in a directory (long format)",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd) in the format of 'ls -la'.
1018
1019 This command is mostly useful for interactive sessions.  It
1020 is I<not> intended that you try to parse the output string.");
1021
1022   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1023    [InitBasicFS, Always, TestOutputList (
1024       [["touch"; "/new"];
1025        ["touch"; "/newer"];
1026        ["touch"; "/newest"];
1027        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1028    "list the files in a directory",
1029    "\
1030 List the files in C<directory> (relative to the root directory,
1031 there is no cwd).  The '.' and '..' entries are not returned, but
1032 hidden files are shown.
1033
1034 This command is mostly useful for interactive sessions.  Programs
1035 should probably use C<guestfs_readdir> instead.");
1036
1037   ("list_devices", (RStringList "devices", []), 7, [],
1038    [InitEmpty, Always, TestOutputListOfDevices (
1039       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1040    "list the block devices",
1041    "\
1042 List all the block devices.
1043
1044 The full block device names are returned, eg. C</dev/sda>");
1045
1046   ("list_partitions", (RStringList "partitions", []), 8, [],
1047    [InitBasicFS, Always, TestOutputListOfDevices (
1048       [["list_partitions"]], ["/dev/sda1"]);
1049     InitEmpty, Always, TestOutputListOfDevices (
1050       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1052    "list the partitions",
1053    "\
1054 List all the partitions detected on all block devices.
1055
1056 The full partition device names are returned, eg. C</dev/sda1>
1057
1058 This does not return logical volumes.  For that you will need to
1059 call C<guestfs_lvs>.");
1060
1061   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1063       [["pvs"]], ["/dev/sda1"]);
1064     InitEmpty, Always, TestOutputListOfDevices (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1070    "list the LVM physical volumes (PVs)",
1071    "\
1072 List all the physical volumes detected.  This is the equivalent
1073 of the L<pvs(8)> command.
1074
1075 This returns a list of just the device names that contain
1076 PVs (eg. C</dev/sda2>).
1077
1078 See also C<guestfs_pvs_full>.");
1079
1080   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1081    [InitBasicFSonLVM, Always, TestOutputList (
1082       [["vgs"]], ["VG"]);
1083     InitEmpty, Always, TestOutputList (
1084       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1085        ["pvcreate"; "/dev/sda1"];
1086        ["pvcreate"; "/dev/sda2"];
1087        ["pvcreate"; "/dev/sda3"];
1088        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1089        ["vgcreate"; "VG2"; "/dev/sda3"];
1090        ["vgs"]], ["VG1"; "VG2"])],
1091    "list the LVM volume groups (VGs)",
1092    "\
1093 List all the volumes groups detected.  This is the equivalent
1094 of the L<vgs(8)> command.
1095
1096 This returns a list of just the volume group names that were
1097 detected (eg. C<VolGroup00>).
1098
1099 See also C<guestfs_vgs_full>.");
1100
1101   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1102    [InitBasicFSonLVM, Always, TestOutputList (
1103       [["lvs"]], ["/dev/VG/LV"]);
1104     InitEmpty, Always, TestOutputList (
1105       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1106        ["pvcreate"; "/dev/sda1"];
1107        ["pvcreate"; "/dev/sda2"];
1108        ["pvcreate"; "/dev/sda3"];
1109        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1110        ["vgcreate"; "VG2"; "/dev/sda3"];
1111        ["lvcreate"; "LV1"; "VG1"; "50"];
1112        ["lvcreate"; "LV2"; "VG1"; "50"];
1113        ["lvcreate"; "LV3"; "VG2"; "50"];
1114        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1115    "list the LVM logical volumes (LVs)",
1116    "\
1117 List all the logical volumes detected.  This is the equivalent
1118 of the L<lvs(8)> command.
1119
1120 This returns a list of the logical volume device names
1121 (eg. C</dev/VolGroup00/LogVol00>).
1122
1123 See also C<guestfs_lvs_full>.");
1124
1125   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM physical volumes (PVs)",
1128    "\
1129 List all the physical volumes detected.  This is the equivalent
1130 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM volume groups (VGs)",
1135    "\
1136 List all the volumes groups detected.  This is the equivalent
1137 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1140    [], (* XXX how to test? *)
1141    "list the LVM logical volumes (LVs)",
1142    "\
1143 List all the logical volumes detected.  This is the equivalent
1144 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1145
1146   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1147    [InitISOFS, Always, TestOutputList (
1148       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1149     InitISOFS, Always, TestOutputList (
1150       [["read_lines"; "/empty"]], [])],
1151    "read file as lines",
1152    "\
1153 Return the contents of the file named C<path>.
1154
1155 The file contents are returned as a list of lines.  Trailing
1156 C<LF> and C<CRLF> character sequences are I<not> returned.
1157
1158 Note that this function cannot correctly handle binary files
1159 (specifically, files containing C<\\0> character which is treated
1160 as end of line).  For those you need to use the C<guestfs_read_file>
1161 function which has a more complex interface.");
1162
1163   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1164    [], (* XXX Augeas code needs tests. *)
1165    "create a new Augeas handle",
1166    "\
1167 Create a new Augeas handle for editing configuration files.
1168 If there was any previous Augeas handle associated with this
1169 guestfs session, then it is closed.
1170
1171 You must call this before using any other C<guestfs_aug_*>
1172 commands.
1173
1174 C<root> is the filesystem root.  C<root> must not be NULL,
1175 use C</> instead.
1176
1177 The flags are the same as the flags defined in
1178 E<lt>augeas.hE<gt>, the logical I<or> of the following
1179 integers:
1180
1181 =over 4
1182
1183 =item C<AUG_SAVE_BACKUP> = 1
1184
1185 Keep the original file with a C<.augsave> extension.
1186
1187 =item C<AUG_SAVE_NEWFILE> = 2
1188
1189 Save changes into a file with extension C<.augnew>, and
1190 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1191
1192 =item C<AUG_TYPE_CHECK> = 4
1193
1194 Typecheck lenses (can be expensive).
1195
1196 =item C<AUG_NO_STDINC> = 8
1197
1198 Do not use standard load path for modules.
1199
1200 =item C<AUG_SAVE_NOOP> = 16
1201
1202 Make save a no-op, just record what would have been changed.
1203
1204 =item C<AUG_NO_LOAD> = 32
1205
1206 Do not load the tree in C<guestfs_aug_init>.
1207
1208 =back
1209
1210 To close the handle, you can call C<guestfs_aug_close>.
1211
1212 To find out more about Augeas, see L<http://augeas.net/>.");
1213
1214   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "close the current Augeas handle",
1217    "\
1218 Close the current Augeas handle and free up any resources
1219 used by it.  After calling this, you have to call
1220 C<guestfs_aug_init> again before you can use any other
1221 Augeas functions.");
1222
1223   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1224    [], (* XXX Augeas code needs tests. *)
1225    "define an Augeas variable",
1226    "\
1227 Defines an Augeas variable C<name> whose value is the result
1228 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1229 undefined.
1230
1231 On success this returns the number of nodes in C<expr>, or
1232 C<0> if C<expr> evaluates to something which is not a nodeset.");
1233
1234   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1235    [], (* XXX Augeas code needs tests. *)
1236    "define an Augeas node",
1237    "\
1238 Defines a variable C<name> whose value is the result of
1239 evaluating C<expr>.
1240
1241 If C<expr> evaluates to an empty nodeset, a node is created,
1242 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1243 C<name> will be the nodeset containing that single node.
1244
1245 On success this returns a pair containing the
1246 number of nodes in the nodeset, and a boolean flag
1247 if a node was created.");
1248
1249   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "look up the value of an Augeas path",
1252    "\
1253 Look up the value associated with C<path>.  If C<path>
1254 matches exactly one node, the C<value> is returned.");
1255
1256   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1257    [], (* XXX Augeas code needs tests. *)
1258    "set Augeas path to value",
1259    "\
1260 Set the value associated with C<path> to C<val>.
1261
1262 In the Augeas API, it is possible to clear a node by setting
1263 the value to NULL.  Due to an oversight in the libguestfs API
1264 you cannot do that with this call.  Instead you must use the
1265 C<guestfs_aug_clear> call.");
1266
1267   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "insert a sibling Augeas node",
1270    "\
1271 Create a new sibling C<label> for C<path>, inserting it into
1272 the tree before or after C<path> (depending on the boolean
1273 flag C<before>).
1274
1275 C<path> must match exactly one existing node in the tree, and
1276 C<label> must be a label, ie. not contain C</>, C<*> or end
1277 with a bracketed index C<[N]>.");
1278
1279   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "remove an Augeas path",
1282    "\
1283 Remove C<path> and all of its children.
1284
1285 On success this returns the number of entries which were removed.");
1286
1287   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "move Augeas node",
1290    "\
1291 Move the node C<src> to C<dest>.  C<src> must match exactly
1292 one node.  C<dest> is overwritten if it exists.");
1293
1294   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "return Augeas nodes which match augpath",
1297    "\
1298 Returns a list of paths which match the path expression C<path>.
1299 The returned paths are sufficiently qualified so that they match
1300 exactly one node in the current tree.");
1301
1302   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "write all pending Augeas changes to disk",
1305    "\
1306 This writes all pending changes to disk.
1307
1308 The flags which were passed to C<guestfs_aug_init> affect exactly
1309 how files are saved.");
1310
1311   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "load files into the tree",
1314    "\
1315 Load files into the tree.
1316
1317 See C<aug_load> in the Augeas documentation for the full gory
1318 details.");
1319
1320   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1321    [], (* XXX Augeas code needs tests. *)
1322    "list Augeas nodes under augpath",
1323    "\
1324 This is just a shortcut for listing C<guestfs_aug_match>
1325 C<path/*> and sorting the resulting nodes into alphabetical order.");
1326
1327   ("rm", (RErr, [Pathname "path"]), 29, [],
1328    [InitBasicFS, Always, TestRun
1329       [["touch"; "/new"];
1330        ["rm"; "/new"]];
1331     InitBasicFS, Always, TestLastFail
1332       [["rm"; "/new"]];
1333     InitBasicFS, Always, TestLastFail
1334       [["mkdir"; "/new"];
1335        ["rm"; "/new"]]],
1336    "remove a file",
1337    "\
1338 Remove the single file C<path>.");
1339
1340   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1341    [InitBasicFS, Always, TestRun
1342       [["mkdir"; "/new"];
1343        ["rmdir"; "/new"]];
1344     InitBasicFS, Always, TestLastFail
1345       [["rmdir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["touch"; "/new"];
1348        ["rmdir"; "/new"]]],
1349    "remove a directory",
1350    "\
1351 Remove the single directory C<path>.");
1352
1353   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1354    [InitBasicFS, Always, TestOutputFalse
1355       [["mkdir"; "/new"];
1356        ["mkdir"; "/new/foo"];
1357        ["touch"; "/new/foo/bar"];
1358        ["rm_rf"; "/new"];
1359        ["exists"; "/new"]]],
1360    "remove a file or directory recursively",
1361    "\
1362 Remove the file or directory C<path>, recursively removing the
1363 contents if its a directory.  This is like the C<rm -rf> shell
1364 command.");
1365
1366   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1367    [InitBasicFS, Always, TestOutputTrue
1368       [["mkdir"; "/new"];
1369        ["is_dir"; "/new"]];
1370     InitBasicFS, Always, TestLastFail
1371       [["mkdir"; "/new/foo/bar"]]],
1372    "create a directory",
1373    "\
1374 Create a directory named C<path>.");
1375
1376   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1377    [InitBasicFS, Always, TestOutputTrue
1378       [["mkdir_p"; "/new/foo/bar"];
1379        ["is_dir"; "/new/foo/bar"]];
1380     InitBasicFS, Always, TestOutputTrue
1381       [["mkdir_p"; "/new/foo/bar"];
1382        ["is_dir"; "/new/foo"]];
1383     InitBasicFS, Always, TestOutputTrue
1384       [["mkdir_p"; "/new/foo/bar"];
1385        ["is_dir"; "/new"]];
1386     (* Regression tests for RHBZ#503133: *)
1387     InitBasicFS, Always, TestRun
1388       [["mkdir"; "/new"];
1389        ["mkdir_p"; "/new"]];
1390     InitBasicFS, Always, TestLastFail
1391       [["touch"; "/new"];
1392        ["mkdir_p"; "/new"]]],
1393    "create a directory and parents",
1394    "\
1395 Create a directory named C<path>, creating any parent directories
1396 as necessary.  This is like the C<mkdir -p> shell command.");
1397
1398   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1399    [], (* XXX Need stat command to test *)
1400    "change file mode",
1401    "\
1402 Change the mode (permissions) of C<path> to C<mode>.  Only
1403 numeric modes are supported.
1404
1405 I<Note>: When using this command from guestfish, C<mode>
1406 by default would be decimal, unless you prefix it with
1407 C<0> to get octal, ie. use C<0700> not C<700>.
1408
1409 The mode actually set is affected by the umask.");
1410
1411   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1412    [], (* XXX Need stat command to test *)
1413    "change file owner and group",
1414    "\
1415 Change the file owner to C<owner> and group to C<group>.
1416
1417 Only numeric uid and gid are supported.  If you want to use
1418 names, you will need to locate and parse the password file
1419 yourself (Augeas support makes this relatively easy).");
1420
1421   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1422    [InitISOFS, Always, TestOutputTrue (
1423       [["exists"; "/empty"]]);
1424     InitISOFS, Always, TestOutputTrue (
1425       [["exists"; "/directory"]])],
1426    "test if file or directory exists",
1427    "\
1428 This returns C<true> if and only if there is a file, directory
1429 (or anything) with the given C<path> name.
1430
1431 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1432
1433   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1434    [InitISOFS, Always, TestOutputTrue (
1435       [["is_file"; "/known-1"]]);
1436     InitISOFS, Always, TestOutputFalse (
1437       [["is_file"; "/directory"]])],
1438    "test if file exists",
1439    "\
1440 This returns C<true> if and only if there is a file
1441 with the given C<path> name.  Note that it returns false for
1442 other objects like directories.
1443
1444 See also C<guestfs_stat>.");
1445
1446   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1447    [InitISOFS, Always, TestOutputFalse (
1448       [["is_dir"; "/known-3"]]);
1449     InitISOFS, Always, TestOutputTrue (
1450       [["is_dir"; "/directory"]])],
1451    "test if file exists",
1452    "\
1453 This returns C<true> if and only if there is a directory
1454 with the given C<path> name.  Note that it returns false for
1455 other objects like files.
1456
1457 See also C<guestfs_stat>.");
1458
1459   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1460    [InitEmpty, Always, TestOutputListOfDevices (
1461       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462        ["pvcreate"; "/dev/sda1"];
1463        ["pvcreate"; "/dev/sda2"];
1464        ["pvcreate"; "/dev/sda3"];
1465        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1466    "create an LVM physical volume",
1467    "\
1468 This creates an LVM physical volume on the named C<device>,
1469 where C<device> should usually be a partition name such
1470 as C</dev/sda1>.");
1471
1472   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1473    [InitEmpty, Always, TestOutputList (
1474       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475        ["pvcreate"; "/dev/sda1"];
1476        ["pvcreate"; "/dev/sda2"];
1477        ["pvcreate"; "/dev/sda3"];
1478        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479        ["vgcreate"; "VG2"; "/dev/sda3"];
1480        ["vgs"]], ["VG1"; "VG2"])],
1481    "create an LVM volume group",
1482    "\
1483 This creates an LVM volume group called C<volgroup>
1484 from the non-empty list of physical volumes C<physvols>.");
1485
1486   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1487    [InitEmpty, Always, TestOutputList (
1488       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1489        ["pvcreate"; "/dev/sda1"];
1490        ["pvcreate"; "/dev/sda2"];
1491        ["pvcreate"; "/dev/sda3"];
1492        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1493        ["vgcreate"; "VG2"; "/dev/sda3"];
1494        ["lvcreate"; "LV1"; "VG1"; "50"];
1495        ["lvcreate"; "LV2"; "VG1"; "50"];
1496        ["lvcreate"; "LV3"; "VG2"; "50"];
1497        ["lvcreate"; "LV4"; "VG2"; "50"];
1498        ["lvcreate"; "LV5"; "VG2"; "50"];
1499        ["lvs"]],
1500       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1501        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1502    "create an LVM logical volume",
1503    "\
1504 This creates an LVM logical volume called C<logvol>
1505 on the volume group C<volgroup>, with C<size> megabytes.");
1506
1507   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1508    [InitEmpty, Always, TestOutput (
1509       [["part_disk"; "/dev/sda"; "mbr"];
1510        ["mkfs"; "ext2"; "/dev/sda1"];
1511        ["mount_options"; ""; "/dev/sda1"; "/"];
1512        ["write"; "/new"; "new file contents"];
1513        ["cat"; "/new"]], "new file contents")],
1514    "make a filesystem",
1515    "\
1516 This creates a filesystem on C<device> (usually a partition
1517 or LVM logical volume).  The filesystem type is C<fstype>, for
1518 example C<ext3>.");
1519
1520   ("sfdisk", (RErr, [Device "device";
1521                      Int "cyls"; Int "heads"; Int "sectors";
1522                      StringList "lines"]), 43, [DangerWillRobinson],
1523    [],
1524    "create partitions on a block device",
1525    "\
1526 This is a direct interface to the L<sfdisk(8)> program for creating
1527 partitions on block devices.
1528
1529 C<device> should be a block device, for example C</dev/sda>.
1530
1531 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1532 and sectors on the device, which are passed directly to sfdisk as
1533 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1534 of these, then the corresponding parameter is omitted.  Usually for
1535 'large' disks, you can just pass C<0> for these, but for small
1536 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1537 out the right geometry and you will need to tell it.
1538
1539 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1540 information refer to the L<sfdisk(8)> manpage.
1541
1542 To create a single partition occupying the whole disk, you would
1543 pass C<lines> as a single element list, when the single element being
1544 the string C<,> (comma).
1545
1546 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1547 C<guestfs_part_init>");
1548
1549   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1550    (* Regression test for RHBZ#597135. *)
1551    [InitBasicFS, Always, TestLastFail
1552       [["write_file"; "/new"; "abc"; "10000"]]],
1553    "create a file",
1554    "\
1555 This call creates a file called C<path>.  The contents of the
1556 file is the string C<content> (which can contain any 8 bit data),
1557 with length C<size>.
1558
1559 As a special case, if C<size> is C<0>
1560 then the length is calculated using C<strlen> (so in this case
1561 the content cannot contain embedded ASCII NULs).
1562
1563 I<NB.> Owing to a bug, writing content containing ASCII NUL
1564 characters does I<not> work, even if the length is specified.");
1565
1566   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567    [InitEmpty, Always, TestOutputListOfDevices (
1568       [["part_disk"; "/dev/sda"; "mbr"];
1569        ["mkfs"; "ext2"; "/dev/sda1"];
1570        ["mount_options"; ""; "/dev/sda1"; "/"];
1571        ["mounts"]], ["/dev/sda1"]);
1572     InitEmpty, Always, TestOutputList (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["umount"; "/"];
1577        ["mounts"]], [])],
1578    "unmount a filesystem",
1579    "\
1580 This unmounts the given filesystem.  The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1583
1584   ("mounts", (RStringList "devices", []), 46, [],
1585    [InitBasicFS, Always, TestOutputListOfDevices (
1586       [["mounts"]], ["/dev/sda1"])],
1587    "show mounted filesystems",
1588    "\
1589 This returns the list of currently mounted filesystems.  It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1591
1592 Some internal mounts are not shown.
1593
1594 See also: C<guestfs_mountpoints>");
1595
1596   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597    [InitBasicFS, Always, TestOutputList (
1598       [["umount_all"];
1599        ["mounts"]], []);
1600     (* check that umount_all can unmount nested mounts correctly: *)
1601     InitEmpty, Always, TestOutputList (
1602       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603        ["mkfs"; "ext2"; "/dev/sda1"];
1604        ["mkfs"; "ext2"; "/dev/sda2"];
1605        ["mkfs"; "ext2"; "/dev/sda3"];
1606        ["mount_options"; ""; "/dev/sda1"; "/"];
1607        ["mkdir"; "/mp1"];
1608        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609        ["mkdir"; "/mp1/mp2"];
1610        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611        ["mkdir"; "/mp1/mp2/mp3"];
1612        ["umount_all"];
1613        ["mounts"]], [])],
1614    "unmount all filesystems",
1615    "\
1616 This unmounts all mounted filesystems.
1617
1618 Some internal mounts are not unmounted by this call.");
1619
1620   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1621    [],
1622    "remove all LVM LVs, VGs and PVs",
1623    "\
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1626
1627   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628    [InitISOFS, Always, TestOutput (
1629       [["file"; "/empty"]], "empty");
1630     InitISOFS, Always, TestOutput (
1631       [["file"; "/known-1"]], "ASCII text");
1632     InitISOFS, Always, TestLastFail (
1633       [["file"; "/notexists"]]);
1634     InitISOFS, Always, TestOutput (
1635       [["file"; "/abssymlink"]], "symbolic link");
1636     InitISOFS, Always, TestOutput (
1637       [["file"; "/directory"]], "directory")],
1638    "determine file type",
1639    "\
1640 This call uses the standard L<file(1)> command to determine
1641 the type or contents of the file.
1642
1643 This call will also transparently look inside various types
1644 of compressed file.
1645
1646 The exact command which runs is C<file -zb path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).
1649
1650 This command can also be used on C</dev/> devices
1651 (and partitions, LV names).  You can for example use this
1652 to determine if a device contains a filesystem, although
1653 it's usually better to use C<guestfs_vfs_type>.
1654
1655 If the C<path> does not begin with C</dev/> then
1656 this command only works for the content of regular files.
1657 For other file types (directory, symbolic link etc) it
1658 will just return the string C<directory> etc.");
1659
1660   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1661    [InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 1"]], "Result1");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 2"]], "Result2\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 3"]], "\nResult3");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 4"]], "\nResult4\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 5"]], "\nResult5\n\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 7"]], "");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 8"]], "\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 9"]], "\n\n");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1701     InitBasicFS, Always, TestOutput (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1705     InitBasicFS, Always, TestLastFail (
1706       [["upload"; "test-command"; "/test-command"];
1707        ["chmod"; "0o755"; "/test-command"];
1708        ["command"; "/test-command"]])],
1709    "run a command from the guest filesystem",
1710    "\
1711 This call runs a command from the guest filesystem.  The
1712 filesystem must be mounted, and must contain a compatible
1713 operating system (ie. something Linux, with the same
1714 or compatible processor architecture).
1715
1716 The single parameter is an argv-style list of arguments.
1717 The first element is the name of the program to run.
1718 Subsequent elements are parameters.  The list must be
1719 non-empty (ie. must contain a program name).  Note that
1720 the command runs directly, and is I<not> invoked via
1721 the shell (see C<guestfs_sh>).
1722
1723 The return value is anything printed to I<stdout> by
1724 the command.
1725
1726 If the command returns a non-zero exit status, then
1727 this function returns an error message.  The error message
1728 string is the content of I<stderr> from the command.
1729
1730 The C<$PATH> environment variable will contain at least
1731 C</usr/bin> and C</bin>.  If you require a program from
1732 another location, you should provide the full path in the
1733 first parameter.
1734
1735 Shared libraries and data files required by the program
1736 must be available on filesystems which are mounted in the
1737 correct places.  It is the caller's responsibility to ensure
1738 all filesystems that are needed are mounted at the right
1739 locations.");
1740
1741   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1742    [InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 1"]], ["Result1"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 2"]], ["Result2"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 7"]], []);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 8"]], [""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 9"]], ["";""]);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1782     InitBasicFS, Always, TestOutputList (
1783       [["upload"; "test-command"; "/test-command"];
1784        ["chmod"; "0o755"; "/test-command"];
1785        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1786    "run a command, returning lines",
1787    "\
1788 This is the same as C<guestfs_command>, but splits the
1789 result into a list of lines.
1790
1791 See also: C<guestfs_sh_lines>");
1792
1793   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1796    "get file information",
1797    "\
1798 Returns file information for the given C<path>.
1799
1800 This is the same as the C<stat(2)> system call.");
1801
1802   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1803    [InitISOFS, Always, TestOutputStruct (
1804       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1805    "get file information for a symbolic link",
1806    "\
1807 Returns file information for the given C<path>.
1808
1809 This is the same as C<guestfs_stat> except that if C<path>
1810 is a symbolic link, then the link is stat-ed, not the file it
1811 refers to.
1812
1813 This is the same as the C<lstat(2)> system call.");
1814
1815   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1816    [InitISOFS, Always, TestOutputStruct (
1817       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1818    "get file system statistics",
1819    "\
1820 Returns file system statistics for any mounted file system.
1821 C<path> should be a file or directory in the mounted file system
1822 (typically it is the mount point itself, but it doesn't need to be).
1823
1824 This is the same as the C<statvfs(2)> system call.");
1825
1826   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1827    [], (* XXX test *)
1828    "get ext2/ext3/ext4 superblock details",
1829    "\
1830 This returns the contents of the ext2, ext3 or ext4 filesystem
1831 superblock on C<device>.
1832
1833 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1834 manpage for more details.  The list of fields returned isn't
1835 clearly defined, and depends on both the version of C<tune2fs>
1836 that libguestfs was built against, and the filesystem itself.");
1837
1838   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1839    [InitEmpty, Always, TestOutputTrue (
1840       [["blockdev_setro"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-only",
1843    "\
1844 Sets the block device named C<device> to read-only.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1849    [InitEmpty, Always, TestOutputFalse (
1850       [["blockdev_setrw"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "set block device to read-write",
1853    "\
1854 Sets the block device named C<device> to read-write.
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1859    [InitEmpty, Always, TestOutputTrue (
1860       [["blockdev_setro"; "/dev/sda"];
1861        ["blockdev_getro"; "/dev/sda"]])],
1862    "is block device set to read-only",
1863    "\
1864 Returns a boolean indicating if the block device is read-only
1865 (true if read-only, false if not).
1866
1867 This uses the L<blockdev(8)> command.");
1868
1869   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1870    [InitEmpty, Always, TestOutputInt (
1871       [["blockdev_getss"; "/dev/sda"]], 512)],
1872    "get sectorsize of block device",
1873    "\
1874 This returns the size of sectors on a block device.
1875 Usually 512, but can be larger for modern devices.
1876
1877 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1878 for that).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1885    "get blocksize of block device",
1886    "\
1887 This returns the block size of a device.
1888
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1891
1892 This uses the L<blockdev(8)> command.");
1893
1894   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1895    [], (* XXX test *)
1896    "set blocksize of block device",
1897    "\
1898 This sets the block size of a device.
1899
1900 (Note this is different from both I<size in blocks> and
1901 I<filesystem block size>).
1902
1903 This uses the L<blockdev(8)> command.");
1904
1905   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1906    [InitEmpty, Always, TestOutputInt (
1907       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1908    "get total size of device in 512-byte sectors",
1909    "\
1910 This returns the size of the device in units of 512-byte sectors
1911 (even if the sectorsize isn't 512 bytes ... weird).
1912
1913 See also C<guestfs_blockdev_getss> for the real sector size of
1914 the device, and C<guestfs_blockdev_getsize64> for the more
1915 useful I<size in bytes>.
1916
1917 This uses the L<blockdev(8)> command.");
1918
1919   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1920    [InitEmpty, Always, TestOutputInt (
1921       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1922    "get total size of device in bytes",
1923    "\
1924 This returns the size of the device in bytes.
1925
1926 See also C<guestfs_blockdev_getsz>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_flushbufs"; "/dev/sda"]]],
1933    "flush device buffers",
1934    "\
1935 This tells the kernel to flush internal buffers associated
1936 with C<device>.
1937
1938 This uses the L<blockdev(8)> command.");
1939
1940   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1941    [InitEmpty, Always, TestRun
1942       [["blockdev_rereadpt"; "/dev/sda"]]],
1943    "reread partition table",
1944    "\
1945 Reread the partition table on C<device>.
1946
1947 This uses the L<blockdev(8)> command.");
1948
1949   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1950    [InitBasicFS, Always, TestOutput (
1951       (* Pick a file from cwd which isn't likely to change. *)
1952       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1953        ["checksum"; "md5"; "/COPYING.LIB"]],
1954       Digest.to_hex (Digest.file "COPYING.LIB"))],
1955    "upload a file from the local machine",
1956    "\
1957 Upload local file C<filename> to C<remotefilename> on the
1958 filesystem.
1959
1960 C<filename> can also be a named pipe.
1961
1962 See also C<guestfs_download>.");
1963
1964   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1965    [InitBasicFS, Always, TestOutput (
1966       (* Pick a file from cwd which isn't likely to change. *)
1967       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1968        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1969        ["upload"; "testdownload.tmp"; "/upload"];
1970        ["checksum"; "md5"; "/upload"]],
1971       Digest.to_hex (Digest.file "COPYING.LIB"))],
1972    "download a file to the local machine",
1973    "\
1974 Download file C<remotefilename> and save it as C<filename>
1975 on the local machine.
1976
1977 C<filename> can also be a named pipe.
1978
1979 See also C<guestfs_upload>, C<guestfs_cat>.");
1980
1981   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1982    [InitISOFS, Always, TestOutput (
1983       [["checksum"; "crc"; "/known-3"]], "2891671662");
1984     InitISOFS, Always, TestLastFail (
1985       [["checksum"; "crc"; "/notexists"]]);
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1998     (* Test for RHBZ#579608, absolute symbolic links. *)
1999     InitISOFS, Always, TestOutput (
2000       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2001    "compute MD5, SHAx or CRC checksum of file",
2002    "\
2003 This call computes the MD5, SHAx or CRC checksum of the
2004 file named C<path>.
2005
2006 The type of checksum to compute is given by the C<csumtype>
2007 parameter which must have one of the following values:
2008
2009 =over 4
2010
2011 =item C<crc>
2012
2013 Compute the cyclic redundancy check (CRC) specified by POSIX
2014 for the C<cksum> command.
2015
2016 =item C<md5>
2017
2018 Compute the MD5 hash (using the C<md5sum> program).
2019
2020 =item C<sha1>
2021
2022 Compute the SHA1 hash (using the C<sha1sum> program).
2023
2024 =item C<sha224>
2025
2026 Compute the SHA224 hash (using the C<sha224sum> program).
2027
2028 =item C<sha256>
2029
2030 Compute the SHA256 hash (using the C<sha256sum> program).
2031
2032 =item C<sha384>
2033
2034 Compute the SHA384 hash (using the C<sha384sum> program).
2035
2036 =item C<sha512>
2037
2038 Compute the SHA512 hash (using the C<sha512sum> program).
2039
2040 =back
2041
2042 The checksum is returned as a printable string.
2043
2044 To get the checksum for a device, use C<guestfs_checksum_device>.
2045
2046 To get the checksums for many files, use C<guestfs_checksums_out>.");
2047
2048   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2049    [InitBasicFS, Always, TestOutput (
2050       [["tar_in"; "../images/helloworld.tar"; "/"];
2051        ["cat"; "/hello"]], "hello\n")],
2052    "unpack tarfile to directory",
2053    "\
2054 This command uploads and unpacks local file C<tarfile> (an
2055 I<uncompressed> tar file) into C<directory>.
2056
2057 To upload a compressed tarball, use C<guestfs_tgz_in>
2058 or C<guestfs_txz_in>.");
2059
2060   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2061    [],
2062    "pack directory into tarfile",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarfile>.
2066
2067 To download a compressed tarball, use C<guestfs_tgz_out>
2068 or C<guestfs_txz_out>.");
2069
2070   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2071    [InitBasicFS, Always, TestOutput (
2072       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2073        ["cat"; "/hello"]], "hello\n")],
2074    "unpack compressed tarball to directory",
2075    "\
2076 This command uploads and unpacks local file C<tarball> (a
2077 I<gzip compressed> tar file) into C<directory>.
2078
2079 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2080
2081   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2082    [],
2083    "pack directory into compressed tarball",
2084    "\
2085 This command packs the contents of C<directory> and downloads
2086 it to local file C<tarball>.
2087
2088 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2089
2090   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2091    [InitBasicFS, Always, TestLastFail (
2092       [["umount"; "/"];
2093        ["mount_ro"; "/dev/sda1"; "/"];
2094        ["touch"; "/new"]]);
2095     InitBasicFS, Always, TestOutput (
2096       [["write"; "/new"; "data"];
2097        ["umount"; "/"];
2098        ["mount_ro"; "/dev/sda1"; "/"];
2099        ["cat"; "/new"]], "data")],
2100    "mount a guest disk, read-only",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 mounts the filesystem with the read-only (I<-o ro>) flag.");
2104
2105   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2106    [],
2107    "mount a guest disk with mount options",
2108    "\
2109 This is the same as the C<guestfs_mount> command, but it
2110 allows you to set the mount options as for the
2111 L<mount(8)> I<-o> flag.
2112
2113 If the C<options> parameter is an empty string, then
2114 no options are passed (all options default to whatever
2115 the filesystem uses).");
2116
2117   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2118    [],
2119    "mount a guest disk with mount options and vfstype",
2120    "\
2121 This is the same as the C<guestfs_mount> command, but it
2122 allows you to set both the mount options and the vfstype
2123 as for the L<mount(8)> I<-o> and I<-t> flags.");
2124
2125   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2126    [],
2127    "debugging and internals",
2128    "\
2129 The C<guestfs_debug> command exposes some internals of
2130 C<guestfsd> (the guestfs daemon) that runs inside the
2131 qemu subprocess.
2132
2133 There is no comprehensive help for this command.  You have
2134 to look at the file C<daemon/debug.c> in the libguestfs source
2135 to find out what you can do.");
2136
2137   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["lvremove"; "/dev/VG/LV1"];
2145        ["lvs"]], ["/dev/VG/LV2"]);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["lvremove"; "/dev/VG"];
2153        ["lvs"]], []);
2154     InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["lvremove"; "/dev/VG"];
2161        ["vgs"]], ["VG"])],
2162    "remove an LVM logical volume",
2163    "\
2164 Remove an LVM logical volume C<device>, where C<device> is
2165 the path to the LV, such as C</dev/VG/LV>.
2166
2167 You can also remove all LVs in a volume group by specifying
2168 the VG name, C</dev/VG>.");
2169
2170   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2171    [InitEmpty, Always, TestOutputList (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["lvs"]], []);
2179     InitEmpty, Always, TestOutputList (
2180       [["part_disk"; "/dev/sda"; "mbr"];
2181        ["pvcreate"; "/dev/sda1"];
2182        ["vgcreate"; "VG"; "/dev/sda1"];
2183        ["lvcreate"; "LV1"; "VG"; "50"];
2184        ["lvcreate"; "LV2"; "VG"; "50"];
2185        ["vgremove"; "VG"];
2186        ["vgs"]], [])],
2187    "remove an LVM volume group",
2188    "\
2189 Remove an LVM volume group C<vgname>, (for example C<VG>).
2190
2191 This also forcibly removes all logical volumes in the volume
2192 group (if any).");
2193
2194   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2195    [InitEmpty, Always, TestOutputListOfDevices (
2196       [["part_disk"; "/dev/sda"; "mbr"];
2197        ["pvcreate"; "/dev/sda1"];
2198        ["vgcreate"; "VG"; "/dev/sda1"];
2199        ["lvcreate"; "LV1"; "VG"; "50"];
2200        ["lvcreate"; "LV2"; "VG"; "50"];
2201        ["vgremove"; "VG"];
2202        ["pvremove"; "/dev/sda1"];
2203        ["lvs"]], []);
2204     InitEmpty, Always, TestOutputListOfDevices (
2205       [["part_disk"; "/dev/sda"; "mbr"];
2206        ["pvcreate"; "/dev/sda1"];
2207        ["vgcreate"; "VG"; "/dev/sda1"];
2208        ["lvcreate"; "LV1"; "VG"; "50"];
2209        ["lvcreate"; "LV2"; "VG"; "50"];
2210        ["vgremove"; "VG"];
2211        ["pvremove"; "/dev/sda1"];
2212        ["vgs"]], []);
2213     InitEmpty, Always, TestOutputListOfDevices (
2214       [["part_disk"; "/dev/sda"; "mbr"];
2215        ["pvcreate"; "/dev/sda1"];
2216        ["vgcreate"; "VG"; "/dev/sda1"];
2217        ["lvcreate"; "LV1"; "VG"; "50"];
2218        ["lvcreate"; "LV2"; "VG"; "50"];
2219        ["vgremove"; "VG"];
2220        ["pvremove"; "/dev/sda1"];
2221        ["pvs"]], [])],
2222    "remove an LVM physical volume",
2223    "\
2224 This wipes a physical volume C<device> so that LVM will no longer
2225 recognise it.
2226
2227 The implementation uses the C<pvremove> command which refuses to
2228 wipe physical volumes that contain any volume groups, so you have
2229 to remove those first.");
2230
2231   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2232    [InitBasicFS, Always, TestOutput (
2233       [["set_e2label"; "/dev/sda1"; "testlabel"];
2234        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2235    "set the ext2/3/4 filesystem label",
2236    "\
2237 This sets the ext2/3/4 filesystem label of the filesystem on
2238 C<device> to C<label>.  Filesystem labels are limited to
2239 16 characters.
2240
2241 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2242 to return the existing label on a filesystem.");
2243
2244   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2245    [],
2246    "get the ext2/3/4 filesystem label",
2247    "\
2248 This returns the ext2/3/4 filesystem label of the filesystem on
2249 C<device>.");
2250
2251   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2252    (let uuid = uuidgen () in
2253     [InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; uuid];
2255         ["get_e2uuid"; "/dev/sda1"]], uuid);
2256      InitBasicFS, Always, TestOutput (
2257        [["set_e2uuid"; "/dev/sda1"; "clear"];
2258         ["get_e2uuid"; "/dev/sda1"]], "");
2259      (* We can't predict what UUIDs will be, so just check the commands run. *)
2260      InitBasicFS, Always, TestRun (
2261        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2262      InitBasicFS, Always, TestRun (
2263        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2264    "set the ext2/3/4 filesystem UUID",
2265    "\
2266 This sets the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device> to C<uuid>.  The format of the UUID and alternatives
2268 such as C<clear>, C<random> and C<time> are described in the
2269 L<tune2fs(8)> manpage.
2270
2271 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2272 to return the existing UUID of a filesystem.");
2273
2274   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2275    (* Regression test for RHBZ#597112. *)
2276    (let uuid = uuidgen () in
2277     [InitBasicFS, Always, TestOutput (
2278        [["mke2journal"; "1024"; "/dev/sdb"];
2279         ["set_e2uuid"; "/dev/sdb"; uuid];
2280         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2281    "get the ext2/3/4 filesystem UUID",
2282    "\
2283 This returns the ext2/3/4 filesystem UUID of the filesystem on
2284 C<device>.");
2285
2286   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2287    [InitBasicFS, Always, TestOutputInt (
2288       [["umount"; "/dev/sda1"];
2289        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2290     InitBasicFS, Always, TestOutputInt (
2291       [["umount"; "/dev/sda1"];
2292        ["zero"; "/dev/sda1"];
2293        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2294    "run the filesystem checker",
2295    "\
2296 This runs the filesystem checker (fsck) on C<device> which
2297 should have filesystem type C<fstype>.
2298
2299 The returned integer is the status.  See L<fsck(8)> for the
2300 list of status codes from C<fsck>.
2301
2302 Notes:
2303
2304 =over 4
2305
2306 =item *
2307
2308 Multiple status codes can be summed together.
2309
2310 =item *
2311
2312 A non-zero return code can mean \"success\", for example if
2313 errors have been corrected on the filesystem.
2314
2315 =item *
2316
2317 Checking or repairing NTFS volumes is not supported
2318 (by linux-ntfs).
2319
2320 =back
2321
2322 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2323
2324   ("zero", (RErr, [Device "device"]), 85, [],
2325    [InitBasicFS, Always, TestOutput (
2326       [["umount"; "/dev/sda1"];
2327        ["zero"; "/dev/sda1"];
2328        ["file"; "/dev/sda1"]], "data")],
2329    "write zeroes to the device",
2330    "\
2331 This command writes zeroes over the first few blocks of C<device>.
2332
2333 How many blocks are zeroed isn't specified (but it's I<not> enough
2334 to securely wipe the device).  It should be sufficient to remove
2335 any partition tables, filesystem superblocks and so on.
2336
2337 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2338
2339   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2340    (* See:
2341     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2342     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2343     *)
2344    [InitBasicFS, Always, TestOutputTrue (
2345       [["mkdir_p"; "/boot/grub"];
2346        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2347        ["grub_install"; "/"; "/dev/vda"];
2348        ["is_dir"; "/boot"]])],
2349    "install GRUB",
2350    "\
2351 This command installs GRUB (the Grand Unified Bootloader) on
2352 C<device>, with the root directory being C<root>.
2353
2354 Note: If grub-install reports the error
2355 \"No suitable drive was found in the generated device map.\"
2356 it may be that you need to create a C</boot/grub/device.map>
2357 file first that contains the mapping between grub device names
2358 and Linux device names.  It is usually sufficient to create
2359 a file containing:
2360
2361  (hd0) /dev/vda
2362
2363 replacing C</dev/vda> with the name of the installation device.");
2364
2365   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2366    [InitBasicFS, Always, TestOutput (
2367       [["write"; "/old"; "file content"];
2368        ["cp"; "/old"; "/new"];
2369        ["cat"; "/new"]], "file content");
2370     InitBasicFS, Always, TestOutputTrue (
2371       [["write"; "/old"; "file content"];
2372        ["cp"; "/old"; "/new"];
2373        ["is_file"; "/old"]]);
2374     InitBasicFS, Always, TestOutput (
2375       [["write"; "/old"; "file content"];
2376        ["mkdir"; "/dir"];
2377        ["cp"; "/old"; "/dir/new"];
2378        ["cat"; "/dir/new"]], "file content")],
2379    "copy a file",
2380    "\
2381 This copies a file from C<src> to C<dest> where C<dest> is
2382 either a destination filename or destination directory.");
2383
2384   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2385    [InitBasicFS, Always, TestOutput (
2386       [["mkdir"; "/olddir"];
2387        ["mkdir"; "/newdir"];
2388        ["write"; "/olddir/file"; "file content"];
2389        ["cp_a"; "/olddir"; "/newdir"];
2390        ["cat"; "/newdir/olddir/file"]], "file content")],
2391    "copy a file or directory recursively",
2392    "\
2393 This copies a file or directory from C<src> to C<dest>
2394 recursively using the C<cp -a> command.");
2395
2396   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2397    [InitBasicFS, Always, TestOutput (
2398       [["write"; "/old"; "file content"];
2399        ["mv"; "/old"; "/new"];
2400        ["cat"; "/new"]], "file content");
2401     InitBasicFS, Always, TestOutputFalse (
2402       [["write"; "/old"; "file content"];
2403        ["mv"; "/old"; "/new"];
2404        ["is_file"; "/old"]])],
2405    "move a file",
2406    "\
2407 This moves a file from C<src> to C<dest> where C<dest> is
2408 either a destination filename or destination directory.");
2409
2410   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2411    [InitEmpty, Always, TestRun (
2412       [["drop_caches"; "3"]])],
2413    "drop kernel page cache, dentries and inodes",
2414    "\
2415 This instructs the guest kernel to drop its page cache,
2416 and/or dentries and inode caches.  The parameter C<whattodrop>
2417 tells the kernel what precisely to drop, see
2418 L<http://linux-mm.org/Drop_Caches>
2419
2420 Setting C<whattodrop> to 3 should drop everything.
2421
2422 This automatically calls L<sync(2)> before the operation,
2423 so that the maximum guest memory is freed.");
2424
2425   ("dmesg", (RString "kmsgs", []), 91, [],
2426    [InitEmpty, Always, TestRun (
2427       [["dmesg"]])],
2428    "return kernel messages",
2429    "\
2430 This returns the kernel messages (C<dmesg> output) from
2431 the guest kernel.  This is sometimes useful for extended
2432 debugging of problems.
2433
2434 Another way to get the same information is to enable
2435 verbose messages with C<guestfs_set_verbose> or by setting
2436 the environment variable C<LIBGUESTFS_DEBUG=1> before
2437 running the program.");
2438
2439   ("ping_daemon", (RErr, []), 92, [],
2440    [InitEmpty, Always, TestRun (
2441       [["ping_daemon"]])],
2442    "ping the guest daemon",
2443    "\
2444 This is a test probe into the guestfs daemon running inside
2445 the qemu subprocess.  Calling this function checks that the
2446 daemon responds to the ping message, without affecting the daemon
2447 or attached block device(s) in any other way.");
2448
2449   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2450    [InitBasicFS, Always, TestOutputTrue (
2451       [["write"; "/file1"; "contents of a file"];
2452        ["cp"; "/file1"; "/file2"];
2453        ["equal"; "/file1"; "/file2"]]);
2454     InitBasicFS, Always, TestOutputFalse (
2455       [["write"; "/file1"; "contents of a file"];
2456        ["write"; "/file2"; "contents of another file"];
2457        ["equal"; "/file1"; "/file2"]]);
2458     InitBasicFS, Always, TestLastFail (
2459       [["equal"; "/file1"; "/file2"]])],
2460    "test if two files have equal contents",
2461    "\
2462 This compares the two files C<file1> and C<file2> and returns
2463 true if their content is exactly equal, or false otherwise.
2464
2465 The external L<cmp(1)> program is used for the comparison.");
2466
2467   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2468    [InitISOFS, Always, TestOutputList (
2469       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2470     InitISOFS, Always, TestOutputList (
2471       [["strings"; "/empty"]], []);
2472     (* Test for RHBZ#579608, absolute symbolic links. *)
2473     InitISOFS, Always, TestRun (
2474       [["strings"; "/abssymlink"]])],
2475    "print the printable strings in a file",
2476    "\
2477 This runs the L<strings(1)> command on a file and returns
2478 the list of printable strings found.");
2479
2480   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2481    [InitISOFS, Always, TestOutputList (
2482       [["strings_e"; "b"; "/known-5"]], []);
2483     InitBasicFS, Always, TestOutputList (
2484       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2485        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2486    "print the printable strings in a file",
2487    "\
2488 This is like the C<guestfs_strings> command, but allows you to
2489 specify the encoding of strings that are looked for in
2490 the source file C<path>.
2491
2492 Allowed encodings are:
2493
2494 =over 4
2495
2496 =item s
2497
2498 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2499 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2500
2501 =item S
2502
2503 Single 8-bit-byte characters.
2504
2505 =item b
2506
2507 16-bit big endian strings such as those encoded in
2508 UTF-16BE or UCS-2BE.
2509
2510 =item l (lower case letter L)
2511
2512 16-bit little endian such as UTF-16LE and UCS-2LE.
2513 This is useful for examining binaries in Windows guests.
2514
2515 =item B
2516
2517 32-bit big endian such as UCS-4BE.
2518
2519 =item L
2520
2521 32-bit little endian such as UCS-4LE.
2522
2523 =back
2524
2525 The returned strings are transcoded to UTF-8.");
2526
2527   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2528    [InitISOFS, Always, TestOutput (
2529       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2530     (* Test for RHBZ#501888c2 regression which caused large hexdump
2531      * commands to segfault.
2532      *)
2533     InitISOFS, Always, TestRun (
2534       [["hexdump"; "/100krandom"]]);
2535     (* Test for RHBZ#579608, absolute symbolic links. *)
2536     InitISOFS, Always, TestRun (
2537       [["hexdump"; "/abssymlink"]])],
2538    "dump a file in hexadecimal",
2539    "\
2540 This runs C<hexdump -C> on the given C<path>.  The result is
2541 the human-readable, canonical hex dump of the file.");
2542
2543   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2544    [InitNone, Always, TestOutput (
2545       [["part_disk"; "/dev/sda"; "mbr"];
2546        ["mkfs"; "ext3"; "/dev/sda1"];
2547        ["mount_options"; ""; "/dev/sda1"; "/"];
2548        ["write"; "/new"; "test file"];
2549        ["umount"; "/dev/sda1"];
2550        ["zerofree"; "/dev/sda1"];
2551        ["mount_options"; ""; "/dev/sda1"; "/"];
2552        ["cat"; "/new"]], "test file")],
2553    "zero unused inodes and disk blocks on ext2/3 filesystem",
2554    "\
2555 This runs the I<zerofree> program on C<device>.  This program
2556 claims to zero unused inodes and disk blocks on an ext2/3
2557 filesystem, thus making it possible to compress the filesystem
2558 more effectively.
2559
2560 You should B<not> run this program if the filesystem is
2561 mounted.
2562
2563 It is possible that using this program can damage the filesystem
2564 or data on the filesystem.");
2565
2566   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2567    [],
2568    "resize an LVM physical volume",
2569    "\
2570 This resizes (expands or shrinks) an existing LVM physical
2571 volume to match the new size of the underlying device.");
2572
2573   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2574                        Int "cyls"; Int "heads"; Int "sectors";
2575                        String "line"]), 99, [DangerWillRobinson],
2576    [],
2577    "modify a single partition on a block device",
2578    "\
2579 This runs L<sfdisk(8)> option to modify just the single
2580 partition C<n> (note: C<n> counts from 1).
2581
2582 For other parameters, see C<guestfs_sfdisk>.  You should usually
2583 pass C<0> for the cyls/heads/sectors parameters.
2584
2585 See also: C<guestfs_part_add>");
2586
2587   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2588    [],
2589    "display the partition table",
2590    "\
2591 This displays the partition table on C<device>, in the
2592 human-readable output of the L<sfdisk(8)> command.  It is
2593 not intended to be parsed.
2594
2595 See also: C<guestfs_part_list>");
2596
2597   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2598    [],
2599    "display the kernel geometry",
2600    "\
2601 This displays the kernel's idea of the geometry of C<device>.
2602
2603 The result is in human-readable format, and not designed to
2604 be parsed.");
2605
2606   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2607    [],
2608    "display the disk geometry from the partition table",
2609    "\
2610 This displays the disk geometry of C<device> read from the
2611 partition table.  Especially in the case where the underlying
2612 block device has been resized, this can be different from the
2613 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2614
2615 The result is in human-readable format, and not designed to
2616 be parsed.");
2617
2618   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2619    [],
2620    "activate or deactivate all volume groups",
2621    "\
2622 This command activates or (if C<activate> is false) deactivates
2623 all logical volumes in all volume groups.
2624 If activated, then they are made known to the
2625 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2626 then those devices disappear.
2627
2628 This command is the same as running C<vgchange -a y|n>");
2629
2630   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2631    [],
2632    "activate or deactivate some volume groups",
2633    "\
2634 This command activates or (if C<activate> is false) deactivates
2635 all logical volumes in the listed volume groups C<volgroups>.
2636 If activated, then they are made known to the
2637 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2638 then those devices disappear.
2639
2640 This command is the same as running C<vgchange -a y|n volgroups...>
2641
2642 Note that if C<volgroups> is an empty list then B<all> volume groups
2643 are activated or deactivated.");
2644
2645   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2646    [InitNone, Always, TestOutput (
2647       [["part_disk"; "/dev/sda"; "mbr"];
2648        ["pvcreate"; "/dev/sda1"];
2649        ["vgcreate"; "VG"; "/dev/sda1"];
2650        ["lvcreate"; "LV"; "VG"; "10"];
2651        ["mkfs"; "ext2"; "/dev/VG/LV"];
2652        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2653        ["write"; "/new"; "test content"];
2654        ["umount"; "/"];
2655        ["lvresize"; "/dev/VG/LV"; "20"];
2656        ["e2fsck_f"; "/dev/VG/LV"];
2657        ["resize2fs"; "/dev/VG/LV"];
2658        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2659        ["cat"; "/new"]], "test content");
2660     InitNone, Always, TestRun (
2661       (* Make an LV smaller to test RHBZ#587484. *)
2662       [["part_disk"; "/dev/sda"; "mbr"];
2663        ["pvcreate"; "/dev/sda1"];
2664        ["vgcreate"; "VG"; "/dev/sda1"];
2665        ["lvcreate"; "LV"; "VG"; "20"];
2666        ["lvresize"; "/dev/VG/LV"; "10"]])],
2667    "resize an LVM logical volume",
2668    "\
2669 This resizes (expands or shrinks) an existing LVM logical
2670 volume to C<mbytes>.  When reducing, data in the reduced part
2671 is lost.");
2672
2673   ("resize2fs", (RErr, [Device "device"]), 106, [],
2674    [], (* lvresize tests this *)
2675    "resize an ext2, ext3 or ext4 filesystem",
2676    "\
2677 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2678 the underlying device.
2679
2680 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2681 on the C<device> before calling this command.  For unknown reasons
2682 C<resize2fs> sometimes gives an error about this and sometimes not.
2683 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2684 calling this function.");
2685
2686   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2687    [InitBasicFS, Always, TestOutputList (
2688       [["find"; "/"]], ["lost+found"]);
2689     InitBasicFS, Always, TestOutputList (
2690       [["touch"; "/a"];
2691        ["mkdir"; "/b"];
2692        ["touch"; "/b/c"];
2693        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2694     InitBasicFS, Always, TestOutputList (
2695       [["mkdir_p"; "/a/b/c"];
2696        ["touch"; "/a/b/c/d"];
2697        ["find"; "/a/b/"]], ["c"; "c/d"])],
2698    "find all files and directories",
2699    "\
2700 This command lists out all files and directories, recursively,
2701 starting at C<directory>.  It is essentially equivalent to
2702 running the shell command C<find directory -print> but some
2703 post-processing happens on the output, described below.
2704
2705 This returns a list of strings I<without any prefix>.  Thus
2706 if the directory structure was:
2707
2708  /tmp/a
2709  /tmp/b
2710  /tmp/c/d
2711
2712 then the returned list from C<guestfs_find> C</tmp> would be
2713 4 elements:
2714
2715  a
2716  b
2717  c
2718  c/d
2719
2720 If C<directory> is not a directory, then this command returns
2721 an error.
2722
2723 The returned list is sorted.
2724
2725 See also C<guestfs_find0>.");
2726
2727   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2728    [], (* lvresize tests this *)
2729    "check an ext2/ext3 filesystem",
2730    "\
2731 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2732 filesystem checker on C<device>, noninteractively (C<-p>),
2733 even if the filesystem appears to be clean (C<-f>).
2734
2735 This command is only needed because of C<guestfs_resize2fs>
2736 (q.v.).  Normally you should use C<guestfs_fsck>.");
2737
2738   ("sleep", (RErr, [Int "secs"]), 109, [],
2739    [InitNone, Always, TestRun (
2740       [["sleep"; "1"]])],
2741    "sleep for some seconds",
2742    "\
2743 Sleep for C<secs> seconds.");
2744
2745   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2746    [InitNone, Always, TestOutputInt (
2747       [["part_disk"; "/dev/sda"; "mbr"];
2748        ["mkfs"; "ntfs"; "/dev/sda1"];
2749        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2750     InitNone, Always, TestOutputInt (
2751       [["part_disk"; "/dev/sda"; "mbr"];
2752        ["mkfs"; "ext2"; "/dev/sda1"];
2753        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2754    "probe NTFS volume",
2755    "\
2756 This command runs the L<ntfs-3g.probe(8)> command which probes
2757 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2758 be mounted read-write, and some cannot be mounted at all).
2759
2760 C<rw> is a boolean flag.  Set it to true if you want to test
2761 if the volume can be mounted read-write.  Set it to false if
2762 you want to test if the volume can be mounted read-only.
2763
2764 The return value is an integer which C<0> if the operation
2765 would succeed, or some non-zero value documented in the
2766 L<ntfs-3g.probe(8)> manual page.");
2767
2768   ("sh", (RString "output", [String "command"]), 111, [],
2769    [], (* XXX needs tests *)
2770    "run a command via the shell",
2771    "\
2772 This call runs a command from the guest filesystem via the
2773 guest's C</bin/sh>.
2774
2775 This is like C<guestfs_command>, but passes the command to:
2776
2777  /bin/sh -c \"command\"
2778
2779 Depending on the guest's shell, this usually results in
2780 wildcards being expanded, shell expressions being interpolated
2781 and so on.
2782
2783 All the provisos about C<guestfs_command> apply to this call.");
2784
2785   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2786    [], (* XXX needs tests *)
2787    "run a command via the shell returning lines",
2788    "\
2789 This is the same as C<guestfs_sh>, but splits the result
2790 into a list of lines.
2791
2792 See also: C<guestfs_command_lines>");
2793
2794   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2795    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2796     * code in stubs.c, since all valid glob patterns must start with "/".
2797     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2798     *)
2799    [InitBasicFS, Always, TestOutputList (
2800       [["mkdir_p"; "/a/b/c"];
2801        ["touch"; "/a/b/c/d"];
2802        ["touch"; "/a/b/c/e"];
2803        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2804     InitBasicFS, Always, TestOutputList (
2805       [["mkdir_p"; "/a/b/c"];
2806        ["touch"; "/a/b/c/d"];
2807        ["touch"; "/a/b/c/e"];
2808        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809     InitBasicFS, Always, TestOutputList (
2810       [["mkdir_p"; "/a/b/c"];
2811        ["touch"; "/a/b/c/d"];
2812        ["touch"; "/a/b/c/e"];
2813        ["glob_expand"; "/a/*/x/*"]], [])],
2814    "expand a wildcard path",
2815    "\
2816 This command searches for all the pathnames matching
2817 C<pattern> according to the wildcard expansion rules
2818 used by the shell.
2819
2820 If no paths match, then this returns an empty list
2821 (note: not an error).
2822
2823 It is just a wrapper around the C L<glob(3)> function
2824 with flags C<GLOB_MARK|GLOB_BRACE>.
2825 See that manual page for more details.");
2826
2827   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2828    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2829       [["scrub_device"; "/dev/sdc"]])],
2830    "scrub (securely wipe) a device",
2831    "\
2832 This command writes patterns over C<device> to make data retrieval
2833 more difficult.
2834
2835 It is an interface to the L<scrub(1)> program.  See that
2836 manual page for more details.");
2837
2838   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2839    [InitBasicFS, Always, TestRun (
2840       [["write"; "/file"; "content"];
2841        ["scrub_file"; "/file"]])],
2842    "scrub (securely wipe) a file",
2843    "\
2844 This command writes patterns over a file to make data retrieval
2845 more difficult.
2846
2847 The file is I<removed> after scrubbing.
2848
2849 It is an interface to the L<scrub(1)> program.  See that
2850 manual page for more details.");
2851
2852   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2853    [], (* XXX needs testing *)
2854    "scrub (securely wipe) free space",
2855    "\
2856 This command creates the directory C<dir> and then fills it
2857 with files until the filesystem is full, and scrubs the files
2858 as for C<guestfs_scrub_file>, and deletes them.
2859 The intention is to scrub any free space on the partition
2860 containing C<dir>.
2861
2862 It is an interface to the L<scrub(1)> program.  See that
2863 manual page for more details.");
2864
2865   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2866    [InitBasicFS, Always, TestRun (
2867       [["mkdir"; "/tmp"];
2868        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2869    "create a temporary directory",
2870    "\
2871 This command creates a temporary directory.  The
2872 C<template> parameter should be a full pathname for the
2873 temporary directory name with the final six characters being
2874 \"XXXXXX\".
2875
2876 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2877 the second one being suitable for Windows filesystems.
2878
2879 The name of the temporary directory that was created
2880 is returned.
2881
2882 The temporary directory is created with mode 0700
2883 and is owned by root.
2884
2885 The caller is responsible for deleting the temporary
2886 directory and its contents after use.
2887
2888 See also: L<mkdtemp(3)>");
2889
2890   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2891    [InitISOFS, Always, TestOutputInt (
2892       [["wc_l"; "/10klines"]], 10000);
2893     (* Test for RHBZ#579608, absolute symbolic links. *)
2894     InitISOFS, Always, TestOutputInt (
2895       [["wc_l"; "/abssymlink"]], 10000)],
2896    "count lines in a file",
2897    "\
2898 This command counts the lines in a file, using the
2899 C<wc -l> external command.");
2900
2901   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2902    [InitISOFS, Always, TestOutputInt (
2903       [["wc_w"; "/10klines"]], 10000)],
2904    "count words in a file",
2905    "\
2906 This command counts the words in a file, using the
2907 C<wc -w> external command.");
2908
2909   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2910    [InitISOFS, Always, TestOutputInt (
2911       [["wc_c"; "/100kallspaces"]], 102400)],
2912    "count characters in a file",
2913    "\
2914 This command counts the characters in a file, using the
2915 C<wc -c> external command.");
2916
2917   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2918    [InitISOFS, Always, TestOutputList (
2919       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2920     (* Test for RHBZ#579608, absolute symbolic links. *)
2921     InitISOFS, Always, TestOutputList (
2922       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2923    "return first 10 lines of a file",
2924    "\
2925 This command returns up to the first 10 lines of a file as
2926 a list of strings.");
2927
2928   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2929    [InitISOFS, Always, TestOutputList (
2930       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2931     InitISOFS, Always, TestOutputList (
2932       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933     InitISOFS, Always, TestOutputList (
2934       [["head_n"; "0"; "/10klines"]], [])],
2935    "return first N lines of a file",
2936    "\
2937 If the parameter C<nrlines> is a positive number, this returns the first
2938 C<nrlines> lines of the file C<path>.
2939
2940 If the parameter C<nrlines> is a negative number, this returns lines
2941 from the file C<path>, excluding the last C<nrlines> lines.
2942
2943 If the parameter C<nrlines> is zero, this returns an empty list.");
2944
2945   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2946    [InitISOFS, Always, TestOutputList (
2947       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2948    "return last 10 lines of a file",
2949    "\
2950 This command returns up to the last 10 lines of a file as
2951 a list of strings.");
2952
2953   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2954    [InitISOFS, Always, TestOutputList (
2955       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2956     InitISOFS, Always, TestOutputList (
2957       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958     InitISOFS, Always, TestOutputList (
2959       [["tail_n"; "0"; "/10klines"]], [])],
2960    "return last N lines of a file",
2961    "\
2962 If the parameter C<nrlines> is a positive number, this returns the last
2963 C<nrlines> lines of the file C<path>.
2964
2965 If the parameter C<nrlines> is a negative number, this returns lines
2966 from the file C<path>, starting with the C<-nrlines>th line.
2967
2968 If the parameter C<nrlines> is zero, this returns an empty list.");
2969
2970   ("df", (RString "output", []), 125, [],
2971    [], (* XXX Tricky to test because it depends on the exact format
2972         * of the 'df' command and other imponderables.
2973         *)
2974    "report file system disk space usage",
2975    "\
2976 This command runs the C<df> command to report disk space used.
2977
2978 This command is mostly useful for interactive sessions.  It
2979 is I<not> intended that you try to parse the output string.
2980 Use C<statvfs> from programs.");
2981
2982   ("df_h", (RString "output", []), 126, [],
2983    [], (* XXX Tricky to test because it depends on the exact format
2984         * of the 'df' command and other imponderables.
2985         *)
2986    "report file system disk space usage (human readable)",
2987    "\
2988 This command runs the C<df -h> command to report disk space used
2989 in human-readable format.
2990
2991 This command is mostly useful for interactive sessions.  It
2992 is I<not> intended that you try to parse the output string.
2993 Use C<statvfs> from programs.");
2994
2995   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2996    [InitISOFS, Always, TestOutputInt (
2997       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2998    "estimate file space usage",
2999    "\
3000 This command runs the C<du -s> command to estimate file space
3001 usage for C<path>.
3002
3003 C<path> can be a file or a directory.  If C<path> is a directory
3004 then the estimate includes the contents of the directory and all
3005 subdirectories (recursively).
3006
3007 The result is the estimated size in I<kilobytes>
3008 (ie. units of 1024 bytes).");
3009
3010   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3011    [InitISOFS, Always, TestOutputList (
3012       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3013    "list files in an initrd",
3014    "\
3015 This command lists out files contained in an initrd.
3016
3017 The files are listed without any initial C</> character.  The
3018 files are listed in the order they appear (not necessarily
3019 alphabetical).  Directory names are listed as separate items.
3020
3021 Old Linux kernels (2.4 and earlier) used a compressed ext2
3022 filesystem as initrd.  We I<only> support the newer initramfs
3023 format (compressed cpio files).");
3024
3025   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3026    [],
3027    "mount a file using the loop device",
3028    "\
3029 This command lets you mount C<file> (a filesystem image
3030 in a file) on a mount point.  It is entirely equivalent to
3031 the command C<mount -o loop file mountpoint>.");
3032
3033   ("mkswap", (RErr, [Device "device"]), 130, [],
3034    [InitEmpty, Always, TestRun (
3035       [["part_disk"; "/dev/sda"; "mbr"];
3036        ["mkswap"; "/dev/sda1"]])],
3037    "create a swap partition",
3038    "\
3039 Create a swap partition on C<device>.");
3040
3041   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3042    [InitEmpty, Always, TestRun (
3043       [["part_disk"; "/dev/sda"; "mbr"];
3044        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3045    "create a swap partition with a label",
3046    "\
3047 Create a swap partition on C<device> with label C<label>.
3048
3049 Note that you cannot attach a swap label to a block device
3050 (eg. C</dev/sda>), just to a partition.  This appears to be
3051 a limitation of the kernel or swap tools.");
3052
3053   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3054    (let uuid = uuidgen () in
3055     [InitEmpty, Always, TestRun (
3056        [["part_disk"; "/dev/sda"; "mbr"];
3057         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3058    "create a swap partition with an explicit UUID",
3059    "\
3060 Create a swap partition on C<device> with UUID C<uuid>.");
3061
3062   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3065        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3066        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3067     InitBasicFS, Always, TestOutputStruct (
3068       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3070    "make block, character or FIFO devices",
3071    "\
3072 This call creates block or character special devices, or
3073 named pipes (FIFOs).
3074
3075 The C<mode> parameter should be the mode, using the standard
3076 constants.  C<devmajor> and C<devminor> are the
3077 device major and minor numbers, only used when creating block
3078 and character special devices.
3079
3080 Note that, just like L<mknod(2)>, the mode must be bitwise
3081 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3082 just creates a regular file).  These constants are
3083 available in the standard Linux header files, or you can use
3084 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3085 which are wrappers around this command which bitwise OR
3086 in the appropriate constant for you.
3087
3088 The mode actually set is affected by the umask.");
3089
3090   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3091    [InitBasicFS, Always, TestOutputStruct (
3092       [["mkfifo"; "0o777"; "/node"];
3093        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3094    "make FIFO (named pipe)",
3095    "\
3096 This call creates a FIFO (named pipe) called C<path> with
3097 mode C<mode>.  It is just a convenient wrapper around
3098 C<guestfs_mknod>.
3099
3100 The mode actually set is affected by the umask.");
3101
3102   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3103    [InitBasicFS, Always, TestOutputStruct (
3104       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3105        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3106    "make block device node",
3107    "\
3108 This call creates a block device node called C<path> with
3109 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3110 It is just a convenient wrapper around C<guestfs_mknod>.
3111
3112 The mode actually set is affected by the umask.");
3113
3114   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3115    [InitBasicFS, Always, TestOutputStruct (
3116       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3117        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3118    "make char device node",
3119    "\
3120 This call creates a char device node called C<path> with
3121 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3122 It is just a convenient wrapper around C<guestfs_mknod>.
3123
3124 The mode actually set is affected by the umask.");
3125
3126   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3127    [InitEmpty, Always, TestOutputInt (
3128       [["umask"; "0o22"]], 0o22)],
3129    "set file mode creation mask (umask)",
3130    "\
3131 This function sets the mask used for creating new files and
3132 device nodes to C<mask & 0777>.
3133
3134 Typical umask values would be C<022> which creates new files
3135 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3136 C<002> which creates new files with permissions like
3137 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3138
3139 The default umask is C<022>.  This is important because it
3140 means that directories and device nodes will be created with
3141 C<0644> or C<0755> mode even if you specify C<0777>.
3142
3143 See also C<guestfs_get_umask>,
3144 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3145
3146 This call returns the previous umask.");
3147
3148   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3149    [],
3150    "read directories entries",
3151    "\
3152 This returns the list of directory entries in directory C<dir>.
3153
3154 All entries in the directory are returned, including C<.> and
3155 C<..>.  The entries are I<not> sorted, but returned in the same
3156 order as the underlying filesystem.
3157
3158 Also this call returns basic file type information about each
3159 file.  The C<ftyp> field will contain one of the following characters:
3160
3161 =over 4
3162
3163 =item 'b'
3164
3165 Block special
3166
3167 =item 'c'
3168
3169 Char special
3170
3171 =item 'd'
3172
3173 Directory
3174
3175 =item 'f'
3176
3177 FIFO (named pipe)
3178
3179 =item 'l'
3180
3181 Symbolic link
3182
3183 =item 'r'
3184
3185 Regular file
3186
3187 =item 's'
3188
3189 Socket
3190
3191 =item 'u'
3192
3193 Unknown file type
3194
3195 =item '?'
3196
3197 The L<readdir(3)> call returned a C<d_type> field with an
3198 unexpected value
3199
3200 =back
3201
3202 This function is primarily intended for use by programs.  To
3203 get a simple list of names, use C<guestfs_ls>.  To get a printable
3204 directory for human consumption, use C<guestfs_ll>.");
3205
3206   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3207    [],
3208    "create partitions on a block device",
3209    "\
3210 This is a simplified interface to the C<guestfs_sfdisk>
3211 command, where partition sizes are specified in megabytes
3212 only (rounded to the nearest cylinder) and you don't need
3213 to specify the cyls, heads and sectors parameters which
3214 were rarely if ever used anyway.
3215
3216 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3217 and C<guestfs_part_disk>");
3218
3219   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3220    [],
3221    "determine file type inside a compressed file",
3222    "\
3223 This command runs C<file> after first decompressing C<path>
3224 using C<method>.
3225
3226 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3227
3228 Since 1.0.63, use C<guestfs_file> instead which can now
3229 process compressed files.");
3230
3231   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3232    [],
3233    "list extended attributes of a file or directory",
3234    "\
3235 This call lists the extended attributes of the file or directory
3236 C<path>.
3237
3238 At the system call level, this is a combination of the
3239 L<listxattr(2)> and L<getxattr(2)> calls.
3240
3241 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3242
3243   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3244    [],
3245    "list extended attributes of a file or directory",
3246    "\
3247 This is the same as C<guestfs_getxattrs>, but if C<path>
3248 is a symbolic link, then it returns the extended attributes
3249 of the link itself.");
3250
3251   ("setxattr", (RErr, [String "xattr";
3252                        String "val"; Int "vallen"; (* will be BufferIn *)
3253                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3254    [],
3255    "set extended attribute of a file or directory",
3256    "\
3257 This call sets the extended attribute named C<xattr>
3258 of the file C<path> to the value C<val> (of length C<vallen>).
3259 The value is arbitrary 8 bit data.
3260
3261 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3262
3263   ("lsetxattr", (RErr, [String "xattr";
3264                         String "val"; Int "vallen"; (* will be BufferIn *)
3265                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3266    [],
3267    "set extended attribute of a file or directory",
3268    "\
3269 This is the same as C<guestfs_setxattr>, but if C<path>
3270 is a symbolic link, then it sets an extended attribute
3271 of the link itself.");
3272
3273   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3274    [],
3275    "remove extended attribute of a file or directory",
3276    "\
3277 This call removes the extended attribute named C<xattr>
3278 of the file C<path>.
3279
3280 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3281
3282   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3283    [],
3284    "remove extended attribute of a file or directory",
3285    "\
3286 This is the same as C<guestfs_removexattr>, but if C<path>
3287 is a symbolic link, then it removes an extended attribute
3288 of the link itself.");
3289
3290   ("mountpoints", (RHashtable "mps", []), 147, [],
3291    [],
3292    "show mountpoints",
3293    "\
3294 This call is similar to C<guestfs_mounts>.  That call returns
3295 a list of devices.  This one returns a hash table (map) of
3296 device name to directory where the device is mounted.");
3297
3298   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3299    (* This is a special case: while you would expect a parameter
3300     * of type "Pathname", that doesn't work, because it implies
3301     * NEED_ROOT in the generated calling code in stubs.c, and
3302     * this function cannot use NEED_ROOT.
3303     *)
3304    [],
3305    "create a mountpoint",
3306    "\
3307 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3308 specialized calls that can be used to create extra mountpoints
3309 before mounting the first filesystem.
3310
3311 These calls are I<only> necessary in some very limited circumstances,
3312 mainly the case where you want to mount a mix of unrelated and/or
3313 read-only filesystems together.
3314
3315 For example, live CDs often contain a \"Russian doll\" nest of
3316 filesystems, an ISO outer layer, with a squashfs image inside, with
3317 an ext2/3 image inside that.  You can unpack this as follows
3318 in guestfish:
3319
3320  add-ro Fedora-11-i686-Live.iso
3321  run
3322  mkmountpoint /cd
3323  mkmountpoint /squash
3324  mkmountpoint /ext3
3325  mount /dev/sda /cd
3326  mount-loop /cd/LiveOS/squashfs.img /squash
3327  mount-loop /squash/LiveOS/ext3fs.img /ext3
3328
3329 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3330
3331   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3332    [],
3333    "remove a mountpoint",
3334    "\
3335 This calls removes a mountpoint that was previously created
3336 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3337 for full details.");
3338
3339   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3340    [InitISOFS, Always, TestOutputBuffer (
3341       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3342     (* Test various near large, large and too large files (RHBZ#589039). *)
3343     InitBasicFS, Always, TestLastFail (
3344       [["touch"; "/a"];
3345        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3346        ["read_file"; "/a"]]);
3347     InitBasicFS, Always, TestLastFail (
3348       [["touch"; "/a"];
3349        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3350        ["read_file"; "/a"]]);
3351     InitBasicFS, Always, TestLastFail (
3352       [["touch"; "/a"];
3353        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3354        ["read_file"; "/a"]])],
3355    "read a file",
3356    "\
3357 This calls returns the contents of the file C<path> as a
3358 buffer.
3359
3360 Unlike C<guestfs_cat>, this function can correctly
3361 handle files that contain embedded ASCII NUL characters.
3362 However unlike C<guestfs_download>, this function is limited
3363 in the total size of file that can be handled.");
3364
3365   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3366    [InitISOFS, Always, TestOutputList (
3367       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3368     InitISOFS, Always, TestOutputList (
3369       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3370     (* Test for RHBZ#579608, absolute symbolic links. *)
3371     InitISOFS, Always, TestOutputList (
3372       [["grep"; "nomatch"; "/abssymlink"]], [])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<grep> program and returns the
3376 matching lines.");
3377
3378   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<egrep> program and returns the
3384 matching lines.");
3385
3386   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<fgrep> program and returns the
3392 matching lines.");
3393
3394   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<grep -i> program and returns the
3400 matching lines.");
3401
3402   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<egrep -i> program and returns the
3408 matching lines.");
3409
3410   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<fgrep -i> program and returns the
3416 matching lines.");
3417
3418   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<zgrep> program and returns the
3424 matching lines.");
3425
3426   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3427    [InitISOFS, Always, TestOutputList (
3428       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429    "return lines matching a pattern",
3430    "\
3431 This calls the external C<zegrep> program and returns the
3432 matching lines.");
3433
3434   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3435    [InitISOFS, Always, TestOutputList (
3436       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437    "return lines matching a pattern",
3438    "\
3439 This calls the external C<zfgrep> program and returns the
3440 matching lines.");
3441
3442   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3443    [InitISOFS, Always, TestOutputList (
3444       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3445    "return lines matching a pattern",
3446    "\
3447 This calls the external C<zgrep -i> program and returns the
3448 matching lines.");
3449
3450   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3451    [InitISOFS, Always, TestOutputList (
3452       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453    "return lines matching a pattern",
3454    "\
3455 This calls the external C<zegrep -i> program and returns the
3456 matching lines.");
3457
3458   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3459    [InitISOFS, Always, TestOutputList (
3460       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461    "return lines matching a pattern",
3462    "\
3463 This calls the external C<zfgrep -i> program and returns the
3464 matching lines.");
3465
3466   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3467    [InitISOFS, Always, TestOutput (
3468       [["realpath"; "/../directory"]], "/directory")],
3469    "canonicalized absolute pathname",
3470    "\
3471 Return the canonicalized absolute pathname of C<path>.  The
3472 returned path has no C<.>, C<..> or symbolic link path elements.");
3473
3474   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3475    [InitBasicFS, Always, TestOutputStruct (
3476       [["touch"; "/a"];
3477        ["ln"; "/a"; "/b"];
3478        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3479    "create a hard link",
3480    "\
3481 This command creates a hard link using the C<ln> command.");
3482
3483   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3484    [InitBasicFS, Always, TestOutputStruct (
3485       [["touch"; "/a"];
3486        ["touch"; "/b"];
3487        ["ln_f"; "/a"; "/b"];
3488        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3489    "create a hard link",
3490    "\
3491 This command creates a hard link using the C<ln -f> command.
3492 The C<-f> option removes the link (C<linkname>) if it exists already.");
3493
3494   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3495    [InitBasicFS, Always, TestOutputStruct (
3496       [["touch"; "/a"];
3497        ["ln_s"; "a"; "/b"];
3498        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3499    "create a symbolic link",
3500    "\
3501 This command creates a symbolic link using the C<ln -s> command.");
3502
3503   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3504    [InitBasicFS, Always, TestOutput (
3505       [["mkdir_p"; "/a/b"];
3506        ["touch"; "/a/b/c"];
3507        ["ln_sf"; "../d"; "/a/b/c"];
3508        ["readlink"; "/a/b/c"]], "../d")],
3509    "create a symbolic link",
3510    "\
3511 This command creates a symbolic link using the C<ln -sf> command,
3512 The C<-f> option removes the link (C<linkname>) if it exists already.");
3513
3514   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3515    [] (* XXX tested above *),
3516    "read the target of a symbolic link",
3517    "\
3518 This command reads the target of a symbolic link.");
3519
3520   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3521    [InitBasicFS, Always, TestOutputStruct (
3522       [["fallocate"; "/a"; "1000000"];
3523        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3524    "preallocate a file in the guest filesystem",
3525    "\
3526 This command preallocates a file (containing zero bytes) named
3527 C<path> of size C<len> bytes.  If the file exists already, it
3528 is overwritten.
3529
3530 Do not confuse this with the guestfish-specific
3531 C<alloc> command which allocates a file in the host and
3532 attaches it as a device.");
3533
3534   ("swapon_device", (RErr, [Device "device"]), 170, [],
3535    [InitPartition, Always, TestRun (
3536       [["mkswap"; "/dev/sda1"];
3537        ["swapon_device"; "/dev/sda1"];
3538        ["swapoff_device"; "/dev/sda1"]])],
3539    "enable swap on device",
3540    "\
3541 This command enables the libguestfs appliance to use the
3542 swap device or partition named C<device>.  The increased
3543 memory is made available for all commands, for example
3544 those run using C<guestfs_command> or C<guestfs_sh>.
3545
3546 Note that you should not swap to existing guest swap
3547 partitions unless you know what you are doing.  They may
3548 contain hibernation information, or other information that
3549 the guest doesn't want you to trash.  You also risk leaking
3550 information about the host to the guest this way.  Instead,
3551 attach a new host device to the guest and swap on that.");
3552
3553   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3554    [], (* XXX tested by swapon_device *)
3555    "disable swap on device",
3556    "\
3557 This command disables the libguestfs appliance swap
3558 device or partition named C<device>.
3559 See C<guestfs_swapon_device>.");
3560
3561   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3562    [InitBasicFS, Always, TestRun (
3563       [["fallocate"; "/swap"; "8388608"];
3564        ["mkswap_file"; "/swap"];
3565        ["swapon_file"; "/swap"];
3566        ["swapoff_file"; "/swap"]])],
3567    "enable swap on file",
3568    "\
3569 This command enables swap to a file.
3570 See C<guestfs_swapon_device> for other notes.");
3571
3572   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3573    [], (* XXX tested by swapon_file *)
3574    "disable swap on file",
3575    "\
3576 This command disables the libguestfs appliance swap on file.");
3577
3578   ("swapon_label", (RErr, [String "label"]), 174, [],
3579    [InitEmpty, Always, TestRun (
3580       [["part_disk"; "/dev/sdb"; "mbr"];
3581        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3582        ["swapon_label"; "swapit"];
3583        ["swapoff_label"; "swapit"];
3584        ["zero"; "/dev/sdb"];
3585        ["blockdev_rereadpt"; "/dev/sdb"]])],
3586    "enable swap on labeled swap partition",
3587    "\
3588 This command enables swap to a labeled swap partition.
3589 See C<guestfs_swapon_device> for other notes.");
3590
3591   ("swapoff_label", (RErr, [String "label"]), 175, [],
3592    [], (* XXX tested by swapon_label *)
3593    "disable swap on labeled swap partition",
3594    "\
3595 This command disables the libguestfs appliance swap on
3596 labeled swap partition.");
3597
3598   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3599    (let uuid = uuidgen () in
3600     [InitEmpty, Always, TestRun (
3601        [["mkswap_U"; uuid; "/dev/sdb"];
3602         ["swapon_uuid"; uuid];
3603         ["swapoff_uuid"; uuid]])]),
3604    "enable swap on swap partition by UUID",
3605    "\
3606 This command enables swap to a swap partition with the given UUID.
3607 See C<guestfs_swapon_device> for other notes.");
3608
3609   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3610    [], (* XXX tested by swapon_uuid *)
3611    "disable swap on swap partition by UUID",
3612    "\
3613 This command disables the libguestfs appliance swap partition
3614 with the given UUID.");
3615
3616   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3617    [InitBasicFS, Always, TestRun (
3618       [["fallocate"; "/swap"; "8388608"];
3619        ["mkswap_file"; "/swap"]])],
3620    "create a swap file",
3621    "\
3622 Create a swap file.
3623
3624 This command just writes a swap file signature to an existing
3625 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3626
3627   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3628    [InitISOFS, Always, TestRun (
3629       [["inotify_init"; "0"]])],
3630    "create an inotify handle",
3631    "\
3632 This command creates a new inotify handle.
3633 The inotify subsystem can be used to notify events which happen to
3634 objects in the guest filesystem.
3635
3636 C<maxevents> is the maximum number of events which will be
3637 queued up between calls to C<guestfs_inotify_read> or
3638 C<guestfs_inotify_files>.
3639 If this is passed as C<0>, then the kernel (or previously set)
3640 default is used.  For Linux 2.6.29 the default was 16384 events.
3641 Beyond this limit, the kernel throws away events, but records
3642 the fact that it threw them away by setting a flag
3643 C<IN_Q_OVERFLOW> in the returned structure list (see
3644 C<guestfs_inotify_read>).
3645
3646 Before any events are generated, you have to add some
3647 watches to the internal watch list.  See:
3648 C<guestfs_inotify_add_watch>,
3649 C<guestfs_inotify_rm_watch> and
3650 C<guestfs_inotify_watch_all>.
3651
3652 Queued up events should be read periodically by calling
3653 C<guestfs_inotify_read>
3654 (or C<guestfs_inotify_files> which is just a helpful
3655 wrapper around C<guestfs_inotify_read>).  If you don't
3656 read the events out often enough then you risk the internal
3657 queue overflowing.
3658
3659 The handle should be closed after use by calling
3660 C<guestfs_inotify_close>.  This also removes any
3661 watches automatically.
3662
3663 See also L<inotify(7)> for an overview of the inotify interface
3664 as exposed by the Linux kernel, which is roughly what we expose
3665 via libguestfs.  Note that there is one global inotify handle
3666 per libguestfs instance.");
3667
3668   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3669    [InitBasicFS, Always, TestOutputList (
3670       [["inotify_init"; "0"];
3671        ["inotify_add_watch"; "/"; "1073741823"];
3672        ["touch"; "/a"];
3673        ["touch"; "/b"];
3674        ["inotify_files"]], ["a"; "b"])],
3675    "add an inotify watch",
3676    "\
3677 Watch C<path> for the events listed in C<mask>.
3678
3679 Note that if C<path> is a directory then events within that
3680 directory are watched, but this does I<not> happen recursively
3681 (in subdirectories).
3682
3683 Note for non-C or non-Linux callers: the inotify events are
3684 defined by the Linux kernel ABI and are listed in
3685 C</usr/include/sys/inotify.h>.");
3686
3687   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3688    [],
3689    "remove an inotify watch",
3690    "\
3691 Remove a previously defined inotify watch.
3692 See C<guestfs_inotify_add_watch>.");
3693
3694   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3695    [],
3696    "return list of inotify events",
3697    "\
3698 Return the complete queue of events that have happened
3699 since the previous read call.
3700
3701 If no events have happened, this returns an empty list.
3702
3703 I<Note>: In order to make sure that all events have been
3704 read, you must call this function repeatedly until it
3705 returns an empty list.  The reason is that the call will
3706 read events up to the maximum appliance-to-host message
3707 size and leave remaining events in the queue.");
3708
3709   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3710    [],
3711    "return list of watched files that had events",
3712    "\
3713 This function is a helpful wrapper around C<guestfs_inotify_read>
3714 which just returns a list of pathnames of objects that were
3715 touched.  The returned pathnames are sorted and deduplicated.");
3716
3717   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3718    [],
3719    "close the inotify handle",
3720    "\
3721 This closes the inotify handle which was previously
3722 opened by inotify_init.  It removes all watches, throws
3723 away any pending events, and deallocates all resources.");
3724
3725   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3726    [],
3727    "set SELinux security context",
3728    "\
3729 This sets the SELinux security context of the daemon
3730 to the string C<context>.
3731
3732 See the documentation about SELINUX in L<guestfs(3)>.");
3733
3734   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3735    [],
3736    "get SELinux security context",
3737    "\
3738 This gets the SELinux security context of the daemon.
3739
3740 See the documentation about SELINUX in L<guestfs(3)>,
3741 and C<guestfs_setcon>");
3742
3743   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3744    [InitEmpty, Always, TestOutput (
3745       [["part_disk"; "/dev/sda"; "mbr"];
3746        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3747        ["mount_options"; ""; "/dev/sda1"; "/"];
3748        ["write"; "/new"; "new file contents"];
3749        ["cat"; "/new"]], "new file contents");
3750     InitEmpty, Always, TestRun (
3751       [["part_disk"; "/dev/sda"; "mbr"];
3752        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3753     InitEmpty, Always, TestLastFail (
3754       [["part_disk"; "/dev/sda"; "mbr"];
3755        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3756     InitEmpty, Always, TestLastFail (
3757       [["part_disk"; "/dev/sda"; "mbr"];
3758        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3759     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3760       [["part_disk"; "/dev/sda"; "mbr"];
3761        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3762    "make a filesystem with block size",
3763    "\
3764 This call is similar to C<guestfs_mkfs>, but it allows you to
3765 control the block size of the resulting filesystem.  Supported
3766 block sizes depend on the filesystem type, but typically they
3767 are C<1024>, C<2048> or C<4096> only.
3768
3769 For VFAT and NTFS the C<blocksize> parameter is treated as
3770 the requested cluster size.");
3771
3772   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3773    [InitEmpty, Always, TestOutput (
3774       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3775        ["mke2journal"; "4096"; "/dev/sda1"];
3776        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3777        ["mount_options"; ""; "/dev/sda2"; "/"];
3778        ["write"; "/new"; "new file contents"];
3779        ["cat"; "/new"]], "new file contents")],
3780    "make ext2/3/4 external journal",
3781    "\
3782 This creates an ext2 external journal on C<device>.  It is equivalent
3783 to the command:
3784
3785  mke2fs -O journal_dev -b blocksize device");
3786
3787   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3788    [InitEmpty, Always, TestOutput (
3789       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3790        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3791        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3792        ["mount_options"; ""; "/dev/sda2"; "/"];
3793        ["write"; "/new"; "new file contents"];
3794        ["cat"; "/new"]], "new file contents")],
3795    "make ext2/3/4 external journal with label",
3796    "\
3797 This creates an ext2 external journal on C<device> with label C<label>.");
3798
3799   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3800    (let uuid = uuidgen () in
3801     [InitEmpty, Always, TestOutput (
3802        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3803         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3804         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3805         ["mount_options"; ""; "/dev/sda2"; "/"];
3806         ["write"; "/new"; "new file contents"];
3807         ["cat"; "/new"]], "new file contents")]),
3808    "make ext2/3/4 external journal with UUID",
3809    "\
3810 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3811
3812   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3813    [],
3814    "make ext2/3/4 filesystem with external journal",
3815    "\
3816 This creates an ext2/3/4 filesystem on C<device> with
3817 an external journal on C<journal>.  It is equivalent
3818 to the command:
3819
3820  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3821
3822 See also C<guestfs_mke2journal>.");
3823
3824   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3825    [],
3826    "make ext2/3/4 filesystem with external journal",
3827    "\
3828 This creates an ext2/3/4 filesystem on C<device> with
3829 an external journal on the journal labeled C<label>.
3830
3831 See also C<guestfs_mke2journal_L>.");
3832
3833   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3834    [],
3835    "make ext2/3/4 filesystem with external journal",
3836    "\
3837 This creates an ext2/3/4 filesystem on C<device> with
3838 an external journal on the journal with UUID C<uuid>.
3839
3840 See also C<guestfs_mke2journal_U>.");
3841
3842   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3843    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3844    "load a kernel module",
3845    "\
3846 This loads a kernel module in the appliance.
3847
3848 The kernel module must have been whitelisted when libguestfs
3849 was built (see C<appliance/kmod.whitelist.in> in the source).");
3850
3851   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3852    [InitNone, Always, TestOutput (
3853       [["echo_daemon"; "This is a test"]], "This is a test"
3854     )],
3855    "echo arguments back to the client",
3856    "\
3857 This command concatenates the list of C<words> passed with single spaces
3858 between them and returns the resulting string.
3859
3860 You can use this command to test the connection through to the daemon.
3861
3862 See also C<guestfs_ping_daemon>.");
3863
3864   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3865    [], (* There is a regression test for this. *)
3866    "find all files and directories, returning NUL-separated list",
3867    "\
3868 This command lists out all files and directories, recursively,
3869 starting at C<directory>, placing the resulting list in the
3870 external file called C<files>.
3871
3872 This command works the same way as C<guestfs_find> with the
3873 following exceptions:
3874
3875 =over 4
3876
3877 =item *
3878
3879 The resulting list is written to an external file.
3880
3881 =item *
3882
3883 Items (filenames) in the result are separated
3884 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3885
3886 =item *
3887
3888 This command is not limited in the number of names that it
3889 can return.
3890
3891 =item *
3892
3893 The result list is not sorted.
3894
3895 =back");
3896
3897   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3898    [InitISOFS, Always, TestOutput (
3899       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3900     InitISOFS, Always, TestOutput (
3901       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3902     InitISOFS, Always, TestOutput (
3903       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3904     InitISOFS, Always, TestLastFail (
3905       [["case_sensitive_path"; "/Known-1/"]]);
3906     InitBasicFS, Always, TestOutput (
3907       [["mkdir"; "/a"];
3908        ["mkdir"; "/a/bbb"];
3909        ["touch"; "/a/bbb/c"];
3910        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3911     InitBasicFS, Always, TestOutput (
3912       [["mkdir"; "/a"];
3913        ["mkdir"; "/a/bbb"];
3914        ["touch"; "/a/bbb/c"];
3915        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3916     InitBasicFS, Always, TestLastFail (
3917       [["mkdir"; "/a"];
3918        ["mkdir"; "/a/bbb"];
3919        ["touch"; "/a/bbb/c"];
3920        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3921    "return true path on case-insensitive filesystem",
3922    "\
3923 This can be used to resolve case insensitive paths on
3924 a filesystem which is case sensitive.  The use case is
3925 to resolve paths which you have read from Windows configuration
3926 files or the Windows Registry, to the true path.
3927
3928 The command handles a peculiarity of the Linux ntfs-3g
3929 filesystem driver (and probably others), which is that although
3930 the underlying filesystem is case-insensitive, the driver
3931 exports the filesystem to Linux as case-sensitive.
3932
3933 One consequence of this is that special directories such
3934 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3935 (or other things) depending on the precise details of how
3936 they were created.  In Windows itself this would not be
3937 a problem.
3938
3939 Bug or feature?  You decide:
3940 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3941
3942 This function resolves the true case of each element in the
3943 path and returns the case-sensitive path.
3944
3945 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3946 might return C<\"/WINDOWS/system32\"> (the exact return value
3947 would depend on details of how the directories were originally
3948 created under Windows).
3949
3950 I<Note>:
3951 This function does not handle drive names, backslashes etc.
3952
3953 See also C<guestfs_realpath>.");
3954
3955   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3956    [InitBasicFS, Always, TestOutput (
3957       [["vfs_type"; "/dev/sda1"]], "ext2")],
3958    "get the Linux VFS type corresponding to a mounted device",
3959    "\
3960 This command gets the filesystem type corresponding to
3961 the filesystem on C<device>.
3962
3963 For most filesystems, the result is the name of the Linux
3964 VFS module which would be used to mount this filesystem
3965 if you mounted it without specifying the filesystem type.
3966 For example a string such as C<ext3> or C<ntfs>.");
3967
3968   ("truncate", (RErr, [Pathname "path"]), 199, [],
3969    [InitBasicFS, Always, TestOutputStruct (
3970       [["write"; "/test"; "some stuff so size is not zero"];
3971        ["truncate"; "/test"];
3972        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3973    "truncate a file to zero size",
3974    "\
3975 This command truncates C<path> to a zero-length file.  The
3976 file must exist already.");
3977
3978   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3979    [InitBasicFS, Always, TestOutputStruct (
3980       [["touch"; "/test"];
3981        ["truncate_size"; "/test"; "1000"];
3982        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3983    "truncate a file to a particular size",
3984    "\
3985 This command truncates C<path> to size C<size> bytes.  The file
3986 must exist already.
3987
3988 If the current file size is less than C<size> then
3989 the file is extended to the required size with zero bytes.
3990 This creates a sparse file (ie. disk blocks are not allocated
3991 for the file until you write to it).  To create a non-sparse
3992 file of zeroes, use C<guestfs_fallocate64> instead.");
3993
3994   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3995    [InitBasicFS, Always, TestOutputStruct (
3996       [["touch"; "/test"];
3997        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3998        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3999    "set timestamp of a file with nanosecond precision",
4000    "\
4001 This command sets the timestamps of a file with nanosecond
4002 precision.
4003
4004 C<atsecs, atnsecs> are the last access time (atime) in secs and
4005 nanoseconds from the epoch.
4006
4007 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4008 secs and nanoseconds from the epoch.
4009
4010 If the C<*nsecs> field contains the special value C<-1> then
4011 the corresponding timestamp is set to the current time.  (The
4012 C<*secs> field is ignored in this case).
4013
4014 If the C<*nsecs> field contains the special value C<-2> then
4015 the corresponding timestamp is left unchanged.  (The
4016 C<*secs> field is ignored in this case).");
4017
4018   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4019    [InitBasicFS, Always, TestOutputStruct (
4020       [["mkdir_mode"; "/test"; "0o111"];
4021        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4022    "create a directory with a particular mode",
4023    "\
4024 This command creates a directory, setting the initial permissions
4025 of the directory to C<mode>.
4026
4027 For common Linux filesystems, the actual mode which is set will
4028 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4029 interpret the mode in other ways.
4030
4031 See also C<guestfs_mkdir>, C<guestfs_umask>");
4032
4033   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4034    [], (* XXX *)
4035    "change file owner and group",
4036    "\
4037 Change the file owner to C<owner> and group to C<group>.
4038 This is like C<guestfs_chown> but if C<path> is a symlink then
4039 the link itself is changed, not the target.
4040
4041 Only numeric uid and gid are supported.  If you want to use
4042 names, you will need to locate and parse the password file
4043 yourself (Augeas support makes this relatively easy).");
4044
4045   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4046    [], (* XXX *)
4047    "lstat on multiple files",
4048    "\
4049 This call allows you to perform the C<guestfs_lstat> operation
4050 on multiple files, where all files are in the directory C<path>.
4051 C<names> is the list of files from this directory.
4052
4053 On return you get a list of stat structs, with a one-to-one
4054 correspondence to the C<names> list.  If any name did not exist
4055 or could not be lstat'd, then the C<ino> field of that structure
4056 is set to C<-1>.
4057
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 See also C<guestfs_lxattrlist> for a similarly efficient call
4061 for getting extended attributes.  Very long directory listings
4062 might cause the protocol message size to be exceeded, causing
4063 this call to fail.  The caller must split up such requests
4064 into smaller groups of names.");
4065
4066   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4067    [], (* XXX *)
4068    "lgetxattr on multiple files",
4069    "\
4070 This call allows you to get the extended attributes
4071 of multiple files, where all files are in the directory C<path>.
4072 C<names> is the list of files from this directory.
4073
4074 On return you get a flat list of xattr structs which must be
4075 interpreted sequentially.  The first xattr struct always has a zero-length
4076 C<attrname>.  C<attrval> in this struct is zero-length
4077 to indicate there was an error doing C<lgetxattr> for this
4078 file, I<or> is a C string which is a decimal number
4079 (the number of following attributes for this file, which could
4080 be C<\"0\">).  Then after the first xattr struct are the
4081 zero or more attributes for the first named file.
4082 This repeats for the second and subsequent files.
4083
4084 This call is intended for programs that want to efficiently
4085 list a directory contents without making many round-trips.
4086 See also C<guestfs_lstatlist> for a similarly efficient call
4087 for getting standard stats.  Very long directory listings
4088 might cause the protocol message size to be exceeded, causing
4089 this call to fail.  The caller must split up such requests
4090 into smaller groups of names.");
4091
4092   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4093    [], (* XXX *)
4094    "readlink on multiple files",
4095    "\
4096 This call allows you to do a C<readlink> operation
4097 on multiple files, where all files are in the directory C<path>.
4098 C<names> is the list of files from this directory.
4099
4100 On return you get a list of strings, with a one-to-one
4101 correspondence to the C<names> list.  Each string is the
4102 value of the symbolic link.
4103
4104 If the C<readlink(2)> operation fails on any name, then
4105 the corresponding result string is the empty string C<\"\">.
4106 However the whole operation is completed even if there
4107 were C<readlink(2)> errors, and so you can call this
4108 function with names where you don't know if they are
4109 symbolic links already (albeit slightly less efficient).
4110
4111 This call is intended for programs that want to efficiently
4112 list a directory contents without making many round-trips.
4113 Very long directory listings might cause the protocol
4114 message size to be exceeded, causing
4115 this call to fail.  The caller must split up such requests
4116 into smaller groups of names.");
4117
4118   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4119    [InitISOFS, Always, TestOutputBuffer (
4120       [["pread"; "/known-4"; "1"; "3"]], "\n");
4121     InitISOFS, Always, TestOutputBuffer (
4122       [["pread"; "/empty"; "0"; "100"]], "")],
4123    "read part of a file",
4124    "\
4125 This command lets you read part of a file.  It reads C<count>
4126 bytes of the file, starting at C<offset>, from file C<path>.
4127
4128 This may read fewer bytes than requested.  For further details
4129 see the L<pread(2)> system call.
4130
4131 See also C<guestfs_pwrite>.");
4132
4133   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4134    [InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "gpt"]])],
4136    "create an empty partition table",
4137    "\
4138 This creates an empty partition table on C<device> of one of the
4139 partition types listed below.  Usually C<parttype> should be
4140 either C<msdos> or C<gpt> (for large disks).
4141
4142 Initially there are no partitions.  Following this, you should
4143 call C<guestfs_part_add> for each partition required.
4144
4145 Possible values for C<parttype> are:
4146
4147 =over 4
4148
4149 =item B<efi> | B<gpt>
4150
4151 Intel EFI / GPT partition table.
4152
4153 This is recommended for >= 2 TB partitions that will be accessed
4154 from Linux and Intel-based Mac OS X.  It also has limited backwards
4155 compatibility with the C<mbr> format.
4156
4157 =item B<mbr> | B<msdos>
4158
4159 The standard PC \"Master Boot Record\" (MBR) format used
4160 by MS-DOS and Windows.  This partition type will B<only> work
4161 for device sizes up to 2 TB.  For large disks we recommend
4162 using C<gpt>.
4163
4164 =back
4165
4166 Other partition table types that may work but are not
4167 supported include:
4168
4169 =over 4
4170
4171 =item B<aix>
4172
4173 AIX disk labels.
4174
4175 =item B<amiga> | B<rdb>
4176
4177 Amiga \"Rigid Disk Block\" format.
4178
4179 =item B<bsd>
4180
4181 BSD disk labels.
4182
4183 =item B<dasd>
4184
4185 DASD, used on IBM mainframes.
4186
4187 =item B<dvh>
4188
4189 MIPS/SGI volumes.
4190
4191 =item B<mac>
4192
4193 Old Mac partition format.  Modern Macs use C<gpt>.
4194
4195 =item B<pc98>
4196
4197 NEC PC-98 format, common in Japan apparently.
4198
4199 =item B<sun>
4200
4201 Sun disk labels.
4202
4203 =back");
4204
4205   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4206    [InitEmpty, Always, TestRun (
4207       [["part_init"; "/dev/sda"; "mbr"];
4208        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4209     InitEmpty, Always, TestRun (
4210       [["part_init"; "/dev/sda"; "gpt"];
4211        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4212        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4213     InitEmpty, Always, TestRun (
4214       [["part_init"; "/dev/sda"; "mbr"];
4215        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4216        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4217        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4218        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4219    "add a partition to the device",
4220    "\
4221 This command adds a partition to C<device>.  If there is no partition
4222 table on the device, call C<guestfs_part_init> first.
4223
4224 The C<prlogex> parameter is the type of partition.  Normally you
4225 should pass C<p> or C<primary> here, but MBR partition tables also
4226 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4227 types.
4228
4229 C<startsect> and C<endsect> are the start and end of the partition
4230 in I<sectors>.  C<endsect> may be negative, which means it counts
4231 backwards from the end of the disk (C<-1> is the last sector).
4232
4233 Creating a partition which covers the whole disk is not so easy.
4234 Use C<guestfs_part_disk> to do that.");
4235
4236   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4237    [InitEmpty, Always, TestRun (
4238       [["part_disk"; "/dev/sda"; "mbr"]]);
4239     InitEmpty, Always, TestRun (
4240       [["part_disk"; "/dev/sda"; "gpt"]])],
4241    "partition whole disk with a single primary partition",
4242    "\
4243 This command is simply a combination of C<guestfs_part_init>
4244 followed by C<guestfs_part_add> to create a single primary partition
4245 covering the whole disk.
4246
4247 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4248 but other possible values are described in C<guestfs_part_init>.");
4249
4250   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4251    [InitEmpty, Always, TestRun (
4252       [["part_disk"; "/dev/sda"; "mbr"];
4253        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4254    "make a partition bootable",
4255    "\
4256 This sets the bootable flag on partition numbered C<partnum> on
4257 device C<device>.  Note that partitions are numbered from 1.
4258
4259 The bootable flag is used by some operating systems (notably
4260 Windows) to determine which partition to boot from.  It is by
4261 no means universally recognized.");
4262
4263   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4264    [InitEmpty, Always, TestRun (
4265       [["part_disk"; "/dev/sda"; "gpt"];
4266        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4267    "set partition name",
4268    "\
4269 This sets the partition name on partition numbered C<partnum> on
4270 device C<device>.  Note that partitions are numbered from 1.
4271
4272 The partition name can only be set on certain types of partition
4273 table.  This works on C<gpt> but not on C<mbr> partitions.");
4274
4275   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4276    [], (* XXX Add a regression test for this. *)
4277    "list partitions on a device",
4278    "\
4279 This command parses the partition table on C<device> and
4280 returns the list of partitions found.
4281
4282 The fields in the returned structure are:
4283
4284 =over 4
4285
4286 =item B<part_num>
4287
4288 Partition number, counting from 1.
4289
4290 =item B<part_start>
4291
4292 Start of the partition I<in bytes>.  To get sectors you have to
4293 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4294
4295 =item B<part_end>
4296
4297 End of the partition in bytes.
4298
4299 =item B<part_size>
4300
4301 Size of the partition in bytes.
4302
4303 =back");
4304
4305   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4306    [InitEmpty, Always, TestOutput (
4307       [["part_disk"; "/dev/sda"; "gpt"];
4308        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4309    "get the partition table type",
4310    "\
4311 This command examines the partition table on C<device> and
4312 returns the partition table type (format) being used.
4313
4314 Common return values include: C<msdos> (a DOS/Windows style MBR
4315 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4316 values are possible, although unusual.  See C<guestfs_part_init>
4317 for a full list.");
4318
4319   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4320    [InitBasicFS, Always, TestOutputBuffer (
4321       [["fill"; "0x63"; "10"; "/test"];
4322        ["read_file"; "/test"]], "cccccccccc")],
4323    "fill a file with octets",
4324    "\
4325 This command creates a new file called C<path>.  The initial
4326 content of the file is C<len> octets of C<c>, where C<c>
4327 must be a number in the range C<[0..255]>.
4328
4329 To fill a file with zero bytes (sparsely), it is
4330 much more efficient to use C<guestfs_truncate_size>.
4331 To create a file with a pattern of repeating bytes
4332 use C<guestfs_fill_pattern>.");
4333
4334   ("available", (RErr, [StringList "groups"]), 216, [],
4335    [InitNone, Always, TestRun [["available"; ""]]],
4336    "test availability of some parts of the API",
4337    "\
4338 This command is used to check the availability of some
4339 groups of functionality in the appliance, which not all builds of
4340 the libguestfs appliance will be able to provide.
4341
4342 The libguestfs groups, and the functions that those
4343 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4344 You can also fetch this list at runtime by calling
4345 C<guestfs_available_all_groups>.
4346
4347 The argument C<groups> is a list of group names, eg:
4348 C<[\"inotify\", \"augeas\"]> would check for the availability of
4349 the Linux inotify functions and Augeas (configuration file
4350 editing) functions.
4351
4352 The command returns no error if I<all> requested groups are available.
4353
4354 It fails with an error if one or more of the requested
4355 groups is unavailable in the appliance.
4356
4357 If an unknown group name is included in the
4358 list of groups then an error is always returned.
4359
4360 I<Notes:>
4361
4362 =over 4
4363
4364 =item *
4365
4366 You must call C<guestfs_launch> before calling this function.
4367
4368 The reason is because we don't know what groups are
4369 supported by the appliance/daemon until it is running and can
4370 be queried.
4371
4372 =item *
4373
4374 If a group of functions is available, this does not necessarily
4375 mean that they will work.  You still have to check for errors
4376 when calling individual API functions even if they are
4377 available.
4378
4379 =item *
4380
4381 It is usually the job of distro packagers to build
4382 complete functionality into the libguestfs appliance.
4383 Upstream libguestfs, if built from source with all
4384 requirements satisfied, will support everything.
4385
4386 =item *
4387
4388 This call was added in version C<1.0.80>.  In previous
4389 versions of libguestfs all you could do would be to speculatively
4390 execute a command to find out if the daemon implemented it.
4391 See also C<guestfs_version>.
4392
4393 =back");
4394
4395   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4396    [InitBasicFS, Always, TestOutputBuffer (
4397       [["write"; "/src"; "hello, world"];
4398        ["dd"; "/src"; "/dest"];
4399        ["read_file"; "/dest"]], "hello, world")],
4400    "copy from source to destination using dd",
4401    "\
4402 This command copies from one source device or file C<src>
4403 to another destination device or file C<dest>.  Normally you
4404 would use this to copy to or from a device or partition, for
4405 example to duplicate a filesystem.
4406
4407 If the destination is a device, it must be as large or larger
4408 than the source file or device, otherwise the copy will fail.
4409 This command cannot do partial copies (see C<guestfs_copy_size>).");
4410
4411   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4412    [InitBasicFS, Always, TestOutputInt (
4413       [["write"; "/file"; "hello, world"];
4414        ["filesize"; "/file"]], 12)],
4415    "return the size of the file in bytes",
4416    "\
4417 This command returns the size of C<file> in bytes.
4418
4419 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4420 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4421 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4422
4423   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4424    [InitBasicFSonLVM, Always, TestOutputList (
4425       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4426        ["lvs"]], ["/dev/VG/LV2"])],
4427    "rename an LVM logical volume",
4428    "\
4429 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4430
4431   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4432    [InitBasicFSonLVM, Always, TestOutputList (
4433       [["umount"; "/"];
4434        ["vg_activate"; "false"; "VG"];
4435        ["vgrename"; "VG"; "VG2"];
4436        ["vg_activate"; "true"; "VG2"];
4437        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4438        ["vgs"]], ["VG2"])],
4439    "rename an LVM volume group",
4440    "\
4441 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4442
4443   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4444    [InitISOFS, Always, TestOutputBuffer (
4445       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4446    "list the contents of a single file in an initrd",
4447    "\
4448 This command unpacks the file C<filename> from the initrd file
4449 called C<initrdpath>.  The filename must be given I<without> the
4450 initial C</> character.
4451
4452 For example, in guestfish you could use the following command
4453 to examine the boot script (usually called C</init>)
4454 contained in a Linux initrd or initramfs image:
4455
4456  initrd-cat /boot/initrd-<version>.img init
4457
4458 See also C<guestfs_initrd_list>.");
4459
4460   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4461    [],
4462    "get the UUID of a physical volume",
4463    "\
4464 This command returns the UUID of the LVM PV C<device>.");
4465
4466   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4467    [],
4468    "get the UUID of a volume group",
4469    "\
4470 This command returns the UUID of the LVM VG named C<vgname>.");
4471
4472   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4473    [],
4474    "get the UUID of a logical volume",
4475    "\
4476 This command returns the UUID of the LVM LV C<device>.");
4477
4478   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4479    [],
4480    "get the PV UUIDs containing the volume group",
4481    "\
4482 Given a VG called C<vgname>, this returns the UUIDs of all
4483 the physical volumes that this volume group resides on.
4484
4485 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4486 calls to associate physical volumes and volume groups.
4487
4488 See also C<guestfs_vglvuuids>.");
4489
4490   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4491    [],
4492    "get the LV UUIDs of all LVs in the volume group",
4493    "\
4494 Given a VG called C<vgname>, this returns the UUIDs of all
4495 the logical volumes created in this volume group.
4496
4497 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4498 calls to associate logical volumes and volume groups.
4499
4500 See also C<guestfs_vgpvuuids>.");
4501
4502   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4503    [InitBasicFS, Always, TestOutputBuffer (
4504       [["write"; "/src"; "hello, world"];
4505        ["copy_size"; "/src"; "/dest"; "5"];
4506        ["read_file"; "/dest"]], "hello")],
4507    "copy size bytes from source to destination using dd",
4508    "\
4509 This command copies exactly C<size> bytes from one source device
4510 or file C<src> to another destination device or file C<dest>.
4511
4512 Note this will fail if the source is too short or if the destination
4513 is not large enough.");
4514
4515   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4516    [InitBasicFSonLVM, Always, TestRun (
4517       [["zero_device"; "/dev/VG/LV"]])],
4518    "write zeroes to an entire device",
4519    "\
4520 This command writes zeroes over the entire C<device>.  Compare
4521 with C<guestfs_zero> which just zeroes the first few blocks of
4522 a device.");
4523
4524   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4525    [InitBasicFS, Always, TestOutput (
4526       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4527        ["cat"; "/hello"]], "hello\n")],
4528    "unpack compressed tarball to directory",
4529    "\
4530 This command uploads and unpacks local file C<tarball> (an
4531 I<xz compressed> tar file) into C<directory>.");
4532
4533   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4534    [],
4535    "pack directory into compressed tarball",
4536    "\
4537 This command packs the contents of C<directory> and downloads
4538 it to local file C<tarball> (as an xz compressed tar archive).");
4539
4540   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4541    [],
4542    "resize an NTFS filesystem",
4543    "\
4544 This command resizes an NTFS filesystem, expanding or
4545 shrinking it to the size of the underlying device.
4546 See also L<ntfsresize(8)>.");
4547
4548   ("vgscan", (RErr, []), 232, [],
4549    [InitEmpty, Always, TestRun (
4550       [["vgscan"]])],
4551    "rescan for LVM physical volumes, volume groups and logical volumes",
4552    "\
4553 This rescans all block devices and rebuilds the list of LVM
4554 physical volumes, volume groups and logical volumes.");
4555
4556   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4557    [InitEmpty, Always, TestRun (
4558       [["part_init"; "/dev/sda"; "mbr"];
4559        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4560        ["part_del"; "/dev/sda"; "1"]])],
4561    "delete a partition",
4562    "\
4563 This command deletes the partition numbered C<partnum> on C<device>.
4564
4565 Note that in the case of MBR partitioning, deleting an
4566 extended partition also deletes any logical partitions
4567 it contains.");
4568
4569   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4570    [InitEmpty, Always, TestOutputTrue (
4571       [["part_init"; "/dev/sda"; "mbr"];
4572        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4573        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4574        ["part_get_bootable"; "/dev/sda"; "1"]])],
4575    "return true if a partition is bootable",
4576    "\
4577 This command returns true if the partition C<partnum> on
4578 C<device> has the bootable flag set.
4579
4580 See also C<guestfs_part_set_bootable>.");
4581
4582   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4583    [InitEmpty, Always, TestOutputInt (
4584       [["part_init"; "/dev/sda"; "mbr"];
4585        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4586        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4587        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4588    "get the MBR type byte (ID byte) from a partition",
4589    "\
4590 Returns the MBR type byte (also known as the ID byte) from
4591 the numbered partition C<partnum>.
4592
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4596
4597   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4598    [], (* tested by part_get_mbr_id *)
4599    "set the MBR type byte (ID byte) of a partition",
4600    "\
4601 Sets the MBR type byte (also known as the ID byte) of
4602 the numbered partition C<partnum> to C<idbyte>.  Note
4603 that the type bytes quoted in most documentation are
4604 in fact hexadecimal numbers, but usually documented
4605 without any leading \"0x\" which might be confusing.
4606
4607 Note that only MBR (old DOS-style) partitions have type bytes.
4608 You will get undefined results for other partition table
4609 types (see C<guestfs_part_get_parttype>).");
4610
4611   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4612    [InitISOFS, Always, TestOutput (
4613       [["checksum_device"; "md5"; "/dev/sdd"]],
4614       (Digest.to_hex (Digest.file "images/test.iso")))],
4615    "compute MD5, SHAx or CRC checksum of the contents of a device",
4616    "\
4617 This call computes the MD5, SHAx or CRC checksum of the
4618 contents of the device named C<device>.  For the types of
4619 checksums supported see the C<guestfs_checksum> command.");
4620
4621   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4622    [InitNone, Always, TestRun (
4623       [["part_disk"; "/dev/sda"; "mbr"];
4624        ["pvcreate"; "/dev/sda1"];
4625        ["vgcreate"; "VG"; "/dev/sda1"];
4626        ["lvcreate"; "LV"; "VG"; "10"];
4627        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4628    "expand an LV to fill free space",
4629    "\
4630 This expands an existing logical volume C<lv> so that it fills
4631 C<pc>% of the remaining free space in the volume group.  Commonly
4632 you would call this with pc = 100 which expands the logical volume
4633 as much as possible, using all remaining free space in the volume
4634 group.");
4635
4636   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4637    [], (* XXX Augeas code needs tests. *)
4638    "clear Augeas path",
4639    "\
4640 Set the value associated with C<path> to C<NULL>.  This
4641 is the same as the L<augtool(1)> C<clear> command.");
4642
4643   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4644    [InitEmpty, Always, TestOutputInt (
4645       [["get_umask"]], 0o22)],
4646    "get the current umask",
4647    "\
4648 Return the current umask.  By default the umask is C<022>
4649 unless it has been set by calling C<guestfs_umask>.");
4650
4651   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4652    [],
4653    "upload a file to the appliance (internal use only)",
4654    "\
4655 The C<guestfs_debug_upload> command uploads a file to
4656 the libguestfs appliance.
4657
4658 There is no comprehensive help for this command.  You have
4659 to look at the file C<daemon/debug.c> in the libguestfs source
4660 to find out what it is for.");
4661
4662   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4663    [InitBasicFS, Always, TestOutput (
4664       [["base64_in"; "../images/hello.b64"; "/hello"];
4665        ["cat"; "/hello"]], "hello\n")],
4666    "upload base64-encoded data to file",
4667    "\
4668 This command uploads base64-encoded data from C<base64file>
4669 to C<filename>.");
4670
4671   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4672    [],
4673    "download file and encode as base64",
4674    "\
4675 This command downloads the contents of C<filename>, writing
4676 it out to local file C<base64file> encoded as base64.");
4677
4678   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4679    [],
4680    "compute MD5, SHAx or CRC checksum of files in a directory",
4681    "\
4682 This command computes the checksums of all regular files in
4683 C<directory> and then emits a list of those checksums to
4684 the local output file C<sumsfile>.
4685
4686 This can be used for verifying the integrity of a virtual
4687 machine.  However to be properly secure you should pay
4688 attention to the output of the checksum command (it uses
4689 the ones from GNU coreutils).  In particular when the
4690 filename is not printable, coreutils uses a special
4691 backslash syntax.  For more information, see the GNU
4692 coreutils info file.");
4693
4694   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4695    [InitBasicFS, Always, TestOutputBuffer (
4696       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4697        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4698    "fill a file with a repeating pattern of bytes",
4699    "\
4700 This function is like C<guestfs_fill> except that it creates
4701 a new file of length C<len> containing the repeating pattern
4702 of bytes in C<pattern>.  The pattern is truncated if necessary
4703 to ensure the length of the file is exactly C<len> bytes.");
4704
4705   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4706    [InitBasicFS, Always, TestOutput (
4707       [["write"; "/new"; "new file contents"];
4708        ["cat"; "/new"]], "new file contents");
4709     InitBasicFS, Always, TestOutput (
4710       [["write"; "/new"; "\nnew file contents\n"];
4711        ["cat"; "/new"]], "\nnew file contents\n");
4712     InitBasicFS, Always, TestOutput (
4713       [["write"; "/new"; "\n\n"];
4714        ["cat"; "/new"]], "\n\n");
4715     InitBasicFS, Always, TestOutput (
4716       [["write"; "/new"; ""];
4717        ["cat"; "/new"]], "");
4718     InitBasicFS, Always, TestOutput (
4719       [["write"; "/new"; "\n\n\n"];
4720        ["cat"; "/new"]], "\n\n\n");
4721     InitBasicFS, Always, TestOutput (
4722       [["write"; "/new"; "\n"];
4723        ["cat"; "/new"]], "\n")],
4724    "create a new file",
4725    "\
4726 This call creates a file called C<path>.  The content of the
4727 file is the string C<content> (which can contain any 8 bit data).");
4728
4729   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4730    [InitBasicFS, Always, TestOutput (
4731       [["write"; "/new"; "new file contents"];
4732        ["pwrite"; "/new"; "data"; "4"];
4733        ["cat"; "/new"]], "new data contents");
4734     InitBasicFS, Always, TestOutput (
4735       [["write"; "/new"; "new file contents"];
4736        ["pwrite"; "/new"; "is extended"; "9"];
4737        ["cat"; "/new"]], "new file is extended");
4738     InitBasicFS, Always, TestOutput (
4739       [["write"; "/new"; "new file contents"];
4740        ["pwrite"; "/new"; ""; "4"];
4741        ["cat"; "/new"]], "new file contents")],
4742    "write to part of a file",
4743    "\
4744 This command writes to part of a file.  It writes the data
4745 buffer C<content> to the file C<path> starting at offset C<offset>.
4746
4747 This command implements the L<pwrite(2)> system call, and like
4748 that system call it may not write the full data requested.  The
4749 return value is the number of bytes that were actually written
4750 to the file.  This could even be 0, although short writes are
4751 unlikely for regular files in ordinary circumstances.
4752
4753 See also C<guestfs_pread>.");
4754
4755   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4756    [],
4757    "resize an ext2, ext3 or ext4 filesystem (with size)",
4758    "\
4759 This command is the same as C<guestfs_resize2fs> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4761
4762   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4763    [],
4764    "resize an LVM physical volume (with size)",
4765    "\
4766 This command is the same as C<guestfs_pvresize> except that it
4767 allows you to specify the new size (in bytes) explicitly.");
4768
4769   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4770    [],
4771    "resize an NTFS filesystem (with size)",
4772    "\
4773 This command is the same as C<guestfs_ntfsresize> except that it
4774 allows you to specify the new size (in bytes) explicitly.");
4775
4776   ("available_all_groups", (RStringList "groups", []), 251, [],
4777    [InitNone, Always, TestRun [["available_all_groups"]]],
4778    "return a list of all optional groups",
4779    "\
4780 This command returns a list of all optional groups that this
4781 daemon knows about.  Note this returns both supported and unsupported
4782 groups.  To find out which ones the daemon can actually support
4783 you have to call C<guestfs_available> on each member of the
4784 returned list.
4785
4786 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4787
4788   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4789    [InitBasicFS, Always, TestOutputStruct (
4790       [["fallocate64"; "/a"; "1000000"];
4791        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4792    "preallocate a file in the guest filesystem",
4793    "\
4794 This command preallocates a file (containing zero bytes) named
4795 C<path> of size C<len> bytes.  If the file exists already, it
4796 is overwritten.
4797
4798 Note that this call allocates disk blocks for the file.
4799 To create a sparse file use C<guestfs_truncate_size> instead.
4800
4801 The deprecated call C<guestfs_fallocate> does the same,
4802 but owing to an oversight it only allowed 30 bit lengths
4803 to be specified, effectively limiting the maximum size
4804 of files created through that call to 1GB.
4805
4806 Do not confuse this with the guestfish-specific
4807 C<alloc> and C<sparse> commands which create
4808 a file in the host and attach it as a device.");
4809
4810   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4811    [InitBasicFS, Always, TestOutput (
4812        [["set_e2label"; "/dev/sda1"; "LTEST"];
4813         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4814    "get the filesystem label",
4815    "\
4816 This returns the filesystem label of the filesystem on
4817 C<device>.
4818
4819 If the filesystem is unlabeled, this returns the empty string.");
4820
4821   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4822    (let uuid = uuidgen () in
4823     [InitBasicFS, Always, TestOutput (
4824        [["set_e2uuid"; "/dev/sda1"; uuid];
4825         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4826    "get the filesystem UUID",
4827    "\
4828 This returns the filesystem UUID of the filesystem on
4829 C<device>.
4830
4831 If the filesystem does not have a UUID, this returns the empty string.");
4832
4833 ]
4834
4835 let all_functions = non_daemon_functions @ daemon_functions
4836
4837 (* In some places we want the functions to be displayed sorted
4838  * alphabetically, so this is useful:
4839  *)
4840 let all_functions_sorted =
4841   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4842                compare n1 n2) all_functions
4843
4844 (* This is used to generate the src/MAX_PROC_NR file which
4845  * contains the maximum procedure number, a surrogate for the
4846  * ABI version number.  See src/Makefile.am for the details.
4847  *)
4848 let max_proc_nr =
4849   let proc_nrs = List.map (
4850     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4851   ) daemon_functions in
4852   List.fold_left max 0 proc_nrs
4853
4854 (* Field types for structures. *)
4855 type field =
4856   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4857   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4858   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4859   | FUInt32
4860   | FInt32
4861   | FUInt64
4862   | FInt64
4863   | FBytes                      (* Any int measure that counts bytes. *)
4864   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4865   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4866
4867 (* Because we generate extra parsing code for LVM command line tools,
4868  * we have to pull out the LVM columns separately here.
4869  *)
4870 let lvm_pv_cols = [
4871   "pv_name", FString;
4872   "pv_uuid", FUUID;
4873   "pv_fmt", FString;
4874   "pv_size", FBytes;
4875   "dev_size", FBytes;
4876   "pv_free", FBytes;
4877   "pv_used", FBytes;
4878   "pv_attr", FString (* XXX *);
4879   "pv_pe_count", FInt64;
4880   "pv_pe_alloc_count", FInt64;
4881   "pv_tags", FString;
4882   "pe_start", FBytes;
4883   "pv_mda_count", FInt64;
4884   "pv_mda_free", FBytes;
4885   (* Not in Fedora 10:
4886      "pv_mda_size", FBytes;
4887   *)
4888 ]
4889 let lvm_vg_cols = [
4890   "vg_name", FString;
4891   "vg_uuid", FUUID;
4892   "vg_fmt", FString;
4893   "vg_attr", FString (* XXX *);
4894   "vg_size", FBytes;
4895   "vg_free", FBytes;
4896   "vg_sysid", FString;
4897   "vg_extent_size", FBytes;
4898   "vg_extent_count", FInt64;
4899   "vg_free_count", FInt64;
4900   "max_lv", FInt64;
4901   "max_pv", FInt64;
4902   "pv_count", FInt64;
4903   "lv_count", FInt64;
4904   "snap_count", FInt64;
4905   "vg_seqno", FInt64;
4906   "vg_tags", FString;
4907   "vg_mda_count", FInt64;
4908   "vg_mda_free", FBytes;
4909   (* Not in Fedora 10:
4910      "vg_mda_size", FBytes;
4911   *)
4912 ]
4913 let lvm_lv_cols = [
4914   "lv_name", FString;
4915   "lv_uuid", FUUID;
4916   "lv_attr", FString (* XXX *);
4917   "lv_major", FInt64;
4918   "lv_minor", FInt64;
4919   "lv_kernel_major", FInt64;
4920   "lv_kernel_minor", FInt64;
4921   "lv_size", FBytes;
4922   "seg_count", FInt64;
4923   "origin", FString;
4924   "snap_percent", FOptPercent;
4925   "copy_percent", FOptPercent;
4926   "move_pv", FString;
4927   "lv_tags", FString;
4928   "mirror_log", FString;
4929   "modules", FString;
4930 ]
4931
4932 (* Names and fields in all structures (in RStruct and RStructList)
4933  * that we support.
4934  *)
4935 let structs = [
4936   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4937    * not use this struct in any new code.
4938    *)
4939   "int_bool", [
4940     "i", FInt32;                (* for historical compatibility *)
4941     "b", FInt32;                (* for historical compatibility *)
4942   ];
4943
4944   (* LVM PVs, VGs, LVs. *)
4945   "lvm_pv", lvm_pv_cols;
4946   "lvm_vg", lvm_vg_cols;
4947   "lvm_lv", lvm_lv_cols;
4948
4949   (* Column names and types from stat structures.
4950    * NB. Can't use things like 'st_atime' because glibc header files
4951    * define some of these as macros.  Ugh.
4952    *)
4953   "stat", [
4954     "dev", FInt64;
4955     "ino", FInt64;
4956     "mode", FInt64;
4957     "nlink", FInt64;
4958     "uid", FInt64;
4959     "gid", FInt64;
4960     "rdev", FInt64;
4961     "size", FInt64;
4962     "blksize", FInt64;
4963     "blocks", FInt64;
4964     "atime", FInt64;
4965     "mtime", FInt64;
4966     "ctime", FInt64;
4967   ];
4968   "statvfs", [
4969     "bsize", FInt64;
4970     "frsize", FInt64;
4971     "blocks", FInt64;
4972     "bfree", FInt64;
4973     "bavail", FInt64;
4974     "files", FInt64;
4975     "ffree", FInt64;
4976     "favail", FInt64;
4977     "fsid", FInt64;
4978     "flag", FInt64;
4979     "namemax", FInt64;
4980   ];
4981
4982   (* Column names in dirent structure. *)
4983   "dirent", [
4984     "ino", FInt64;
4985     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4986     "ftyp", FChar;
4987     "name", FString;
4988   ];
4989
4990   (* Version numbers. *)
4991   "version", [
4992     "major", FInt64;
4993     "minor", FInt64;
4994     "release", FInt64;
4995     "extra", FString;
4996   ];
4997
4998   (* Extended attribute. *)
4999   "xattr", [
5000     "attrname", FString;
5001     "attrval", FBuffer;
5002   ];
5003
5004   (* Inotify events. *)
5005   "inotify_event", [
5006     "in_wd", FInt64;
5007     "in_mask", FUInt32;
5008     "in_cookie", FUInt32;
5009     "in_name", FString;
5010   ];
5011
5012   (* Partition table entry. *)
5013   "partition", [
5014     "part_num", FInt32;
5015     "part_start", FBytes;
5016     "part_end", FBytes;
5017     "part_size", FBytes;
5018   ];
5019 ] (* end of structs *)
5020
5021 (* Ugh, Java has to be different ..
5022  * These names are also used by the Haskell bindings.
5023  *)
5024 let java_structs = [
5025   "int_bool", "IntBool";
5026   "lvm_pv", "PV";
5027   "lvm_vg", "VG";
5028   "lvm_lv", "LV";
5029   "stat", "Stat";
5030   "statvfs", "StatVFS";
5031   "dirent", "Dirent";
5032   "version", "Version";
5033   "xattr", "XAttr";
5034   "inotify_event", "INotifyEvent";
5035   "partition", "Partition";
5036 ]
5037
5038 (* What structs are actually returned. *)
5039 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5040
5041 (* Returns a list of RStruct/RStructList structs that are returned
5042  * by any function.  Each element of returned list is a pair:
5043  *
5044  * (structname, RStructOnly)
5045  *    == there exists function which returns RStruct (_, structname)
5046  * (structname, RStructListOnly)
5047  *    == there exists function which returns RStructList (_, structname)
5048  * (structname, RStructAndList)
5049  *    == there are functions returning both RStruct (_, structname)
5050  *                                      and RStructList (_, structname)
5051  *)
5052 let rstructs_used_by functions =
5053   (* ||| is a "logical OR" for rstructs_used_t *)
5054   let (|||) a b =
5055     match a, b with
5056     | RStructAndList, _
5057     | _, RStructAndList -> RStructAndList
5058     | RStructOnly, RStructListOnly
5059     | RStructListOnly, RStructOnly -> RStructAndList
5060     | RStructOnly, RStructOnly -> RStructOnly
5061     | RStructListOnly, RStructListOnly -> RStructListOnly
5062   in
5063
5064   let h = Hashtbl.create 13 in
5065
5066   (* if elem->oldv exists, update entry using ||| operator,
5067    * else just add elem->newv to the hash
5068    *)
5069   let update elem newv =
5070     try  let oldv = Hashtbl.find h elem in
5071          Hashtbl.replace h elem (newv ||| oldv)
5072     with Not_found -> Hashtbl.add h elem newv
5073   in
5074
5075   List.iter (
5076     fun (_, style, _, _, _, _, _) ->
5077       match fst style with
5078       | RStruct (_, structname) -> update structname RStructOnly
5079       | RStructList (_, structname) -> update structname RStructListOnly
5080       | _ -> ()
5081   ) functions;
5082
5083   (* return key->values as a list of (key,value) *)
5084   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5085
5086 (* Used for testing language bindings. *)
5087 type callt =
5088   | CallString of string
5089   | CallOptString of string option
5090   | CallStringList of string list
5091   | CallInt of int
5092   | CallInt64 of int64
5093   | CallBool of bool
5094   | CallBuffer of string
5095
5096 (* Used to memoize the result of pod2text. *)
5097 let pod2text_memo_filename = "src/.pod2text.data"
5098 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5099   try
5100     let chan = open_in pod2text_memo_filename in
5101     let v = input_value chan in
5102     close_in chan;
5103     v
5104   with
5105     _ -> Hashtbl.create 13
5106 let pod2text_memo_updated () =
5107   let chan = open_out pod2text_memo_filename in
5108   output_value chan pod2text_memo;
5109   close_out chan
5110
5111 (* Useful functions.
5112  * Note we don't want to use any external OCaml libraries which
5113  * makes this a bit harder than it should be.
5114  *)
5115 module StringMap = Map.Make (String)
5116
5117 let failwithf fs = ksprintf failwith fs
5118
5119 let unique = let i = ref 0 in fun () -> incr i; !i
5120
5121 let replace_char s c1 c2 =
5122   let s2 = String.copy s in
5123   let r = ref false in
5124   for i = 0 to String.length s2 - 1 do
5125     if String.unsafe_get s2 i = c1 then (
5126       String.unsafe_set s2 i c2;
5127       r := true
5128     )
5129   done;
5130   if not !r then s else s2
5131
5132 let isspace c =
5133   c = ' '
5134   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5135
5136 let triml ?(test = isspace) str =
5137   let i = ref 0 in
5138   let n = ref (String.length str) in
5139   while !n > 0 && test str.[!i]; do
5140     decr n;
5141     incr i
5142   done;
5143   if !i = 0 then str
5144   else String.sub str !i !n
5145
5146 let trimr ?(test = isspace) str =
5147   let n = ref (String.length str) in
5148   while !n > 0 && test str.[!n-1]; do
5149     decr n
5150   done;
5151   if !n = String.length str then str
5152   else String.sub str 0 !n
5153
5154 let trim ?(test = isspace) str =
5155   trimr ~test (triml ~test str)
5156
5157 let rec find s sub =
5158   let len = String.length s in
5159   let sublen = String.length sub in
5160   let rec loop i =
5161     if i <= len-sublen then (
5162       let rec loop2 j =
5163         if j < sublen then (
5164           if s.[i+j] = sub.[j] then loop2 (j+1)
5165           else -1
5166         ) else
5167           i (* found *)
5168       in
5169       let r = loop2 0 in
5170       if r = -1 then loop (i+1) else r
5171     ) else
5172       -1 (* not found *)
5173   in
5174   loop 0
5175
5176 let rec replace_str s s1 s2 =
5177   let len = String.length s in
5178   let sublen = String.length s1 in
5179   let i = find s s1 in
5180   if i = -1 then s
5181   else (
5182     let s' = String.sub s 0 i in
5183     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5184     s' ^ s2 ^ replace_str s'' s1 s2
5185   )
5186
5187 let rec string_split sep str =
5188   let len = String.length str in
5189   let seplen = String.length sep in
5190   let i = find str sep in
5191   if i = -1 then [str]
5192   else (
5193     let s' = String.sub str 0 i in
5194     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5195     s' :: string_split sep s''
5196   )
5197
5198 let files_equal n1 n2 =
5199   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5200   match Sys.command cmd with
5201   | 0 -> true
5202   | 1 -> false
5203   | i -> failwithf "%s: failed with error code %d" cmd i
5204
5205 let rec filter_map f = function
5206   | [] -> []
5207   | x :: xs ->
5208       match f x with
5209       | Some y -> y :: filter_map f xs
5210       | None -> filter_map f xs
5211
5212 let rec find_map f = function
5213   | [] -> raise Not_found
5214   | x :: xs ->
5215       match f x with
5216       | Some y -> y
5217       | None -> find_map f xs
5218
5219 let iteri f xs =
5220   let rec loop i = function
5221     | [] -> ()
5222     | x :: xs -> f i x; loop (i+1) xs
5223   in
5224   loop 0 xs
5225
5226 let mapi f xs =
5227   let rec loop i = function
5228     | [] -> []
5229     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5230   in
5231   loop 0 xs
5232
5233 let count_chars c str =
5234   let count = ref 0 in
5235   for i = 0 to String.length str - 1 do
5236     if c = String.unsafe_get str i then incr count
5237   done;
5238   !count
5239
5240 let explode str =
5241   let r = ref [] in
5242   for i = 0 to String.length str - 1 do
5243     let c = String.unsafe_get str i in
5244     r := c :: !r;
5245   done;
5246   List.rev !r
5247
5248 let map_chars f str =
5249   List.map f (explode str)
5250
5251 let name_of_argt = function
5252   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5253   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5254   | FileIn n | FileOut n | BufferIn n -> n
5255
5256 let java_name_of_struct typ =
5257   try List.assoc typ java_structs
5258   with Not_found ->
5259     failwithf
5260       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5261
5262 let cols_of_struct typ =
5263   try List.assoc typ structs
5264   with Not_found ->
5265     failwithf "cols_of_struct: unknown struct %s" typ
5266
5267 let seq_of_test = function
5268   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5269   | TestOutputListOfDevices (s, _)
5270   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5271   | TestOutputTrue s | TestOutputFalse s
5272   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5273   | TestOutputStruct (s, _)
5274   | TestLastFail s -> s
5275
5276 (* Handling for function flags. *)
5277 let protocol_limit_warning =
5278   "Because of the message protocol, there is a transfer limit
5279 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5280
5281 let danger_will_robinson =
5282   "B<This command is dangerous.  Without careful use you
5283 can easily destroy all your data>."
5284
5285 let deprecation_notice flags =
5286   try
5287     let alt =
5288       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5289     let txt =
5290       sprintf "This function is deprecated.
5291 In new code, use the C<%s> call instead.
5292
5293 Deprecated functions will not be removed from the API, but the
5294 fact that they are deprecated indicates that there are problems
5295 with correct use of these functions." alt in
5296     Some txt
5297   with
5298     Not_found -> None
5299
5300 (* Create list of optional groups. *)
5301 let optgroups =
5302   let h = Hashtbl.create 13 in
5303   List.iter (
5304     fun (name, _, _, flags, _, _, _) ->
5305       List.iter (
5306         function
5307         | Optional group ->
5308             let names = try Hashtbl.find h group with Not_found -> [] in
5309             Hashtbl.replace h group (name :: names)
5310         | _ -> ()
5311       ) flags
5312   ) daemon_functions;
5313   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5314   let groups =
5315     List.map (
5316       fun group -> group, List.sort compare (Hashtbl.find h group)
5317     ) groups in
5318   List.sort (fun x y -> compare (fst x) (fst y)) groups
5319
5320 (* Check function names etc. for consistency. *)
5321 let check_functions () =
5322   let contains_uppercase str =
5323     let len = String.length str in
5324     let rec loop i =
5325       if i >= len then false
5326       else (
5327         let c = str.[i] in
5328         if c >= 'A' && c <= 'Z' then true
5329         else loop (i+1)
5330       )
5331     in
5332     loop 0
5333   in
5334
5335   (* Check function names. *)
5336   List.iter (
5337     fun (name, _, _, _, _, _, _) ->
5338       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5339         failwithf "function name %s does not need 'guestfs' prefix" name;
5340       if name = "" then
5341         failwithf "function name is empty";
5342       if name.[0] < 'a' || name.[0] > 'z' then
5343         failwithf "function name %s must start with lowercase a-z" name;
5344       if String.contains name '-' then
5345         failwithf "function name %s should not contain '-', use '_' instead."
5346           name
5347   ) all_functions;
5348
5349   (* Check function parameter/return names. *)
5350   List.iter (
5351     fun (name, style, _, _, _, _, _) ->
5352       let check_arg_ret_name n =
5353         if contains_uppercase n then
5354           failwithf "%s param/ret %s should not contain uppercase chars"
5355             name n;
5356         if String.contains n '-' || String.contains n '_' then
5357           failwithf "%s param/ret %s should not contain '-' or '_'"
5358             name n;
5359         if n = "value" then
5360           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;
5361         if n = "int" || n = "char" || n = "short" || n = "long" then
5362           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5363         if n = "i" || n = "n" then
5364           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5365         if n = "argv" || n = "args" then
5366           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5367
5368         (* List Haskell, OCaml and C keywords here.
5369          * http://www.haskell.org/haskellwiki/Keywords
5370          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5371          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5372          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5373          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5374          * Omitting _-containing words, since they're handled above.
5375          * Omitting the OCaml reserved word, "val", is ok,
5376          * and saves us from renaming several parameters.
5377          *)
5378         let reserved = [
5379           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5380           "char"; "class"; "const"; "constraint"; "continue"; "data";
5381           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5382           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5383           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5384           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5385           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5386           "interface";
5387           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5388           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5389           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5390           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5391           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5392           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5393           "volatile"; "when"; "where"; "while";
5394           ] in
5395         if List.mem n reserved then
5396           failwithf "%s has param/ret using reserved word %s" name n;
5397       in
5398
5399       (match fst style with
5400        | RErr -> ()
5401        | RInt n | RInt64 n | RBool n
5402        | RConstString n | RConstOptString n | RString n
5403        | RStringList n | RStruct (n, _) | RStructList (n, _)
5404        | RHashtable n | RBufferOut n ->
5405            check_arg_ret_name n
5406       );
5407       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5408   ) all_functions;
5409
5410   (* Check short descriptions. *)
5411   List.iter (
5412     fun (name, _, _, _, _, shortdesc, _) ->
5413       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5414         failwithf "short description of %s should begin with lowercase." name;
5415       let c = shortdesc.[String.length shortdesc-1] in
5416       if c = '\n' || c = '.' then
5417         failwithf "short description of %s should not end with . or \\n." name
5418   ) all_functions;
5419
5420   (* Check long descriptions. *)
5421   List.iter (
5422     fun (name, _, _, _, _, _, longdesc) ->
5423       if longdesc.[String.length longdesc-1] = '\n' then
5424         failwithf "long description of %s should not end with \\n." name
5425   ) all_functions;
5426
5427   (* Check proc_nrs. *)
5428   List.iter (
5429     fun (name, _, proc_nr, _, _, _, _) ->
5430       if proc_nr <= 0 then
5431         failwithf "daemon function %s should have proc_nr > 0" name
5432   ) daemon_functions;
5433
5434   List.iter (
5435     fun (name, _, proc_nr, _, _, _, _) ->
5436       if proc_nr <> -1 then
5437         failwithf "non-daemon function %s should have proc_nr -1" name
5438   ) non_daemon_functions;
5439
5440   let proc_nrs =
5441     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5442       daemon_functions in
5443   let proc_nrs =
5444     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5445   let rec loop = function
5446     | [] -> ()
5447     | [_] -> ()
5448     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5449         loop rest
5450     | (name1,nr1) :: (name2,nr2) :: _ ->
5451         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5452           name1 name2 nr1 nr2
5453   in
5454   loop proc_nrs;
5455
5456   (* Check tests. *)
5457   List.iter (
5458     function
5459       (* Ignore functions that have no tests.  We generate a
5460        * warning when the user does 'make check' instead.
5461        *)
5462     | name, _, _, _, [], _, _ -> ()
5463     | name, _, _, _, tests, _, _ ->
5464         let funcs =
5465           List.map (
5466             fun (_, _, test) ->
5467               match seq_of_test test with
5468               | [] ->
5469                   failwithf "%s has a test containing an empty sequence" name
5470               | cmds -> List.map List.hd cmds
5471           ) tests in
5472         let funcs = List.flatten funcs in
5473
5474         let tested = List.mem name funcs in
5475
5476         if not tested then
5477           failwithf "function %s has tests but does not test itself" name
5478   ) all_functions
5479
5480 (* 'pr' prints to the current output file. *)
5481 let chan = ref Pervasives.stdout
5482 let lines = ref 0
5483 let pr fs =
5484   ksprintf
5485     (fun str ->
5486        let i = count_chars '\n' str in
5487        lines := !lines + i;
5488        output_string !chan str
5489     ) fs
5490
5491 let copyright_years =
5492   let this_year = 1900 + (localtime (time ())).tm_year in
5493   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5494
5495 (* Generate a header block in a number of standard styles. *)
5496 type comment_style =
5497     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5498 type license = GPLv2plus | LGPLv2plus
5499
5500 let generate_header ?(extra_inputs = []) comment license =
5501   let inputs = "src/generator.ml" :: extra_inputs in
5502   let c = match comment with
5503     | CStyle ->         pr "/* "; " *"
5504     | CPlusPlusStyle -> pr "// "; "//"
5505     | HashStyle ->      pr "# ";  "#"
5506     | OCamlStyle ->     pr "(* "; " *"
5507     | HaskellStyle ->   pr "{- "; "  " in
5508   pr "libguestfs generated file\n";
5509   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5510   List.iter (pr "%s   %s\n" c) inputs;
5511   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5512   pr "%s\n" c;
5513   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5514   pr "%s\n" c;
5515   (match license with
5516    | GPLv2plus ->
5517        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5518        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5519        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5520        pr "%s (at your option) any later version.\n" c;
5521        pr "%s\n" c;
5522        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5523        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5524        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5525        pr "%s GNU General Public License for more details.\n" c;
5526        pr "%s\n" c;
5527        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5528        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5529        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5530
5531    | LGPLv2plus ->
5532        pr "%s This library is free software; you can redistribute it and/or\n" c;
5533        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5534        pr "%s License as published by the Free Software Foundation; either\n" c;
5535        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5536        pr "%s\n" c;
5537        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5538        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5539        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5540        pr "%s Lesser General Public License for more details.\n" c;
5541        pr "%s\n" c;
5542        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5543        pr "%s License along with this library; if not, write to the Free Software\n" c;
5544        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5545   );
5546   (match comment with
5547    | CStyle -> pr " */\n"
5548    | CPlusPlusStyle
5549    | HashStyle -> ()
5550    | OCamlStyle -> pr " *)\n"
5551    | HaskellStyle -> pr "-}\n"
5552   );
5553   pr "\n"
5554
5555 (* Start of main code generation functions below this line. *)
5556
5557 (* Generate the pod documentation for the C API. *)
5558 let rec generate_actions_pod () =
5559   List.iter (
5560     fun (shortname, style, _, flags, _, _, longdesc) ->
5561       if not (List.mem NotInDocs flags) then (
5562         let name = "guestfs_" ^ shortname in
5563         pr "=head2 %s\n\n" name;
5564         pr " ";
5565         generate_prototype ~extern:false ~handle:"g" name style;
5566         pr "\n\n";
5567         pr "%s\n\n" longdesc;
5568         (match fst style with
5569          | RErr ->
5570              pr "This function returns 0 on success or -1 on error.\n\n"
5571          | RInt _ ->
5572              pr "On error this function returns -1.\n\n"
5573          | RInt64 _ ->
5574              pr "On error this function returns -1.\n\n"
5575          | RBool _ ->
5576              pr "This function returns a C truth value on success or -1 on error.\n\n"
5577          | RConstString _ ->
5578              pr "This function returns a string, or NULL on error.
5579 The string is owned by the guest handle and must I<not> be freed.\n\n"
5580          | RConstOptString _ ->
5581              pr "This function returns a string which may be NULL.
5582 There is no way to return an error from this function.
5583 The string is owned by the guest handle and must I<not> be freed.\n\n"
5584          | RString _ ->
5585              pr "This function returns a string, or NULL on error.
5586 I<The caller must free the returned string after use>.\n\n"
5587          | RStringList _ ->
5588              pr "This function returns a NULL-terminated array of strings
5589 (like L<environ(3)>), or NULL if there was an error.
5590 I<The caller must free the strings and the array after use>.\n\n"
5591          | RStruct (_, typ) ->
5592              pr "This function returns a C<struct guestfs_%s *>,
5593 or NULL if there was an error.
5594 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5595          | RStructList (_, typ) ->
5596              pr "This function returns a C<struct guestfs_%s_list *>
5597 (see E<lt>guestfs-structs.hE<gt>),
5598 or NULL if there was an error.
5599 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5600          | RHashtable _ ->
5601              pr "This function returns a NULL-terminated array of
5602 strings, or NULL if there was an error.
5603 The array of strings will always have length C<2n+1>, where
5604 C<n> keys and values alternate, followed by the trailing NULL entry.
5605 I<The caller must free the strings and the array after use>.\n\n"
5606          | RBufferOut _ ->
5607              pr "This function returns a buffer, or NULL on error.
5608 The size of the returned buffer is written to C<*size_r>.
5609 I<The caller must free the returned buffer after use>.\n\n"
5610         );
5611         if List.mem ProtocolLimitWarning flags then
5612           pr "%s\n\n" protocol_limit_warning;
5613         if List.mem DangerWillRobinson flags then
5614           pr "%s\n\n" danger_will_robinson;
5615         match deprecation_notice flags with
5616         | None -> ()
5617         | Some txt -> pr "%s\n\n" txt
5618       )
5619   ) all_functions_sorted
5620
5621 and generate_structs_pod () =
5622   (* Structs documentation. *)
5623   List.iter (
5624     fun (typ, cols) ->
5625       pr "=head2 guestfs_%s\n" typ;
5626       pr "\n";
5627       pr " struct guestfs_%s {\n" typ;
5628       List.iter (
5629         function
5630         | name, FChar -> pr "   char %s;\n" name
5631         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5632         | name, FInt32 -> pr "   int32_t %s;\n" name
5633         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5634         | name, FInt64 -> pr "   int64_t %s;\n" name
5635         | name, FString -> pr "   char *%s;\n" name
5636         | name, FBuffer ->
5637             pr "   /* The next two fields describe a byte array. */\n";
5638             pr "   uint32_t %s_len;\n" name;
5639             pr "   char *%s;\n" name
5640         | name, FUUID ->
5641             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5642             pr "   char %s[32];\n" name
5643         | name, FOptPercent ->
5644             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5645             pr "   float %s;\n" name
5646       ) cols;
5647       pr " };\n";
5648       pr " \n";
5649       pr " struct guestfs_%s_list {\n" typ;
5650       pr "   uint32_t len; /* Number of elements in list. */\n";
5651       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5652       pr " };\n";
5653       pr " \n";
5654       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5655       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5656         typ typ;
5657       pr "\n"
5658   ) structs
5659
5660 and generate_availability_pod () =
5661   (* Availability documentation. *)
5662   pr "=over 4\n";
5663   pr "\n";
5664   List.iter (
5665     fun (group, functions) ->
5666       pr "=item B<%s>\n" group;
5667       pr "\n";
5668       pr "The following functions:\n";
5669       List.iter (pr "L</guestfs_%s>\n") functions;
5670       pr "\n"
5671   ) optgroups;
5672   pr "=back\n";
5673   pr "\n"
5674
5675 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5676  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5677  *
5678  * We have to use an underscore instead of a dash because otherwise
5679  * rpcgen generates incorrect code.
5680  *
5681  * This header is NOT exported to clients, but see also generate_structs_h.
5682  *)
5683 and generate_xdr () =
5684   generate_header CStyle LGPLv2plus;
5685
5686   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5687   pr "typedef string guestfs_str<>;\n";
5688   pr "\n";
5689
5690   (* Internal structures. *)
5691   List.iter (
5692     function
5693     | typ, cols ->
5694         pr "struct guestfs_int_%s {\n" typ;
5695         List.iter (function
5696                    | name, FChar -> pr "  char %s;\n" name
5697                    | name, FString -> pr "  string %s<>;\n" name
5698                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5699                    | name, FUUID -> pr "  opaque %s[32];\n" name
5700                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5701                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5702                    | name, FOptPercent -> pr "  float %s;\n" name
5703                   ) cols;
5704         pr "};\n";
5705         pr "\n";
5706         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5707         pr "\n";
5708   ) structs;
5709
5710   List.iter (
5711     fun (shortname, style, _, _, _, _, _) ->
5712       let name = "guestfs_" ^ shortname in
5713
5714       (match snd style with
5715        | [] -> ()
5716        | args ->
5717            pr "struct %s_args {\n" name;
5718            List.iter (
5719              function
5720              | Pathname n | Device n | Dev_or_Path n | String n ->
5721                  pr "  string %s<>;\n" n
5722              | OptString n -> pr "  guestfs_str *%s;\n" n
5723              | StringList n | DeviceList n -> pr "  guestfs_str %s<>;\n" n
5724              | Bool n -> pr "  bool %s;\n" n
5725              | Int n -> pr "  int %s;\n" n
5726              | Int64 n -> pr "  hyper %s;\n" n
5727              | BufferIn n ->
5728                  pr "  opaque %s<>;\n" n
5729              | FileIn _ | FileOut _ -> ()
5730            ) args;
5731            pr "};\n\n"
5732       );
5733       (match fst style with
5734        | RErr -> ()
5735        | RInt n ->
5736            pr "struct %s_ret {\n" name;
5737            pr "  int %s;\n" n;
5738            pr "};\n\n"
5739        | RInt64 n ->
5740            pr "struct %s_ret {\n" name;
5741            pr "  hyper %s;\n" n;
5742            pr "};\n\n"
5743        | RBool n ->
5744            pr "struct %s_ret {\n" name;
5745            pr "  bool %s;\n" n;
5746            pr "};\n\n"
5747        | RConstString _ | RConstOptString _ ->
5748            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5749        | RString n ->
5750            pr "struct %s_ret {\n" name;
5751            pr "  string %s<>;\n" n;
5752            pr "};\n\n"
5753        | RStringList n ->
5754            pr "struct %s_ret {\n" name;
5755            pr "  guestfs_str %s<>;\n" n;
5756            pr "};\n\n"
5757        | RStruct (n, typ) ->
5758            pr "struct %s_ret {\n" name;
5759            pr "  guestfs_int_%s %s;\n" typ n;
5760            pr "};\n\n"
5761        | RStructList (n, typ) ->
5762            pr "struct %s_ret {\n" name;
5763            pr "  guestfs_int_%s_list %s;\n" typ n;
5764            pr "};\n\n"
5765        | RHashtable n ->
5766            pr "struct %s_ret {\n" name;
5767            pr "  guestfs_str %s<>;\n" n;
5768            pr "};\n\n"
5769        | RBufferOut n ->
5770            pr "struct %s_ret {\n" name;
5771            pr "  opaque %s<>;\n" n;
5772            pr "};\n\n"
5773       );
5774   ) daemon_functions;
5775
5776   (* Table of procedure numbers. *)
5777   pr "enum guestfs_procedure {\n";
5778   List.iter (
5779     fun (shortname, _, proc_nr, _, _, _, _) ->
5780       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5781   ) daemon_functions;
5782   pr "  GUESTFS_PROC_NR_PROCS\n";
5783   pr "};\n";
5784   pr "\n";
5785
5786   (* Having to choose a maximum message size is annoying for several
5787    * reasons (it limits what we can do in the API), but it (a) makes
5788    * the protocol a lot simpler, and (b) provides a bound on the size
5789    * of the daemon which operates in limited memory space.
5790    *)
5791   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5792   pr "\n";
5793
5794   (* Message header, etc. *)
5795   pr "\
5796 /* The communication protocol is now documented in the guestfs(3)
5797  * manpage.
5798  */
5799
5800 const GUESTFS_PROGRAM = 0x2000F5F5;
5801 const GUESTFS_PROTOCOL_VERSION = 1;
5802
5803 /* These constants must be larger than any possible message length. */
5804 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5805 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5806
5807 enum guestfs_message_direction {
5808   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5809   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5810 };
5811
5812 enum guestfs_message_status {
5813   GUESTFS_STATUS_OK = 0,
5814   GUESTFS_STATUS_ERROR = 1
5815 };
5816
5817 const GUESTFS_ERROR_LEN = 256;
5818
5819 struct guestfs_message_error {
5820   string error_message<GUESTFS_ERROR_LEN>;
5821 };
5822
5823 struct guestfs_message_header {
5824   unsigned prog;                     /* GUESTFS_PROGRAM */
5825   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5826   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5827   guestfs_message_direction direction;
5828   unsigned serial;                   /* message serial number */
5829   guestfs_message_status status;
5830 };
5831
5832 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5833
5834 struct guestfs_chunk {
5835   int cancel;                        /* if non-zero, transfer is cancelled */
5836   /* data size is 0 bytes if the transfer has finished successfully */
5837   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5838 };
5839 "
5840
5841 (* Generate the guestfs-structs.h file. *)
5842 and generate_structs_h () =
5843   generate_header CStyle LGPLv2plus;
5844
5845   (* This is a public exported header file containing various
5846    * structures.  The structures are carefully written to have
5847    * exactly the same in-memory format as the XDR structures that
5848    * we use on the wire to the daemon.  The reason for creating
5849    * copies of these structures here is just so we don't have to
5850    * export the whole of guestfs_protocol.h (which includes much
5851    * unrelated and XDR-dependent stuff that we don't want to be
5852    * public, or required by clients).
5853    *
5854    * To reiterate, we will pass these structures to and from the
5855    * client with a simple assignment or memcpy, so the format
5856    * must be identical to what rpcgen / the RFC defines.
5857    *)
5858
5859   (* Public structures. *)
5860   List.iter (
5861     fun (typ, cols) ->
5862       pr "struct guestfs_%s {\n" typ;
5863       List.iter (
5864         function
5865         | name, FChar -> pr "  char %s;\n" name
5866         | name, FString -> pr "  char *%s;\n" name
5867         | name, FBuffer ->
5868             pr "  uint32_t %s_len;\n" name;
5869             pr "  char *%s;\n" name
5870         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5871         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5872         | name, FInt32 -> pr "  int32_t %s;\n" name
5873         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5874         | name, FInt64 -> pr "  int64_t %s;\n" name
5875         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5876       ) cols;
5877       pr "};\n";
5878       pr "\n";
5879       pr "struct guestfs_%s_list {\n" typ;
5880       pr "  uint32_t len;\n";
5881       pr "  struct guestfs_%s *val;\n" typ;
5882       pr "};\n";
5883       pr "\n";
5884       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5885       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5886       pr "\n"
5887   ) structs
5888
5889 (* Generate the guestfs-actions.h file. *)
5890 and generate_actions_h () =
5891   generate_header CStyle LGPLv2plus;
5892   List.iter (
5893     fun (shortname, style, _, _, _, _, _) ->
5894       let name = "guestfs_" ^ shortname in
5895       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5896         name style
5897   ) all_functions
5898
5899 (* Generate the guestfs-internal-actions.h file. *)
5900 and generate_internal_actions_h () =
5901   generate_header CStyle LGPLv2plus;
5902   List.iter (
5903     fun (shortname, style, _, _, _, _, _) ->
5904       let name = "guestfs__" ^ shortname in
5905       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5906         name style
5907   ) non_daemon_functions
5908
5909 (* Generate the client-side dispatch stubs. *)
5910 and generate_client_actions () =
5911   generate_header CStyle LGPLv2plus;
5912
5913   pr "\
5914 #include <stdio.h>
5915 #include <stdlib.h>
5916 #include <stdint.h>
5917 #include <string.h>
5918 #include <inttypes.h>
5919
5920 #include \"guestfs.h\"
5921 #include \"guestfs-internal.h\"
5922 #include \"guestfs-internal-actions.h\"
5923 #include \"guestfs_protocol.h\"
5924
5925 /* Check the return message from a call for validity. */
5926 static int
5927 check_reply_header (guestfs_h *g,
5928                     const struct guestfs_message_header *hdr,
5929                     unsigned int proc_nr, unsigned int serial)
5930 {
5931   if (hdr->prog != GUESTFS_PROGRAM) {
5932     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5933     return -1;
5934   }
5935   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5936     error (g, \"wrong protocol version (%%d/%%d)\",
5937            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5938     return -1;
5939   }
5940   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5941     error (g, \"unexpected message direction (%%d/%%d)\",
5942            hdr->direction, GUESTFS_DIRECTION_REPLY);
5943     return -1;
5944   }
5945   if (hdr->proc != proc_nr) {
5946     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5947     return -1;
5948   }
5949   if (hdr->serial != serial) {
5950     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5951     return -1;
5952   }
5953
5954   return 0;
5955 }
5956
5957 /* Check we are in the right state to run a high-level action. */
5958 static int
5959 check_state (guestfs_h *g, const char *caller)
5960 {
5961   if (!guestfs__is_ready (g)) {
5962     if (guestfs__is_config (g) || guestfs__is_launching (g))
5963       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5964         caller);
5965     else
5966       error (g, \"%%s called from the wrong state, %%d != READY\",
5967         caller, guestfs__get_state (g));
5968     return -1;
5969   }
5970   return 0;
5971 }
5972
5973 ";
5974
5975   let error_code_of = function
5976     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5977     | RConstString _ | RConstOptString _
5978     | RString _ | RStringList _
5979     | RStruct _ | RStructList _
5980     | RHashtable _ | RBufferOut _ -> "NULL"
5981   in
5982
5983   (* Generate code to check String-like parameters are not passed in
5984    * as NULL (returning an error if they are).
5985    *)
5986   let check_null_strings shortname style =
5987     let pr_newline = ref false in
5988     List.iter (
5989       function
5990       (* parameters which should not be NULL *)
5991       | String n
5992       | Device n
5993       | Pathname n
5994       | Dev_or_Path n
5995       | FileIn n
5996       | FileOut n
5997       | BufferIn n
5998       | StringList n
5999       | DeviceList n ->
6000           pr "  if (%s == NULL) {\n" n;
6001           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6002           pr "           \"%s\", \"%s\");\n" shortname n;
6003           pr "    return %s;\n" (error_code_of (fst style));
6004           pr "  }\n";
6005           pr_newline := true
6006
6007       (* can be NULL *)
6008       | OptString _
6009
6010       (* not applicable *)
6011       | Bool _
6012       | Int _
6013       | Int64 _ -> ()
6014     ) (snd style);
6015
6016     if !pr_newline then pr "\n";
6017   in
6018
6019   (* Generate code to generate guestfish call traces. *)
6020   let trace_call shortname style =
6021     pr "  if (guestfs__get_trace (g)) {\n";
6022
6023     let needs_i =
6024       List.exists (function
6025                    | StringList _ | DeviceList _ -> true
6026                    | _ -> false) (snd style) in
6027     if needs_i then (
6028       pr "    size_t i;\n";
6029       pr "\n"
6030     );
6031
6032     pr "    printf (\"%s\");\n" shortname;
6033     List.iter (
6034       function
6035       | String n                        (* strings *)
6036       | Device n
6037       | Pathname n
6038       | Dev_or_Path n
6039       | FileIn n
6040       | FileOut n
6041       | BufferIn n ->
6042           (* guestfish doesn't support string escaping, so neither do we *)
6043           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6044       | OptString n ->                  (* string option *)
6045           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6046           pr "    else printf (\" null\");\n"
6047       | StringList n
6048       | DeviceList n ->                 (* string list *)
6049           pr "    putchar (' ');\n";
6050           pr "    putchar ('\"');\n";
6051           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6052           pr "      if (i > 0) putchar (' ');\n";
6053           pr "      fputs (%s[i], stdout);\n" n;
6054           pr "    }\n";
6055           pr "    putchar ('\"');\n";
6056       | Bool n ->                       (* boolean *)
6057           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6058       | Int n ->                        (* int *)
6059           pr "    printf (\" %%d\", %s);\n" n
6060       | Int64 n ->
6061           pr "    printf (\" %%\" PRIi64, %s);\n" n
6062     ) (snd style);
6063     pr "    putchar ('\\n');\n";
6064     pr "  }\n";
6065     pr "\n";
6066   in
6067
6068   (* For non-daemon functions, generate a wrapper around each function. *)
6069   List.iter (
6070     fun (shortname, style, _, _, _, _, _) ->
6071       let name = "guestfs_" ^ shortname in
6072
6073       generate_prototype ~extern:false ~semicolon:false ~newline:true
6074         ~handle:"g" name style;
6075       pr "{\n";
6076       check_null_strings shortname style;
6077       trace_call shortname style;
6078       pr "  return guestfs__%s " shortname;
6079       generate_c_call_args ~handle:"g" style;
6080       pr ";\n";
6081       pr "}\n";
6082       pr "\n"
6083   ) non_daemon_functions;
6084
6085   (* Client-side stubs for each function. *)
6086   List.iter (
6087     fun (shortname, style, _, _, _, _, _) ->
6088       let name = "guestfs_" ^ shortname in
6089       let error_code = error_code_of (fst style) in
6090
6091       (* Generate the action stub. *)
6092       generate_prototype ~extern:false ~semicolon:false ~newline:true
6093         ~handle:"g" name style;
6094
6095       pr "{\n";
6096
6097       (match snd style with
6098        | [] -> ()
6099        | _ -> pr "  struct %s_args args;\n" name
6100       );
6101
6102       pr "  guestfs_message_header hdr;\n";
6103       pr "  guestfs_message_error err;\n";
6104       let has_ret =
6105         match fst style with
6106         | RErr -> false
6107         | RConstString _ | RConstOptString _ ->
6108             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6109         | RInt _ | RInt64 _
6110         | RBool _ | RString _ | RStringList _
6111         | RStruct _ | RStructList _
6112         | RHashtable _ | RBufferOut _ ->
6113             pr "  struct %s_ret ret;\n" name;
6114             true in
6115
6116       pr "  int serial;\n";
6117       pr "  int r;\n";
6118       pr "\n";
6119       check_null_strings shortname style;
6120       trace_call shortname style;
6121       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6122         shortname error_code;
6123       pr "  guestfs___set_busy (g);\n";
6124       pr "\n";
6125
6126       (* Send the main header and arguments. *)
6127       (match snd style with
6128        | [] ->
6129            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6130              (String.uppercase shortname)
6131        | args ->
6132            List.iter (
6133              function
6134              | Pathname n | Device n | Dev_or_Path n | String n ->
6135                  pr "  args.%s = (char *) %s;\n" n n
6136              | OptString n ->
6137                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6138              | StringList n | DeviceList n ->
6139                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6140                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6141              | Bool n ->
6142                  pr "  args.%s = %s;\n" n n
6143              | Int n ->
6144                  pr "  args.%s = %s;\n" n n
6145              | Int64 n ->
6146                  pr "  args.%s = %s;\n" n n
6147              | FileIn _ | FileOut _ -> ()
6148              | BufferIn n ->
6149                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6150                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6151                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6152                    shortname;
6153                  pr "    guestfs___end_busy (g);\n";
6154                  pr "    return %s;\n" error_code;
6155                  pr "  }\n";
6156                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6157                  pr "  args.%s.%s_len = %s_size;\n" n n n
6158            ) args;
6159            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6160              (String.uppercase shortname);
6161            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6162              name;
6163       );
6164       pr "  if (serial == -1) {\n";
6165       pr "    guestfs___end_busy (g);\n";
6166       pr "    return %s;\n" error_code;
6167       pr "  }\n";
6168       pr "\n";
6169
6170       (* Send any additional files (FileIn) requested. *)
6171       let need_read_reply_label = ref false in
6172       List.iter (
6173         function
6174         | FileIn n ->
6175             pr "  r = guestfs___send_file (g, %s);\n" n;
6176             pr "  if (r == -1) {\n";
6177             pr "    guestfs___end_busy (g);\n";
6178             pr "    return %s;\n" error_code;
6179             pr "  }\n";
6180             pr "  if (r == -2) /* daemon cancelled */\n";
6181             pr "    goto read_reply;\n";
6182             need_read_reply_label := true;
6183             pr "\n";
6184         | _ -> ()
6185       ) (snd style);
6186
6187       (* Wait for the reply from the remote end. *)
6188       if !need_read_reply_label then pr " read_reply:\n";
6189       pr "  memset (&hdr, 0, sizeof hdr);\n";
6190       pr "  memset (&err, 0, sizeof err);\n";
6191       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6192       pr "\n";
6193       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6194       if not has_ret then
6195         pr "NULL, NULL"
6196       else
6197         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6198       pr ");\n";
6199
6200       pr "  if (r == -1) {\n";
6201       pr "    guestfs___end_busy (g);\n";
6202       pr "    return %s;\n" error_code;
6203       pr "  }\n";
6204       pr "\n";
6205
6206       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6207         (String.uppercase shortname);
6208       pr "    guestfs___end_busy (g);\n";
6209       pr "    return %s;\n" error_code;
6210       pr "  }\n";
6211       pr "\n";
6212
6213       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6214       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6215       pr "    free (err.error_message);\n";
6216       pr "    guestfs___end_busy (g);\n";
6217       pr "    return %s;\n" error_code;
6218       pr "  }\n";
6219       pr "\n";
6220
6221       (* Expecting to receive further files (FileOut)? *)
6222       List.iter (
6223         function
6224         | FileOut n ->
6225             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6226             pr "    guestfs___end_busy (g);\n";
6227             pr "    return %s;\n" error_code;
6228             pr "  }\n";
6229             pr "\n";
6230         | _ -> ()
6231       ) (snd style);
6232
6233       pr "  guestfs___end_busy (g);\n";
6234
6235       (match fst style with
6236        | RErr -> pr "  return 0;\n"
6237        | RInt n | RInt64 n | RBool n ->
6238            pr "  return ret.%s;\n" n
6239        | RConstString _ | RConstOptString _ ->
6240            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6241        | RString n ->
6242            pr "  return ret.%s; /* caller will free */\n" n
6243        | RStringList n | RHashtable n ->
6244            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6245            pr "  ret.%s.%s_val =\n" n n;
6246            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6247            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6248              n n;
6249            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6250            pr "  return ret.%s.%s_val;\n" n n
6251        | RStruct (n, _) ->
6252            pr "  /* caller will free this */\n";
6253            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6254        | RStructList (n, _) ->
6255            pr "  /* caller will free this */\n";
6256            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6257        | RBufferOut n ->
6258            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6259            pr "   * _val might be NULL here.  To make the API saner for\n";
6260            pr "   * callers, we turn this case into a unique pointer (using\n";
6261            pr "   * malloc(1)).\n";
6262            pr "   */\n";
6263            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6264            pr "    *size_r = ret.%s.%s_len;\n" n n;
6265            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6266            pr "  } else {\n";
6267            pr "    free (ret.%s.%s_val);\n" n n;
6268            pr "    char *p = safe_malloc (g, 1);\n";
6269            pr "    *size_r = ret.%s.%s_len;\n" n n;
6270            pr "    return p;\n";
6271            pr "  }\n";
6272       );
6273
6274       pr "}\n\n"
6275   ) daemon_functions;
6276
6277   (* Functions to free structures. *)
6278   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6279   pr " * structure format is identical to the XDR format.  See note in\n";
6280   pr " * generator.ml.\n";
6281   pr " */\n";
6282   pr "\n";
6283
6284   List.iter (
6285     fun (typ, _) ->
6286       pr "void\n";
6287       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6288       pr "{\n";
6289       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6290       pr "  free (x);\n";
6291       pr "}\n";
6292       pr "\n";
6293
6294       pr "void\n";
6295       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6296       pr "{\n";
6297       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6298       pr "  free (x);\n";
6299       pr "}\n";
6300       pr "\n";
6301
6302   ) structs;
6303
6304 (* Generate daemon/actions.h. *)
6305 and generate_daemon_actions_h () =
6306   generate_header CStyle GPLv2plus;
6307
6308   pr "#include \"../src/guestfs_protocol.h\"\n";
6309   pr "\n";
6310
6311   List.iter (
6312     fun (name, style, _, _, _, _, _) ->
6313       generate_prototype
6314         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6315         name style;
6316   ) daemon_functions
6317
6318 (* Generate the linker script which controls the visibility of
6319  * symbols in the public ABI and ensures no other symbols get
6320  * exported accidentally.
6321  *)
6322 and generate_linker_script () =
6323   generate_header HashStyle GPLv2plus;
6324
6325   let globals = [
6326     "guestfs_create";
6327     "guestfs_close";
6328     "guestfs_get_error_handler";
6329     "guestfs_get_out_of_memory_handler";
6330     "guestfs_last_error";
6331     "guestfs_set_close_callback";
6332     "guestfs_set_error_handler";
6333     "guestfs_set_launch_done_callback";
6334     "guestfs_set_log_message_callback";
6335     "guestfs_set_out_of_memory_handler";
6336     "guestfs_set_subprocess_quit_callback";
6337
6338     (* Unofficial parts of the API: the bindings code use these
6339      * functions, so it is useful to export them.
6340      *)
6341     "guestfs_safe_calloc";
6342     "guestfs_safe_malloc";
6343     "guestfs_safe_strdup";
6344     "guestfs_safe_memdup";
6345   ] in
6346   let functions =
6347     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6348       all_functions in
6349   let structs =
6350     List.concat (
6351       List.map (fun (typ, _) ->
6352                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6353         structs
6354     ) in
6355   let globals = List.sort compare (globals @ functions @ structs) in
6356
6357   pr "{\n";
6358   pr "    global:\n";
6359   List.iter (pr "        %s;\n") globals;
6360   pr "\n";
6361
6362   pr "    local:\n";
6363   pr "        *;\n";
6364   pr "};\n"
6365
6366 (* Generate the server-side stubs. *)
6367 and generate_daemon_actions () =
6368   generate_header CStyle GPLv2plus;
6369
6370   pr "#include <config.h>\n";
6371   pr "\n";
6372   pr "#include <stdio.h>\n";
6373   pr "#include <stdlib.h>\n";
6374   pr "#include <string.h>\n";
6375   pr "#include <inttypes.h>\n";
6376   pr "#include <rpc/types.h>\n";
6377   pr "#include <rpc/xdr.h>\n";
6378   pr "\n";
6379   pr "#include \"daemon.h\"\n";
6380   pr "#include \"c-ctype.h\"\n";
6381   pr "#include \"../src/guestfs_protocol.h\"\n";
6382   pr "#include \"actions.h\"\n";
6383   pr "\n";
6384
6385   List.iter (
6386     fun (name, style, _, _, _, _, _) ->
6387       (* Generate server-side stubs. *)
6388       pr "static void %s_stub (XDR *xdr_in)\n" name;
6389       pr "{\n";
6390       let error_code =
6391         match fst style with
6392         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6393         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6394         | RBool _ -> pr "  int r;\n"; "-1"
6395         | RConstString _ | RConstOptString _ ->
6396             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6397         | RString _ -> pr "  char *r;\n"; "NULL"
6398         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6399         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6400         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6401         | RBufferOut _ ->
6402             pr "  size_t size = 1;\n";
6403             pr "  char *r;\n";
6404             "NULL" in
6405
6406       (match snd style with
6407        | [] -> ()
6408        | args ->
6409            pr "  struct guestfs_%s_args args;\n" name;
6410            List.iter (
6411              function
6412              | Device n | Dev_or_Path n
6413              | Pathname n
6414              | String n -> ()
6415              | OptString n -> pr "  char *%s;\n" n
6416              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6417              | Bool n -> pr "  int %s;\n" n
6418              | Int n -> pr "  int %s;\n" n
6419              | Int64 n -> pr "  int64_t %s;\n" n
6420              | FileIn _ | FileOut _ -> ()
6421              | BufferIn n ->
6422                  pr "  const char *%s;\n" n;
6423                  pr "  size_t %s_size;\n" n
6424            ) args
6425       );
6426       pr "\n";
6427
6428       let is_filein =
6429         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6430
6431       (match snd style with
6432        | [] -> ()
6433        | args ->
6434            pr "  memset (&args, 0, sizeof args);\n";
6435            pr "\n";
6436            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6437            if is_filein then
6438              pr "    if (cancel_receive () != -2)\n";
6439            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6440            pr "    goto done;\n";
6441            pr "  }\n";
6442            let pr_args n =
6443              pr "  char *%s = args.%s;\n" n n
6444            in
6445            let pr_list_handling_code n =
6446              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6447              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6448              pr "  if (%s == NULL) {\n" n;
6449              if is_filein then
6450                pr "    if (cancel_receive () != -2)\n";
6451              pr "      reply_with_perror (\"realloc\");\n";
6452              pr "    goto done;\n";
6453              pr "  }\n";
6454              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6455              pr "  args.%s.%s_val = %s;\n" n n n;
6456            in
6457            List.iter (
6458              function
6459              | Pathname n ->
6460                  pr_args n;
6461                  pr "  ABS_PATH (%s, %s, goto done);\n"
6462                    n (if is_filein then "cancel_receive ()" else "0");
6463              | Device n ->
6464                  pr_args n;
6465                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6466                    n (if is_filein then "cancel_receive ()" else "0");
6467              | Dev_or_Path n ->
6468                  pr_args n;
6469                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6470                    n (if is_filein then "cancel_receive ()" else "0");
6471              | String n -> pr_args n
6472              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6473              | StringList n ->
6474                  pr_list_handling_code n;
6475              | DeviceList n ->
6476                  pr_list_handling_code n;
6477                  pr "  /* Ensure that each is a device,\n";
6478                  pr "   * and perform device name translation.\n";
6479                  pr "   */\n";
6480                  pr "  {\n";
6481                  pr "    size_t i;\n";
6482                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6483                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6484                    (if is_filein then "cancel_receive ()" else "0");
6485                  pr "  }\n";
6486              | Bool n -> pr "  %s = args.%s;\n" n n
6487              | Int n -> pr "  %s = args.%s;\n" n n
6488              | Int64 n -> pr "  %s = args.%s;\n" n n
6489              | FileIn _ | FileOut _ -> ()
6490              | BufferIn n ->
6491                  pr "  %s = args.%s.%s_val;\n" n n n;
6492                  pr "  %s_size = args.%s.%s_len;\n" n n n
6493            ) args;
6494            pr "\n"
6495       );
6496
6497       (* this is used at least for do_equal *)
6498       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6499         (* Emit NEED_ROOT just once, even when there are two or
6500            more Pathname args *)
6501         pr "  NEED_ROOT (%s, goto done);\n"
6502           (if is_filein then "cancel_receive ()" else "0");
6503       );
6504
6505       (* Don't want to call the impl with any FileIn or FileOut
6506        * parameters, since these go "outside" the RPC protocol.
6507        *)
6508       let args' =
6509         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6510           (snd style) in
6511       pr "  r = do_%s " name;
6512       generate_c_call_args (fst style, args');
6513       pr ";\n";
6514
6515       (match fst style with
6516        | RErr | RInt _ | RInt64 _ | RBool _
6517        | RConstString _ | RConstOptString _
6518        | RString _ | RStringList _ | RHashtable _
6519        | RStruct (_, _) | RStructList (_, _) ->
6520            pr "  if (r == %s)\n" error_code;
6521            pr "    /* do_%s has already called reply_with_error */\n" name;
6522            pr "    goto done;\n";
6523            pr "\n"
6524        | RBufferOut _ ->
6525            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6526            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6527            pr "   */\n";
6528            pr "  if (size == 1 && r == %s)\n" error_code;
6529            pr "    /* do_%s has already called reply_with_error */\n" name;
6530            pr "    goto done;\n";
6531            pr "\n"
6532       );
6533
6534       (* If there are any FileOut parameters, then the impl must
6535        * send its own reply.
6536        *)
6537       let no_reply =
6538         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6539       if no_reply then
6540         pr "  /* do_%s has already sent a reply */\n" name
6541       else (
6542         match fst style with
6543         | RErr -> pr "  reply (NULL, NULL);\n"
6544         | RInt n | RInt64 n | RBool n ->
6545             pr "  struct guestfs_%s_ret ret;\n" name;
6546             pr "  ret.%s = r;\n" n;
6547             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6548               name
6549         | RConstString _ | RConstOptString _ ->
6550             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6551         | RString n ->
6552             pr "  struct guestfs_%s_ret ret;\n" name;
6553             pr "  ret.%s = r;\n" n;
6554             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6555               name;
6556             pr "  free (r);\n"
6557         | RStringList n | RHashtable n ->
6558             pr "  struct guestfs_%s_ret ret;\n" name;
6559             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6560             pr "  ret.%s.%s_val = r;\n" n n;
6561             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6562               name;
6563             pr "  free_strings (r);\n"
6564         | RStruct (n, _) ->
6565             pr "  struct guestfs_%s_ret ret;\n" name;
6566             pr "  ret.%s = *r;\n" n;
6567             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6568               name;
6569             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6570               name
6571         | RStructList (n, _) ->
6572             pr "  struct guestfs_%s_ret ret;\n" name;
6573             pr "  ret.%s = *r;\n" n;
6574             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6575               name;
6576             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6577               name
6578         | RBufferOut n ->
6579             pr "  struct guestfs_%s_ret ret;\n" name;
6580             pr "  ret.%s.%s_val = r;\n" n n;
6581             pr "  ret.%s.%s_len = size;\n" n n;
6582             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6583               name;
6584             pr "  free (r);\n"
6585       );
6586
6587       (* Free the args. *)
6588       pr "done:\n";
6589       (match snd style with
6590        | [] -> ()
6591        | _ ->
6592            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6593              name
6594       );
6595       pr "  return;\n";
6596       pr "}\n\n";
6597   ) daemon_functions;
6598
6599   (* Dispatch function. *)
6600   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6601   pr "{\n";
6602   pr "  switch (proc_nr) {\n";
6603
6604   List.iter (
6605     fun (name, style, _, _, _, _, _) ->
6606       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6607       pr "      %s_stub (xdr_in);\n" name;
6608       pr "      break;\n"
6609   ) daemon_functions;
6610
6611   pr "    default:\n";
6612   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";
6613   pr "  }\n";
6614   pr "}\n";
6615   pr "\n";
6616
6617   (* LVM columns and tokenization functions. *)
6618   (* XXX This generates crap code.  We should rethink how we
6619    * do this parsing.
6620    *)
6621   List.iter (
6622     function
6623     | typ, cols ->
6624         pr "static const char *lvm_%s_cols = \"%s\";\n"
6625           typ (String.concat "," (List.map fst cols));
6626         pr "\n";
6627
6628         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6629         pr "{\n";
6630         pr "  char *tok, *p, *next;\n";
6631         pr "  size_t i, j;\n";
6632         pr "\n";
6633         (*
6634           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6635           pr "\n";
6636         *)
6637         pr "  if (!str) {\n";
6638         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6639         pr "    return -1;\n";
6640         pr "  }\n";
6641         pr "  if (!*str || c_isspace (*str)) {\n";
6642         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6643         pr "    return -1;\n";
6644         pr "  }\n";
6645         pr "  tok = str;\n";
6646         List.iter (
6647           fun (name, coltype) ->
6648             pr "  if (!tok) {\n";
6649             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6650             pr "    return -1;\n";
6651             pr "  }\n";
6652             pr "  p = strchrnul (tok, ',');\n";
6653             pr "  if (*p) next = p+1; else next = NULL;\n";
6654             pr "  *p = '\\0';\n";
6655             (match coltype with
6656              | FString ->
6657                  pr "  r->%s = strdup (tok);\n" name;
6658                  pr "  if (r->%s == NULL) {\n" name;
6659                  pr "    perror (\"strdup\");\n";
6660                  pr "    return -1;\n";
6661                  pr "  }\n"
6662              | FUUID ->
6663                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6664                  pr "    if (tok[j] == '\\0') {\n";
6665                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6666                  pr "      return -1;\n";
6667                  pr "    } else if (tok[j] != '-')\n";
6668                  pr "      r->%s[i++] = tok[j];\n" name;
6669                  pr "  }\n";
6670              | FBytes ->
6671                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6672                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6673                  pr "    return -1;\n";
6674                  pr "  }\n";
6675              | FInt64 ->
6676                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6677                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6678                  pr "    return -1;\n";
6679                  pr "  }\n";
6680              | FOptPercent ->
6681                  pr "  if (tok[0] == '\\0')\n";
6682                  pr "    r->%s = -1;\n" name;
6683                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6684                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6685                  pr "    return -1;\n";
6686                  pr "  }\n";
6687              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6688                  assert false (* can never be an LVM column *)
6689             );
6690             pr "  tok = next;\n";
6691         ) cols;
6692
6693         pr "  if (tok != NULL) {\n";
6694         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6695         pr "    return -1;\n";
6696         pr "  }\n";
6697         pr "  return 0;\n";
6698         pr "}\n";
6699         pr "\n";
6700
6701         pr "guestfs_int_lvm_%s_list *\n" typ;
6702         pr "parse_command_line_%ss (void)\n" typ;
6703         pr "{\n";
6704         pr "  char *out, *err;\n";
6705         pr "  char *p, *pend;\n";
6706         pr "  int r, i;\n";
6707         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6708         pr "  void *newp;\n";
6709         pr "\n";
6710         pr "  ret = malloc (sizeof *ret);\n";
6711         pr "  if (!ret) {\n";
6712         pr "    reply_with_perror (\"malloc\");\n";
6713         pr "    return NULL;\n";
6714         pr "  }\n";
6715         pr "\n";
6716         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6717         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6718         pr "\n";
6719         pr "  r = command (&out, &err,\n";
6720         pr "           \"lvm\", \"%ss\",\n" typ;
6721         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6722         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6723         pr "  if (r == -1) {\n";
6724         pr "    reply_with_error (\"%%s\", err);\n";
6725         pr "    free (out);\n";
6726         pr "    free (err);\n";
6727         pr "    free (ret);\n";
6728         pr "    return NULL;\n";
6729         pr "  }\n";
6730         pr "\n";
6731         pr "  free (err);\n";
6732         pr "\n";
6733         pr "  /* Tokenize each line of the output. */\n";
6734         pr "  p = out;\n";
6735         pr "  i = 0;\n";
6736         pr "  while (p) {\n";
6737         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6738         pr "    if (pend) {\n";
6739         pr "      *pend = '\\0';\n";
6740         pr "      pend++;\n";
6741         pr "    }\n";
6742         pr "\n";
6743         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6744         pr "      p++;\n";
6745         pr "\n";
6746         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6747         pr "      p = pend;\n";
6748         pr "      continue;\n";
6749         pr "    }\n";
6750         pr "\n";
6751         pr "    /* Allocate some space to store this next entry. */\n";
6752         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6753         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6754         pr "    if (newp == NULL) {\n";
6755         pr "      reply_with_perror (\"realloc\");\n";
6756         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6757         pr "      free (ret);\n";
6758         pr "      free (out);\n";
6759         pr "      return NULL;\n";
6760         pr "    }\n";
6761         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6762         pr "\n";
6763         pr "    /* Tokenize the next entry. */\n";
6764         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6765         pr "    if (r == -1) {\n";
6766         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6767         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6768         pr "      free (ret);\n";
6769         pr "      free (out);\n";
6770         pr "      return NULL;\n";
6771         pr "    }\n";
6772         pr "\n";
6773         pr "    ++i;\n";
6774         pr "    p = pend;\n";
6775         pr "  }\n";
6776         pr "\n";
6777         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6778         pr "\n";
6779         pr "  free (out);\n";
6780         pr "  return ret;\n";
6781         pr "}\n"
6782
6783   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6784
6785 (* Generate a list of function names, for debugging in the daemon.. *)
6786 and generate_daemon_names () =
6787   generate_header CStyle GPLv2plus;
6788
6789   pr "#include <config.h>\n";
6790   pr "\n";
6791   pr "#include \"daemon.h\"\n";
6792   pr "\n";
6793
6794   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6795   pr "const char *function_names[] = {\n";
6796   List.iter (
6797     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6798   ) daemon_functions;
6799   pr "};\n";
6800
6801 (* Generate the optional groups for the daemon to implement
6802  * guestfs_available.
6803  *)
6804 and generate_daemon_optgroups_c () =
6805   generate_header CStyle GPLv2plus;
6806
6807   pr "#include <config.h>\n";
6808   pr "\n";
6809   pr "#include \"daemon.h\"\n";
6810   pr "#include \"optgroups.h\"\n";
6811   pr "\n";
6812
6813   pr "struct optgroup optgroups[] = {\n";
6814   List.iter (
6815     fun (group, _) ->
6816       pr "  { \"%s\", optgroup_%s_available },\n" group group
6817   ) optgroups;
6818   pr "  { NULL, NULL }\n";
6819   pr "};\n"
6820
6821 and generate_daemon_optgroups_h () =
6822   generate_header CStyle GPLv2plus;
6823
6824   List.iter (
6825     fun (group, _) ->
6826       pr "extern int optgroup_%s_available (void);\n" group
6827   ) optgroups
6828
6829 (* Generate the tests. *)
6830 and generate_tests () =
6831   generate_header CStyle GPLv2plus;
6832
6833   pr "\
6834 #include <stdio.h>
6835 #include <stdlib.h>
6836 #include <string.h>
6837 #include <unistd.h>
6838 #include <sys/types.h>
6839 #include <fcntl.h>
6840
6841 #include \"guestfs.h\"
6842 #include \"guestfs-internal.h\"
6843
6844 static guestfs_h *g;
6845 static int suppress_error = 0;
6846
6847 static void print_error (guestfs_h *g, void *data, const char *msg)
6848 {
6849   if (!suppress_error)
6850     fprintf (stderr, \"%%s\\n\", msg);
6851 }
6852
6853 /* FIXME: nearly identical code appears in fish.c */
6854 static void print_strings (char *const *argv)
6855 {
6856   size_t argc;
6857
6858   for (argc = 0; argv[argc] != NULL; ++argc)
6859     printf (\"\\t%%s\\n\", argv[argc]);
6860 }
6861
6862 /*
6863 static void print_table (char const *const *argv)
6864 {
6865   size_t i;
6866
6867   for (i = 0; argv[i] != NULL; i += 2)
6868     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6869 }
6870 */
6871
6872 static int
6873 is_available (const char *group)
6874 {
6875   const char *groups[] = { group, NULL };
6876   int r;
6877
6878   suppress_error = 1;
6879   r = guestfs_available (g, (char **) groups);
6880   suppress_error = 0;
6881
6882   return r == 0;
6883 }
6884
6885 static void
6886 incr (guestfs_h *g, void *iv)
6887 {
6888   int *i = (int *) iv;
6889   (*i)++;
6890 }
6891
6892 ";
6893
6894   (* Generate a list of commands which are not tested anywhere. *)
6895   pr "static void no_test_warnings (void)\n";
6896   pr "{\n";
6897
6898   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6899   List.iter (
6900     fun (_, _, _, _, tests, _, _) ->
6901       let tests = filter_map (
6902         function
6903         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6904         | (_, Disabled, _) -> None
6905       ) tests in
6906       let seq = List.concat (List.map seq_of_test tests) in
6907       let cmds_tested = List.map List.hd seq in
6908       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6909   ) all_functions;
6910
6911   List.iter (
6912     fun (name, _, _, _, _, _, _) ->
6913       if not (Hashtbl.mem hash name) then
6914         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6915   ) all_functions;
6916
6917   pr "}\n";
6918   pr "\n";
6919
6920   (* Generate the actual tests.  Note that we generate the tests
6921    * in reverse order, deliberately, so that (in general) the
6922    * newest tests run first.  This makes it quicker and easier to
6923    * debug them.
6924    *)
6925   let test_names =
6926     List.map (
6927       fun (name, _, _, flags, tests, _, _) ->
6928         mapi (generate_one_test name flags) tests
6929     ) (List.rev all_functions) in
6930   let test_names = List.concat test_names in
6931   let nr_tests = List.length test_names in
6932
6933   pr "\
6934 int main (int argc, char *argv[])
6935 {
6936   char c = 0;
6937   unsigned long int n_failed = 0;
6938   const char *filename;
6939   int fd;
6940   int nr_tests, test_num = 0;
6941
6942   setbuf (stdout, NULL);
6943
6944   no_test_warnings ();
6945
6946   g = guestfs_create ();
6947   if (g == NULL) {
6948     printf (\"guestfs_create FAILED\\n\");
6949     exit (EXIT_FAILURE);
6950   }
6951
6952   guestfs_set_error_handler (g, print_error, NULL);
6953
6954   guestfs_set_path (g, \"../appliance\");
6955
6956   filename = \"test1.img\";
6957   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6958   if (fd == -1) {
6959     perror (filename);
6960     exit (EXIT_FAILURE);
6961   }
6962   if (lseek (fd, %d, SEEK_SET) == -1) {
6963     perror (\"lseek\");
6964     close (fd);
6965     unlink (filename);
6966     exit (EXIT_FAILURE);
6967   }
6968   if (write (fd, &c, 1) == -1) {
6969     perror (\"write\");
6970     close (fd);
6971     unlink (filename);
6972     exit (EXIT_FAILURE);
6973   }
6974   if (close (fd) == -1) {
6975     perror (filename);
6976     unlink (filename);
6977     exit (EXIT_FAILURE);
6978   }
6979   if (guestfs_add_drive (g, filename) == -1) {
6980     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6981     exit (EXIT_FAILURE);
6982   }
6983
6984   filename = \"test2.img\";
6985   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6986   if (fd == -1) {
6987     perror (filename);
6988     exit (EXIT_FAILURE);
6989   }
6990   if (lseek (fd, %d, SEEK_SET) == -1) {
6991     perror (\"lseek\");
6992     close (fd);
6993     unlink (filename);
6994     exit (EXIT_FAILURE);
6995   }
6996   if (write (fd, &c, 1) == -1) {
6997     perror (\"write\");
6998     close (fd);
6999     unlink (filename);
7000     exit (EXIT_FAILURE);
7001   }
7002   if (close (fd) == -1) {
7003     perror (filename);
7004     unlink (filename);
7005     exit (EXIT_FAILURE);
7006   }
7007   if (guestfs_add_drive (g, filename) == -1) {
7008     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7009     exit (EXIT_FAILURE);
7010   }
7011
7012   filename = \"test3.img\";
7013   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7014   if (fd == -1) {
7015     perror (filename);
7016     exit (EXIT_FAILURE);
7017   }
7018   if (lseek (fd, %d, SEEK_SET) == -1) {
7019     perror (\"lseek\");
7020     close (fd);
7021     unlink (filename);
7022     exit (EXIT_FAILURE);
7023   }
7024   if (write (fd, &c, 1) == -1) {
7025     perror (\"write\");
7026     close (fd);
7027     unlink (filename);
7028     exit (EXIT_FAILURE);
7029   }
7030   if (close (fd) == -1) {
7031     perror (filename);
7032     unlink (filename);
7033     exit (EXIT_FAILURE);
7034   }
7035   if (guestfs_add_drive (g, filename) == -1) {
7036     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7037     exit (EXIT_FAILURE);
7038   }
7039
7040   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7041     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7042     exit (EXIT_FAILURE);
7043   }
7044
7045   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7046   alarm (600);
7047
7048   if (guestfs_launch (g) == -1) {
7049     printf (\"guestfs_launch FAILED\\n\");
7050     exit (EXIT_FAILURE);
7051   }
7052
7053   /* Cancel previous alarm. */
7054   alarm (0);
7055
7056   nr_tests = %d;
7057
7058 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7059
7060   iteri (
7061     fun i test_name ->
7062       pr "  test_num++;\n";
7063       pr "  if (guestfs_get_verbose (g))\n";
7064       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7065       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7066       pr "  if (%s () == -1) {\n" test_name;
7067       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7068       pr "    n_failed++;\n";
7069       pr "  }\n";
7070   ) test_names;
7071   pr "\n";
7072
7073   pr "  /* Check close callback is called. */
7074   int close_sentinel = 1;
7075   guestfs_set_close_callback (g, incr, &close_sentinel);
7076
7077   guestfs_close (g);
7078
7079   if (close_sentinel != 2) {
7080     fprintf (stderr, \"close callback was not called\\n\");
7081     exit (EXIT_FAILURE);
7082   }
7083
7084   unlink (\"test1.img\");
7085   unlink (\"test2.img\");
7086   unlink (\"test3.img\");
7087
7088 ";
7089
7090   pr "  if (n_failed > 0) {\n";
7091   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7092   pr "    exit (EXIT_FAILURE);\n";
7093   pr "  }\n";
7094   pr "\n";
7095
7096   pr "  exit (EXIT_SUCCESS);\n";
7097   pr "}\n"
7098
7099 and generate_one_test name flags i (init, prereq, test) =
7100   let test_name = sprintf "test_%s_%d" name i in
7101
7102   pr "\
7103 static int %s_skip (void)
7104 {
7105   const char *str;
7106
7107   str = getenv (\"TEST_ONLY\");
7108   if (str)
7109     return strstr (str, \"%s\") == NULL;
7110   str = getenv (\"SKIP_%s\");
7111   if (str && STREQ (str, \"1\")) return 1;
7112   str = getenv (\"SKIP_TEST_%s\");
7113   if (str && STREQ (str, \"1\")) return 1;
7114   return 0;
7115 }
7116
7117 " test_name name (String.uppercase test_name) (String.uppercase name);
7118
7119   (match prereq with
7120    | Disabled | Always | IfAvailable _ -> ()
7121    | If code | Unless code ->
7122        pr "static int %s_prereq (void)\n" test_name;
7123        pr "{\n";
7124        pr "  %s\n" code;
7125        pr "}\n";
7126        pr "\n";
7127   );
7128
7129   pr "\
7130 static int %s (void)
7131 {
7132   if (%s_skip ()) {
7133     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7134     return 0;
7135   }
7136
7137 " test_name test_name test_name;
7138
7139   (* Optional functions should only be tested if the relevant
7140    * support is available in the daemon.
7141    *)
7142   List.iter (
7143     function
7144     | Optional group ->
7145         pr "  if (!is_available (\"%s\")) {\n" group;
7146         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7147         pr "    return 0;\n";
7148         pr "  }\n";
7149     | _ -> ()
7150   ) flags;
7151
7152   (match prereq with
7153    | Disabled ->
7154        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7155    | If _ ->
7156        pr "  if (! %s_prereq ()) {\n" test_name;
7157        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7158        pr "    return 0;\n";
7159        pr "  }\n";
7160        pr "\n";
7161        generate_one_test_body name i test_name init test;
7162    | Unless _ ->
7163        pr "  if (%s_prereq ()) {\n" test_name;
7164        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7165        pr "    return 0;\n";
7166        pr "  }\n";
7167        pr "\n";
7168        generate_one_test_body name i test_name init test;
7169    | IfAvailable group ->
7170        pr "  if (!is_available (\"%s\")) {\n" group;
7171        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7172        pr "    return 0;\n";
7173        pr "  }\n";
7174        pr "\n";
7175        generate_one_test_body name i test_name init test;
7176    | Always ->
7177        generate_one_test_body name i test_name init test
7178   );
7179
7180   pr "  return 0;\n";
7181   pr "}\n";
7182   pr "\n";
7183   test_name
7184
7185 and generate_one_test_body name i test_name init test =
7186   (match init with
7187    | InitNone (* XXX at some point, InitNone and InitEmpty became
7188                * folded together as the same thing.  Really we should
7189                * make InitNone do nothing at all, but the tests may
7190                * need to be checked to make sure this is OK.
7191                *)
7192    | InitEmpty ->
7193        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7194        List.iter (generate_test_command_call test_name)
7195          [["blockdev_setrw"; "/dev/sda"];
7196           ["umount_all"];
7197           ["lvm_remove_all"]]
7198    | InitPartition ->
7199        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7200        List.iter (generate_test_command_call test_name)
7201          [["blockdev_setrw"; "/dev/sda"];
7202           ["umount_all"];
7203           ["lvm_remove_all"];
7204           ["part_disk"; "/dev/sda"; "mbr"]]
7205    | InitBasicFS ->
7206        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7207        List.iter (generate_test_command_call test_name)
7208          [["blockdev_setrw"; "/dev/sda"];
7209           ["umount_all"];
7210           ["lvm_remove_all"];
7211           ["part_disk"; "/dev/sda"; "mbr"];
7212           ["mkfs"; "ext2"; "/dev/sda1"];
7213           ["mount_options"; ""; "/dev/sda1"; "/"]]
7214    | InitBasicFSonLVM ->
7215        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7216          test_name;
7217        List.iter (generate_test_command_call test_name)
7218          [["blockdev_setrw"; "/dev/sda"];
7219           ["umount_all"];
7220           ["lvm_remove_all"];
7221           ["part_disk"; "/dev/sda"; "mbr"];
7222           ["pvcreate"; "/dev/sda1"];
7223           ["vgcreate"; "VG"; "/dev/sda1"];
7224           ["lvcreate"; "LV"; "VG"; "8"];
7225           ["mkfs"; "ext2"; "/dev/VG/LV"];
7226           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7227    | InitISOFS ->
7228        pr "  /* InitISOFS for %s */\n" test_name;
7229        List.iter (generate_test_command_call test_name)
7230          [["blockdev_setrw"; "/dev/sda"];
7231           ["umount_all"];
7232           ["lvm_remove_all"];
7233           ["mount_ro"; "/dev/sdd"; "/"]]
7234   );
7235
7236   let get_seq_last = function
7237     | [] ->
7238         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7239           test_name
7240     | seq ->
7241         let seq = List.rev seq in
7242         List.rev (List.tl seq), List.hd seq
7243   in
7244
7245   match test with
7246   | TestRun seq ->
7247       pr "  /* TestRun for %s (%d) */\n" name i;
7248       List.iter (generate_test_command_call test_name) seq
7249   | TestOutput (seq, expected) ->
7250       pr "  /* TestOutput for %s (%d) */\n" name i;
7251       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7252       let seq, last = get_seq_last seq in
7253       let test () =
7254         pr "    if (STRNEQ (r, expected)) {\n";
7255         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7256         pr "      return -1;\n";
7257         pr "    }\n"
7258       in
7259       List.iter (generate_test_command_call test_name) seq;
7260       generate_test_command_call ~test test_name last
7261   | TestOutputList (seq, expected) ->
7262       pr "  /* TestOutputList for %s (%d) */\n" name i;
7263       let seq, last = get_seq_last seq in
7264       let test () =
7265         iteri (
7266           fun i str ->
7267             pr "    if (!r[%d]) {\n" i;
7268             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7269             pr "      print_strings (r);\n";
7270             pr "      return -1;\n";
7271             pr "    }\n";
7272             pr "    {\n";
7273             pr "      const char *expected = \"%s\";\n" (c_quote str);
7274             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7275             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7276             pr "        return -1;\n";
7277             pr "      }\n";
7278             pr "    }\n"
7279         ) expected;
7280         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7281         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7282           test_name;
7283         pr "      print_strings (r);\n";
7284         pr "      return -1;\n";
7285         pr "    }\n"
7286       in
7287       List.iter (generate_test_command_call test_name) seq;
7288       generate_test_command_call ~test test_name last
7289   | TestOutputListOfDevices (seq, expected) ->
7290       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7291       let seq, last = get_seq_last seq in
7292       let test () =
7293         iteri (
7294           fun i str ->
7295             pr "    if (!r[%d]) {\n" i;
7296             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7297             pr "      print_strings (r);\n";
7298             pr "      return -1;\n";
7299             pr "    }\n";
7300             pr "    {\n";
7301             pr "      const char *expected = \"%s\";\n" (c_quote str);
7302             pr "      r[%d][5] = 's';\n" i;
7303             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7304             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7305             pr "        return -1;\n";
7306             pr "      }\n";
7307             pr "    }\n"
7308         ) expected;
7309         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7310         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7311           test_name;
7312         pr "      print_strings (r);\n";
7313         pr "      return -1;\n";
7314         pr "    }\n"
7315       in
7316       List.iter (generate_test_command_call test_name) seq;
7317       generate_test_command_call ~test test_name last
7318   | TestOutputInt (seq, expected) ->
7319       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7320       let seq, last = get_seq_last seq in
7321       let test () =
7322         pr "    if (r != %d) {\n" expected;
7323         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7324           test_name expected;
7325         pr "               (int) r);\n";
7326         pr "      return -1;\n";
7327         pr "    }\n"
7328       in
7329       List.iter (generate_test_command_call test_name) seq;
7330       generate_test_command_call ~test test_name last
7331   | TestOutputIntOp (seq, op, expected) ->
7332       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7333       let seq, last = get_seq_last seq in
7334       let test () =
7335         pr "    if (! (r %s %d)) {\n" op expected;
7336         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7337           test_name op expected;
7338         pr "               (int) r);\n";
7339         pr "      return -1;\n";
7340         pr "    }\n"
7341       in
7342       List.iter (generate_test_command_call test_name) seq;
7343       generate_test_command_call ~test test_name last
7344   | TestOutputTrue seq ->
7345       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7346       let seq, last = get_seq_last seq in
7347       let test () =
7348         pr "    if (!r) {\n";
7349         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7350           test_name;
7351         pr "      return -1;\n";
7352         pr "    }\n"
7353       in
7354       List.iter (generate_test_command_call test_name) seq;
7355       generate_test_command_call ~test test_name last
7356   | TestOutputFalse seq ->
7357       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7358       let seq, last = get_seq_last seq in
7359       let test () =
7360         pr "    if (r) {\n";
7361         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7362           test_name;
7363         pr "      return -1;\n";
7364         pr "    }\n"
7365       in
7366       List.iter (generate_test_command_call test_name) seq;
7367       generate_test_command_call ~test test_name last
7368   | TestOutputLength (seq, expected) ->
7369       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7370       let seq, last = get_seq_last seq in
7371       let test () =
7372         pr "    int j;\n";
7373         pr "    for (j = 0; j < %d; ++j)\n" expected;
7374         pr "      if (r[j] == NULL) {\n";
7375         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7376           test_name;
7377         pr "        print_strings (r);\n";
7378         pr "        return -1;\n";
7379         pr "      }\n";
7380         pr "    if (r[j] != NULL) {\n";
7381         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7382           test_name;
7383         pr "      print_strings (r);\n";
7384         pr "      return -1;\n";
7385         pr "    }\n"
7386       in
7387       List.iter (generate_test_command_call test_name) seq;
7388       generate_test_command_call ~test test_name last
7389   | TestOutputBuffer (seq, expected) ->
7390       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7391       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7392       let seq, last = get_seq_last seq in
7393       let len = String.length expected in
7394       let test () =
7395         pr "    if (size != %d) {\n" len;
7396         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7397         pr "      return -1;\n";
7398         pr "    }\n";
7399         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7400         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7401         pr "      return -1;\n";
7402         pr "    }\n"
7403       in
7404       List.iter (generate_test_command_call test_name) seq;
7405       generate_test_command_call ~test test_name last
7406   | TestOutputStruct (seq, checks) ->
7407       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7408       let seq, last = get_seq_last seq in
7409       let test () =
7410         List.iter (
7411           function
7412           | CompareWithInt (field, expected) ->
7413               pr "    if (r->%s != %d) {\n" field expected;
7414               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7415                 test_name field expected;
7416               pr "               (int) r->%s);\n" field;
7417               pr "      return -1;\n";
7418               pr "    }\n"
7419           | CompareWithIntOp (field, op, expected) ->
7420               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7421               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7422                 test_name field op expected;
7423               pr "               (int) r->%s);\n" field;
7424               pr "      return -1;\n";
7425               pr "    }\n"
7426           | CompareWithString (field, expected) ->
7427               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7428               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7429                 test_name field expected;
7430               pr "               r->%s);\n" field;
7431               pr "      return -1;\n";
7432               pr "    }\n"
7433           | CompareFieldsIntEq (field1, field2) ->
7434               pr "    if (r->%s != r->%s) {\n" field1 field2;
7435               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7436                 test_name field1 field2;
7437               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7438               pr "      return -1;\n";
7439               pr "    }\n"
7440           | CompareFieldsStrEq (field1, field2) ->
7441               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7442               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7443                 test_name field1 field2;
7444               pr "               r->%s, r->%s);\n" field1 field2;
7445               pr "      return -1;\n";
7446               pr "    }\n"
7447         ) checks
7448       in
7449       List.iter (generate_test_command_call test_name) seq;
7450       generate_test_command_call ~test test_name last
7451   | TestLastFail seq ->
7452       pr "  /* TestLastFail for %s (%d) */\n" name i;
7453       let seq, last = get_seq_last seq in
7454       List.iter (generate_test_command_call test_name) seq;
7455       generate_test_command_call test_name ~expect_error:true last
7456
7457 (* Generate the code to run a command, leaving the result in 'r'.
7458  * If you expect to get an error then you should set expect_error:true.
7459  *)
7460 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7461   match cmd with
7462   | [] -> assert false
7463   | name :: args ->
7464       (* Look up the command to find out what args/ret it has. *)
7465       let style =
7466         try
7467           let _, style, _, _, _, _, _ =
7468             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7469           style
7470         with Not_found ->
7471           failwithf "%s: in test, command %s was not found" test_name name in
7472
7473       if List.length (snd style) <> List.length args then
7474         failwithf "%s: in test, wrong number of args given to %s"
7475           test_name name;
7476
7477       pr "  {\n";
7478
7479       List.iter (
7480         function
7481         | OptString n, "NULL" -> ()
7482         | Pathname n, arg
7483         | Device n, arg
7484         | Dev_or_Path n, arg
7485         | String n, arg
7486         | OptString n, arg ->
7487             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7488         | BufferIn n, arg ->
7489             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7490             pr "    size_t %s_size = %d;\n" n (String.length arg)
7491         | Int _, _
7492         | Int64 _, _
7493         | Bool _, _
7494         | FileIn _, _ | FileOut _, _ -> ()
7495         | StringList n, "" | DeviceList n, "" ->
7496             pr "    const char *const %s[1] = { NULL };\n" n
7497         | StringList n, arg | DeviceList n, arg ->
7498             let strs = string_split " " arg in
7499             iteri (
7500               fun i str ->
7501                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7502             ) strs;
7503             pr "    const char *const %s[] = {\n" n;
7504             iteri (
7505               fun i _ -> pr "      %s_%d,\n" n i
7506             ) strs;
7507             pr "      NULL\n";
7508             pr "    };\n";
7509       ) (List.combine (snd style) args);
7510
7511       let error_code =
7512         match fst style with
7513         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7514         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7515         | RConstString _ | RConstOptString _ ->
7516             pr "    const char *r;\n"; "NULL"
7517         | RString _ -> pr "    char *r;\n"; "NULL"
7518         | RStringList _ | RHashtable _ ->
7519             pr "    char **r;\n";
7520             pr "    size_t i;\n";
7521             "NULL"
7522         | RStruct (_, typ) ->
7523             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7524         | RStructList (_, typ) ->
7525             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7526         | RBufferOut _ ->
7527             pr "    char *r;\n";
7528             pr "    size_t size;\n";
7529             "NULL" in
7530
7531       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7532       pr "    r = guestfs_%s (g" name;
7533
7534       (* Generate the parameters. *)
7535       List.iter (
7536         function
7537         | OptString _, "NULL" -> pr ", NULL"
7538         | Pathname n, _
7539         | Device n, _ | Dev_or_Path n, _
7540         | String n, _
7541         | OptString n, _ ->
7542             pr ", %s" n
7543         | BufferIn n, _ ->
7544             pr ", %s, %s_size" n n
7545         | FileIn _, arg | FileOut _, arg ->
7546             pr ", \"%s\"" (c_quote arg)
7547         | StringList n, _ | DeviceList n, _ ->
7548             pr ", (char **) %s" n
7549         | Int _, arg ->
7550             let i =
7551               try int_of_string arg
7552               with Failure "int_of_string" ->
7553                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7554             pr ", %d" i
7555         | Int64 _, arg ->
7556             let i =
7557               try Int64.of_string arg
7558               with Failure "int_of_string" ->
7559                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7560             pr ", %Ld" i
7561         | Bool _, arg ->
7562             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7563       ) (List.combine (snd style) args);
7564
7565       (match fst style with
7566        | RBufferOut _ -> pr ", &size"
7567        | _ -> ()
7568       );
7569
7570       pr ");\n";
7571
7572       if not expect_error then
7573         pr "    if (r == %s)\n" error_code
7574       else
7575         pr "    if (r != %s)\n" error_code;
7576       pr "      return -1;\n";
7577
7578       (* Insert the test code. *)
7579       (match test with
7580        | None -> ()
7581        | Some f -> f ()
7582       );
7583
7584       (match fst style with
7585        | RErr | RInt _ | RInt64 _ | RBool _
7586        | RConstString _ | RConstOptString _ -> ()
7587        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7588        | RStringList _ | RHashtable _ ->
7589            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7590            pr "      free (r[i]);\n";
7591            pr "    free (r);\n"
7592        | RStruct (_, typ) ->
7593            pr "    guestfs_free_%s (r);\n" typ
7594        | RStructList (_, typ) ->
7595            pr "    guestfs_free_%s_list (r);\n" typ
7596       );
7597
7598       pr "  }\n"
7599
7600 and c_quote str =
7601   let str = replace_str str "\r" "\\r" in
7602   let str = replace_str str "\n" "\\n" in
7603   let str = replace_str str "\t" "\\t" in
7604   let str = replace_str str "\000" "\\0" in
7605   str
7606
7607 (* Generate a lot of different functions for guestfish. *)
7608 and generate_fish_cmds () =
7609   generate_header CStyle GPLv2plus;
7610
7611   let all_functions =
7612     List.filter (
7613       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7614     ) all_functions in
7615   let all_functions_sorted =
7616     List.filter (
7617       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7618     ) all_functions_sorted in
7619
7620   pr "#include <config.h>\n";
7621   pr "\n";
7622   pr "#include <stdio.h>\n";
7623   pr "#include <stdlib.h>\n";
7624   pr "#include <string.h>\n";
7625   pr "#include <inttypes.h>\n";
7626   pr "\n";
7627   pr "#include <guestfs.h>\n";
7628   pr "#include \"c-ctype.h\"\n";
7629   pr "#include \"full-write.h\"\n";
7630   pr "#include \"xstrtol.h\"\n";
7631   pr "#include \"fish.h\"\n";
7632   pr "\n";
7633   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7634   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7635   pr "\n";
7636
7637   (* list_commands function, which implements guestfish -h *)
7638   pr "void list_commands (void)\n";
7639   pr "{\n";
7640   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7641   pr "  list_builtin_commands ();\n";
7642   List.iter (
7643     fun (name, _, _, flags, _, shortdesc, _) ->
7644       let name = replace_char name '_' '-' in
7645       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7646         name shortdesc
7647   ) all_functions_sorted;
7648   pr "  printf (\"    %%s\\n\",";
7649   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7650   pr "}\n";
7651   pr "\n";
7652
7653   (* display_command function, which implements guestfish -h cmd *)
7654   pr "int display_command (const char *cmd)\n";
7655   pr "{\n";
7656   List.iter (
7657     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7658       let name2 = replace_char name '_' '-' in
7659       let alias =
7660         try find_map (function FishAlias n -> Some n | _ -> None) flags
7661         with Not_found -> name in
7662       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7663       let synopsis =
7664         match snd style with
7665         | [] -> name2
7666         | args ->
7667             sprintf "%s %s"
7668               name2 (String.concat " " (List.map name_of_argt args)) in
7669
7670       let warnings =
7671         if List.mem ProtocolLimitWarning flags then
7672           ("\n\n" ^ protocol_limit_warning)
7673         else "" in
7674
7675       (* For DangerWillRobinson commands, we should probably have
7676        * guestfish prompt before allowing you to use them (especially
7677        * in interactive mode). XXX
7678        *)
7679       let warnings =
7680         warnings ^
7681           if List.mem DangerWillRobinson flags then
7682             ("\n\n" ^ danger_will_robinson)
7683           else "" in
7684
7685       let warnings =
7686         warnings ^
7687           match deprecation_notice flags with
7688           | None -> ""
7689           | Some txt -> "\n\n" ^ txt in
7690
7691       let describe_alias =
7692         if name <> alias then
7693           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7694         else "" in
7695
7696       pr "  if (";
7697       pr "STRCASEEQ (cmd, \"%s\")" name;
7698       if name <> name2 then
7699         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7700       if name <> alias then
7701         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7702       pr ") {\n";
7703       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7704         name2 shortdesc
7705         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7706          "=head1 DESCRIPTION\n\n" ^
7707          longdesc ^ warnings ^ describe_alias);
7708       pr "    return 0;\n";
7709       pr "  }\n";
7710       pr "  else\n"
7711   ) all_functions;
7712   pr "    return display_builtin_command (cmd);\n";
7713   pr "}\n";
7714   pr "\n";
7715
7716   let emit_print_list_function typ =
7717     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7718       typ typ typ;
7719     pr "{\n";
7720     pr "  unsigned int i;\n";
7721     pr "\n";
7722     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7723     pr "    printf (\"[%%d] = {\\n\", i);\n";
7724     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7725     pr "    printf (\"}\\n\");\n";
7726     pr "  }\n";
7727     pr "}\n";
7728     pr "\n";
7729   in
7730
7731   (* print_* functions *)
7732   List.iter (
7733     fun (typ, cols) ->
7734       let needs_i =
7735         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7736
7737       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7738       pr "{\n";
7739       if needs_i then (
7740         pr "  unsigned int i;\n";
7741         pr "\n"
7742       );
7743       List.iter (
7744         function
7745         | name, FString ->
7746             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7747         | name, FUUID ->
7748             pr "  printf (\"%%s%s: \", indent);\n" name;
7749             pr "  for (i = 0; i < 32; ++i)\n";
7750             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7751             pr "  printf (\"\\n\");\n"
7752         | name, FBuffer ->
7753             pr "  printf (\"%%s%s: \", indent);\n" name;
7754             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7755             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7756             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7757             pr "    else\n";
7758             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7759             pr "  printf (\"\\n\");\n"
7760         | name, (FUInt64|FBytes) ->
7761             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7762               name typ name
7763         | name, FInt64 ->
7764             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7765               name typ name
7766         | name, FUInt32 ->
7767             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7768               name typ name
7769         | name, FInt32 ->
7770             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7771               name typ name
7772         | name, FChar ->
7773             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7774               name typ name
7775         | name, FOptPercent ->
7776             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7777               typ name name typ name;
7778             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7779       ) cols;
7780       pr "}\n";
7781       pr "\n";
7782   ) structs;
7783
7784   (* Emit a print_TYPE_list function definition only if that function is used. *)
7785   List.iter (
7786     function
7787     | typ, (RStructListOnly | RStructAndList) ->
7788         (* generate the function for typ *)
7789         emit_print_list_function typ
7790     | typ, _ -> () (* empty *)
7791   ) (rstructs_used_by all_functions);
7792
7793   (* Emit a print_TYPE function definition only if that function is used. *)
7794   List.iter (
7795     function
7796     | typ, (RStructOnly | RStructAndList) ->
7797         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7798         pr "{\n";
7799         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7800         pr "}\n";
7801         pr "\n";
7802     | typ, _ -> () (* empty *)
7803   ) (rstructs_used_by all_functions);
7804
7805   (* run_<action> actions *)
7806   List.iter (
7807     fun (name, style, _, flags, _, _, _) ->
7808       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7809       pr "{\n";
7810       (match fst style with
7811        | RErr
7812        | RInt _
7813        | RBool _ -> pr "  int r;\n"
7814        | RInt64 _ -> pr "  int64_t r;\n"
7815        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7816        | RString _ -> pr "  char *r;\n"
7817        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7818        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7819        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7820        | RBufferOut _ ->
7821            pr "  char *r;\n";
7822            pr "  size_t size;\n";
7823       );
7824       List.iter (
7825         function
7826         | Device n
7827         | String n
7828         | OptString n -> pr "  const char *%s;\n" n
7829         | Pathname n
7830         | Dev_or_Path n
7831         | FileIn n
7832         | FileOut n -> pr "  char *%s;\n" n
7833         | BufferIn n ->
7834             pr "  const char *%s;\n" n;
7835             pr "  size_t %s_size;\n" n
7836         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7837         | Bool n -> pr "  int %s;\n" n
7838         | Int n -> pr "  int %s;\n" n
7839         | Int64 n -> pr "  int64_t %s;\n" n
7840       ) (snd style);
7841
7842       (* Check and convert parameters. *)
7843       let argc_expected = List.length (snd style) in
7844       pr "  if (argc != %d) {\n" argc_expected;
7845       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7846         argc_expected;
7847       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7848       pr "    return -1;\n";
7849       pr "  }\n";
7850
7851       let parse_integer fn fntyp rtyp range name i =
7852         pr "  {\n";
7853         pr "    strtol_error xerr;\n";
7854         pr "    %s r;\n" fntyp;
7855         pr "\n";
7856         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7857         pr "    if (xerr != LONGINT_OK) {\n";
7858         pr "      fprintf (stderr,\n";
7859         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7860         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7861         pr "      return -1;\n";
7862         pr "    }\n";
7863         (match range with
7864          | None -> ()
7865          | Some (min, max, comment) ->
7866              pr "    /* %s */\n" comment;
7867              pr "    if (r < %s || r > %s) {\n" min max;
7868              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7869                name;
7870              pr "      return -1;\n";
7871              pr "    }\n";
7872              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7873         );
7874         pr "    %s = r;\n" name;
7875         pr "  }\n";
7876       in
7877
7878       iteri (
7879         fun i ->
7880           function
7881           | Device name
7882           | String name ->
7883               pr "  %s = argv[%d];\n" name i
7884           | Pathname name
7885           | Dev_or_Path name ->
7886               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7887               pr "  if (%s == NULL) return -1;\n" name
7888           | OptString name ->
7889               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7890                 name i i
7891           | BufferIn name ->
7892               pr "  %s = argv[%d];\n" name i;
7893               pr "  %s_size = strlen (argv[%d]);\n" name i
7894           | FileIn name ->
7895               pr "  %s = file_in (argv[%d]);\n" name i;
7896               pr "  if (%s == NULL) return -1;\n" name
7897           | FileOut name ->
7898               pr "  %s = file_out (argv[%d]);\n" name i;
7899               pr "  if (%s == NULL) return -1;\n" name
7900           | StringList name | DeviceList name ->
7901               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7902               pr "  if (%s == NULL) return -1;\n" name;
7903           | Bool name ->
7904               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7905           | Int name ->
7906               let range =
7907                 let min = "(-(2LL<<30))"
7908                 and max = "((2LL<<30)-1)"
7909                 and comment =
7910                   "The Int type in the generator is a signed 31 bit int." in
7911                 Some (min, max, comment) in
7912               parse_integer "xstrtoll" "long long" "int" range name i
7913           | Int64 name ->
7914               parse_integer "xstrtoll" "long long" "int64_t" None name i
7915       ) (snd style);
7916
7917       (* Call C API function. *)
7918       pr "  r = guestfs_%s " name;
7919       generate_c_call_args ~handle:"g" style;
7920       pr ";\n";
7921
7922       List.iter (
7923         function
7924         | Device _ | String _
7925         | OptString _ | Bool _
7926         | Int _ | Int64 _
7927         | BufferIn _ -> ()
7928         | Pathname name | Dev_or_Path name | FileOut name ->
7929             pr "  free (%s);\n" name
7930         | FileIn name ->
7931             pr "  free_file_in (%s);\n" name
7932         | StringList name | DeviceList name ->
7933             pr "  free_strings (%s);\n" name
7934       ) (snd style);
7935
7936       (* Any output flags? *)
7937       let fish_output =
7938         let flags = filter_map (
7939           function FishOutput flag -> Some flag | _ -> None
7940         ) flags in
7941         match flags with
7942         | [] -> None
7943         | [f] -> Some f
7944         | _ ->
7945             failwithf "%s: more than one FishOutput flag is not allowed" name in
7946
7947       (* Check return value for errors and display command results. *)
7948       (match fst style with
7949        | RErr -> pr "  return r;\n"
7950        | RInt _ ->
7951            pr "  if (r == -1) return -1;\n";
7952            (match fish_output with
7953             | None ->
7954                 pr "  printf (\"%%d\\n\", r);\n";
7955             | Some FishOutputOctal ->
7956                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7957             | Some FishOutputHexadecimal ->
7958                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7959            pr "  return 0;\n"
7960        | RInt64 _ ->
7961            pr "  if (r == -1) return -1;\n";
7962            (match fish_output with
7963             | None ->
7964                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7965             | Some FishOutputOctal ->
7966                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7967             | Some FishOutputHexadecimal ->
7968                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7969            pr "  return 0;\n"
7970        | RBool _ ->
7971            pr "  if (r == -1) return -1;\n";
7972            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7973            pr "  return 0;\n"
7974        | RConstString _ ->
7975            pr "  if (r == NULL) return -1;\n";
7976            pr "  printf (\"%%s\\n\", r);\n";
7977            pr "  return 0;\n"
7978        | RConstOptString _ ->
7979            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7980            pr "  return 0;\n"
7981        | RString _ ->
7982            pr "  if (r == NULL) return -1;\n";
7983            pr "  printf (\"%%s\\n\", r);\n";
7984            pr "  free (r);\n";
7985            pr "  return 0;\n"
7986        | RStringList _ ->
7987            pr "  if (r == NULL) return -1;\n";
7988            pr "  print_strings (r);\n";
7989            pr "  free_strings (r);\n";
7990            pr "  return 0;\n"
7991        | RStruct (_, typ) ->
7992            pr "  if (r == NULL) return -1;\n";
7993            pr "  print_%s (r);\n" typ;
7994            pr "  guestfs_free_%s (r);\n" typ;
7995            pr "  return 0;\n"
7996        | RStructList (_, typ) ->
7997            pr "  if (r == NULL) return -1;\n";
7998            pr "  print_%s_list (r);\n" typ;
7999            pr "  guestfs_free_%s_list (r);\n" typ;
8000            pr "  return 0;\n"
8001        | RHashtable _ ->
8002            pr "  if (r == NULL) return -1;\n";
8003            pr "  print_table (r);\n";
8004            pr "  free_strings (r);\n";
8005            pr "  return 0;\n"
8006        | RBufferOut _ ->
8007            pr "  if (r == NULL) return -1;\n";
8008            pr "  if (full_write (1, r, size) != size) {\n";
8009            pr "    perror (\"write\");\n";
8010            pr "    free (r);\n";
8011            pr "    return -1;\n";
8012            pr "  }\n";
8013            pr "  free (r);\n";
8014            pr "  return 0;\n"
8015       );
8016       pr "}\n";
8017       pr "\n"
8018   ) all_functions;
8019
8020   (* run_action function *)
8021   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8022   pr "{\n";
8023   List.iter (
8024     fun (name, _, _, flags, _, _, _) ->
8025       let name2 = replace_char name '_' '-' in
8026       let alias =
8027         try find_map (function FishAlias n -> Some n | _ -> None) flags
8028         with Not_found -> name in
8029       pr "  if (";
8030       pr "STRCASEEQ (cmd, \"%s\")" name;
8031       if name <> name2 then
8032         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8033       if name <> alias then
8034         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8035       pr ")\n";
8036       pr "    return run_%s (cmd, argc, argv);\n" name;
8037       pr "  else\n";
8038   ) all_functions;
8039   pr "    {\n";
8040   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8041   pr "      if (command_num == 1)\n";
8042   pr "        extended_help_message ();\n";
8043   pr "      return -1;\n";
8044   pr "    }\n";
8045   pr "  return 0;\n";
8046   pr "}\n";
8047   pr "\n"
8048
8049 (* Readline completion for guestfish. *)
8050 and generate_fish_completion () =
8051   generate_header CStyle GPLv2plus;
8052
8053   let all_functions =
8054     List.filter (
8055       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8056     ) all_functions in
8057
8058   pr "\
8059 #include <config.h>
8060
8061 #include <stdio.h>
8062 #include <stdlib.h>
8063 #include <string.h>
8064
8065 #ifdef HAVE_LIBREADLINE
8066 #include <readline/readline.h>
8067 #endif
8068
8069 #include \"fish.h\"
8070
8071 #ifdef HAVE_LIBREADLINE
8072
8073 static const char *const commands[] = {
8074   BUILTIN_COMMANDS_FOR_COMPLETION,
8075 ";
8076
8077   (* Get the commands, including the aliases.  They don't need to be
8078    * sorted - the generator() function just does a dumb linear search.
8079    *)
8080   let commands =
8081     List.map (
8082       fun (name, _, _, flags, _, _, _) ->
8083         let name2 = replace_char name '_' '-' in
8084         let alias =
8085           try find_map (function FishAlias n -> Some n | _ -> None) flags
8086           with Not_found -> name in
8087
8088         if name <> alias then [name2; alias] else [name2]
8089     ) all_functions in
8090   let commands = List.flatten commands in
8091
8092   List.iter (pr "  \"%s\",\n") commands;
8093
8094   pr "  NULL
8095 };
8096
8097 static char *
8098 generator (const char *text, int state)
8099 {
8100   static size_t index, len;
8101   const char *name;
8102
8103   if (!state) {
8104     index = 0;
8105     len = strlen (text);
8106   }
8107
8108   rl_attempted_completion_over = 1;
8109
8110   while ((name = commands[index]) != NULL) {
8111     index++;
8112     if (STRCASEEQLEN (name, text, len))
8113       return strdup (name);
8114   }
8115
8116   return NULL;
8117 }
8118
8119 #endif /* HAVE_LIBREADLINE */
8120
8121 #ifdef HAVE_RL_COMPLETION_MATCHES
8122 #define RL_COMPLETION_MATCHES rl_completion_matches
8123 #else
8124 #ifdef HAVE_COMPLETION_MATCHES
8125 #define RL_COMPLETION_MATCHES completion_matches
8126 #endif
8127 #endif /* else just fail if we don't have either symbol */
8128
8129 char **
8130 do_completion (const char *text, int start, int end)
8131 {
8132   char **matches = NULL;
8133
8134 #ifdef HAVE_LIBREADLINE
8135   rl_completion_append_character = ' ';
8136
8137   if (start == 0)
8138     matches = RL_COMPLETION_MATCHES (text, generator);
8139   else if (complete_dest_paths)
8140     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8141 #endif
8142
8143   return matches;
8144 }
8145 ";
8146
8147 (* Generate the POD documentation for guestfish. *)
8148 and generate_fish_actions_pod () =
8149   let all_functions_sorted =
8150     List.filter (
8151       fun (_, _, _, flags, _, _, _) ->
8152         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8153     ) all_functions_sorted in
8154
8155   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8156
8157   List.iter (
8158     fun (name, style, _, flags, _, _, longdesc) ->
8159       let longdesc =
8160         Str.global_substitute rex (
8161           fun s ->
8162             let sub =
8163               try Str.matched_group 1 s
8164               with Not_found ->
8165                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8166             "C<" ^ replace_char sub '_' '-' ^ ">"
8167         ) longdesc in
8168       let name = replace_char name '_' '-' in
8169       let alias =
8170         try find_map (function FishAlias n -> Some n | _ -> None) flags
8171         with Not_found -> name in
8172
8173       pr "=head2 %s" name;
8174       if name <> alias then
8175         pr " | %s" alias;
8176       pr "\n";
8177       pr "\n";
8178       pr " %s" name;
8179       List.iter (
8180         function
8181         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8182         | OptString n -> pr " %s" n
8183         | StringList n | DeviceList n -> pr " '%s ...'" n
8184         | Bool _ -> pr " true|false"
8185         | Int n -> pr " %s" n
8186         | Int64 n -> pr " %s" n
8187         | FileIn n | FileOut n -> pr " (%s|-)" n
8188         | BufferIn n -> pr " %s" n
8189       ) (snd style);
8190       pr "\n";
8191       pr "\n";
8192       pr "%s\n\n" longdesc;
8193
8194       if List.exists (function FileIn _ | FileOut _ -> true
8195                       | _ -> false) (snd style) then
8196         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8197
8198       if List.mem ProtocolLimitWarning flags then
8199         pr "%s\n\n" protocol_limit_warning;
8200
8201       if List.mem DangerWillRobinson flags then
8202         pr "%s\n\n" danger_will_robinson;
8203
8204       match deprecation_notice flags with
8205       | None -> ()
8206       | Some txt -> pr "%s\n\n" txt
8207   ) all_functions_sorted
8208
8209 (* Generate a C function prototype. *)
8210 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8211     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8212     ?(prefix = "")
8213     ?handle name style =
8214   if extern then pr "extern ";
8215   if static then pr "static ";
8216   (match fst style with
8217    | RErr -> pr "int "
8218    | RInt _ -> pr "int "
8219    | RInt64 _ -> pr "int64_t "
8220    | RBool _ -> pr "int "
8221    | RConstString _ | RConstOptString _ -> pr "const char *"
8222    | RString _ | RBufferOut _ -> pr "char *"
8223    | RStringList _ | RHashtable _ -> pr "char **"
8224    | RStruct (_, typ) ->
8225        if not in_daemon then pr "struct guestfs_%s *" typ
8226        else pr "guestfs_int_%s *" typ
8227    | RStructList (_, typ) ->
8228        if not in_daemon then pr "struct guestfs_%s_list *" typ
8229        else pr "guestfs_int_%s_list *" typ
8230   );
8231   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8232   pr "%s%s (" prefix name;
8233   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8234     pr "void"
8235   else (
8236     let comma = ref false in
8237     (match handle with
8238      | None -> ()
8239      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8240     );
8241     let next () =
8242       if !comma then (
8243         if single_line then pr ", " else pr ",\n\t\t"
8244       );
8245       comma := true
8246     in
8247     List.iter (
8248       function
8249       | Pathname n
8250       | Device n | Dev_or_Path n
8251       | String n
8252       | OptString n ->
8253           next ();
8254           pr "const char *%s" n
8255       | StringList n | DeviceList n ->
8256           next ();
8257           pr "char *const *%s" n
8258       | Bool n -> next (); pr "int %s" n
8259       | Int n -> next (); pr "int %s" n
8260       | Int64 n -> next (); pr "int64_t %s" n
8261       | FileIn n
8262       | FileOut n ->
8263           if not in_daemon then (next (); pr "const char *%s" n)
8264       | BufferIn n ->
8265           next ();
8266           pr "const char *%s" n;
8267           next ();
8268           pr "size_t %s_size" n
8269     ) (snd style);
8270     if is_RBufferOut then (next (); pr "size_t *size_r");
8271   );
8272   pr ")";
8273   if semicolon then pr ";";
8274   if newline then pr "\n"
8275
8276 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8277 and generate_c_call_args ?handle ?(decl = false) style =
8278   pr "(";
8279   let comma = ref false in
8280   let next () =
8281     if !comma then pr ", ";
8282     comma := true
8283   in
8284   (match handle with
8285    | None -> ()
8286    | Some handle -> pr "%s" handle; comma := true
8287   );
8288   List.iter (
8289     function
8290     | BufferIn n ->
8291         next ();
8292         pr "%s, %s_size" n n
8293     | arg ->
8294         next ();
8295         pr "%s" (name_of_argt arg)
8296   ) (snd style);
8297   (* For RBufferOut calls, add implicit &size parameter. *)
8298   if not decl then (
8299     match fst style with
8300     | RBufferOut _ ->
8301         next ();
8302         pr "&size"
8303     | _ -> ()
8304   );
8305   pr ")"
8306
8307 (* Generate the OCaml bindings interface. *)
8308 and generate_ocaml_mli () =
8309   generate_header OCamlStyle LGPLv2plus;
8310
8311   pr "\
8312 (** For API documentation you should refer to the C API
8313     in the guestfs(3) manual page.  The OCaml API uses almost
8314     exactly the same calls. *)
8315
8316 type t
8317 (** A [guestfs_h] handle. *)
8318
8319 exception Error of string
8320 (** This exception is raised when there is an error. *)
8321
8322 exception Handle_closed of string
8323 (** This exception is raised if you use a {!Guestfs.t} handle
8324     after calling {!close} on it.  The string is the name of
8325     the function. *)
8326
8327 val create : unit -> t
8328 (** Create a {!Guestfs.t} handle. *)
8329
8330 val close : t -> unit
8331 (** Close the {!Guestfs.t} handle and free up all resources used
8332     by it immediately.
8333
8334     Handles are closed by the garbage collector when they become
8335     unreferenced, but callers can call this in order to provide
8336     predictable cleanup. *)
8337
8338 ";
8339   generate_ocaml_structure_decls ();
8340
8341   (* The actions. *)
8342   List.iter (
8343     fun (name, style, _, _, _, shortdesc, _) ->
8344       generate_ocaml_prototype name style;
8345       pr "(** %s *)\n" shortdesc;
8346       pr "\n"
8347   ) all_functions_sorted
8348
8349 (* Generate the OCaml bindings implementation. *)
8350 and generate_ocaml_ml () =
8351   generate_header OCamlStyle LGPLv2plus;
8352
8353   pr "\
8354 type t
8355
8356 exception Error of string
8357 exception Handle_closed of string
8358
8359 external create : unit -> t = \"ocaml_guestfs_create\"
8360 external close : t -> unit = \"ocaml_guestfs_close\"
8361
8362 (* Give the exceptions names, so they can be raised from the C code. *)
8363 let () =
8364   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8365   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8366
8367 ";
8368
8369   generate_ocaml_structure_decls ();
8370
8371   (* The actions. *)
8372   List.iter (
8373     fun (name, style, _, _, _, shortdesc, _) ->
8374       generate_ocaml_prototype ~is_external:true name style;
8375   ) all_functions_sorted
8376
8377 (* Generate the OCaml bindings C implementation. *)
8378 and generate_ocaml_c () =
8379   generate_header CStyle LGPLv2plus;
8380
8381   pr "\
8382 #include <stdio.h>
8383 #include <stdlib.h>
8384 #include <string.h>
8385
8386 #include <caml/config.h>
8387 #include <caml/alloc.h>
8388 #include <caml/callback.h>
8389 #include <caml/fail.h>
8390 #include <caml/memory.h>
8391 #include <caml/mlvalues.h>
8392 #include <caml/signals.h>
8393
8394 #include \"guestfs.h\"
8395
8396 #include \"guestfs_c.h\"
8397
8398 /* Copy a hashtable of string pairs into an assoc-list.  We return
8399  * the list in reverse order, but hashtables aren't supposed to be
8400  * ordered anyway.
8401  */
8402 static CAMLprim value
8403 copy_table (char * const * argv)
8404 {
8405   CAMLparam0 ();
8406   CAMLlocal5 (rv, pairv, kv, vv, cons);
8407   size_t i;
8408
8409   rv = Val_int (0);
8410   for (i = 0; argv[i] != NULL; i += 2) {
8411     kv = caml_copy_string (argv[i]);
8412     vv = caml_copy_string (argv[i+1]);
8413     pairv = caml_alloc (2, 0);
8414     Store_field (pairv, 0, kv);
8415     Store_field (pairv, 1, vv);
8416     cons = caml_alloc (2, 0);
8417     Store_field (cons, 1, rv);
8418     rv = cons;
8419     Store_field (cons, 0, pairv);
8420   }
8421
8422   CAMLreturn (rv);
8423 }
8424
8425 ";
8426
8427   (* Struct copy functions. *)
8428
8429   let emit_ocaml_copy_list_function typ =
8430     pr "static CAMLprim value\n";
8431     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8432     pr "{\n";
8433     pr "  CAMLparam0 ();\n";
8434     pr "  CAMLlocal2 (rv, v);\n";
8435     pr "  unsigned int i;\n";
8436     pr "\n";
8437     pr "  if (%ss->len == 0)\n" typ;
8438     pr "    CAMLreturn (Atom (0));\n";
8439     pr "  else {\n";
8440     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8441     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8442     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8443     pr "      caml_modify (&Field (rv, i), v);\n";
8444     pr "    }\n";
8445     pr "    CAMLreturn (rv);\n";
8446     pr "  }\n";
8447     pr "}\n";
8448     pr "\n";
8449   in
8450
8451   List.iter (
8452     fun (typ, cols) ->
8453       let has_optpercent_col =
8454         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8455
8456       pr "static CAMLprim value\n";
8457       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8458       pr "{\n";
8459       pr "  CAMLparam0 ();\n";
8460       if has_optpercent_col then
8461         pr "  CAMLlocal3 (rv, v, v2);\n"
8462       else
8463         pr "  CAMLlocal2 (rv, v);\n";
8464       pr "\n";
8465       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8466       iteri (
8467         fun i col ->
8468           (match col with
8469            | name, FString ->
8470                pr "  v = caml_copy_string (%s->%s);\n" typ name
8471            | name, FBuffer ->
8472                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8473                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8474                  typ name typ name
8475            | name, FUUID ->
8476                pr "  v = caml_alloc_string (32);\n";
8477                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8478            | name, (FBytes|FInt64|FUInt64) ->
8479                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8480            | name, (FInt32|FUInt32) ->
8481                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8482            | name, FOptPercent ->
8483                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8484                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8485                pr "    v = caml_alloc (1, 0);\n";
8486                pr "    Store_field (v, 0, v2);\n";
8487                pr "  } else /* None */\n";
8488                pr "    v = Val_int (0);\n";
8489            | name, FChar ->
8490                pr "  v = Val_int (%s->%s);\n" typ name
8491           );
8492           pr "  Store_field (rv, %d, v);\n" i
8493       ) cols;
8494       pr "  CAMLreturn (rv);\n";
8495       pr "}\n";
8496       pr "\n";
8497   ) structs;
8498
8499   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8500   List.iter (
8501     function
8502     | typ, (RStructListOnly | RStructAndList) ->
8503         (* generate the function for typ *)
8504         emit_ocaml_copy_list_function typ
8505     | typ, _ -> () (* empty *)
8506   ) (rstructs_used_by all_functions);
8507
8508   (* The wrappers. *)
8509   List.iter (
8510     fun (name, style, _, _, _, _, _) ->
8511       pr "/* Automatically generated wrapper for function\n";
8512       pr " * ";
8513       generate_ocaml_prototype name style;
8514       pr " */\n";
8515       pr "\n";
8516
8517       let params =
8518         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8519
8520       let needs_extra_vs =
8521         match fst style with RConstOptString _ -> true | _ -> false in
8522
8523       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8524       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8525       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8526       pr "\n";
8527
8528       pr "CAMLprim value\n";
8529       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8530       List.iter (pr ", value %s") (List.tl params);
8531       pr ")\n";
8532       pr "{\n";
8533
8534       (match params with
8535        | [p1; p2; p3; p4; p5] ->
8536            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8537        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8538            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8539            pr "  CAMLxparam%d (%s);\n"
8540              (List.length rest) (String.concat ", " rest)
8541        | ps ->
8542            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8543       );
8544       if not needs_extra_vs then
8545         pr "  CAMLlocal1 (rv);\n"
8546       else
8547         pr "  CAMLlocal3 (rv, v, v2);\n";
8548       pr "\n";
8549
8550       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8551       pr "  if (g == NULL)\n";
8552       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8553       pr "\n";
8554
8555       List.iter (
8556         function
8557         | Pathname n
8558         | Device n | Dev_or_Path n
8559         | String n
8560         | FileIn n
8561         | FileOut n ->
8562             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8563             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8564         | OptString n ->
8565             pr "  char *%s =\n" n;
8566             pr "    %sv != Val_int (0) ?" n;
8567             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8568         | BufferIn n ->
8569             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8570             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8571         | StringList n | DeviceList n ->
8572             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8573         | Bool n ->
8574             pr "  int %s = Bool_val (%sv);\n" n n
8575         | Int n ->
8576             pr "  int %s = Int_val (%sv);\n" n n
8577         | Int64 n ->
8578             pr "  int64_t %s = Int64_val (%sv);\n" n n
8579       ) (snd style);
8580       let error_code =
8581         match fst style with
8582         | RErr -> pr "  int r;\n"; "-1"
8583         | RInt _ -> pr "  int r;\n"; "-1"
8584         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8585         | RBool _ -> pr "  int r;\n"; "-1"
8586         | RConstString _ | RConstOptString _ ->
8587             pr "  const char *r;\n"; "NULL"
8588         | RString _ -> pr "  char *r;\n"; "NULL"
8589         | RStringList _ ->
8590             pr "  size_t i;\n";
8591             pr "  char **r;\n";
8592             "NULL"
8593         | RStruct (_, typ) ->
8594             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8595         | RStructList (_, typ) ->
8596             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8597         | RHashtable _ ->
8598             pr "  size_t i;\n";
8599             pr "  char **r;\n";
8600             "NULL"
8601         | RBufferOut _ ->
8602             pr "  char *r;\n";
8603             pr "  size_t size;\n";
8604             "NULL" in
8605       pr "\n";
8606
8607       pr "  caml_enter_blocking_section ();\n";
8608       pr "  r = guestfs_%s " name;
8609       generate_c_call_args ~handle:"g" style;
8610       pr ";\n";
8611       pr "  caml_leave_blocking_section ();\n";
8612
8613       (* Free strings if we copied them above. *)
8614       List.iter (
8615         function
8616         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8617         | FileIn n | FileOut n | BufferIn n ->
8618             pr "  free (%s);\n" n
8619         | StringList n | DeviceList n ->
8620             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8621         | Bool _ | Int _ | Int64 _ -> ()
8622       ) (snd style);
8623
8624       pr "  if (r == %s)\n" error_code;
8625       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8626       pr "\n";
8627
8628       (match fst style with
8629        | RErr -> pr "  rv = Val_unit;\n"
8630        | RInt _ -> pr "  rv = Val_int (r);\n"
8631        | RInt64 _ ->
8632            pr "  rv = caml_copy_int64 (r);\n"
8633        | RBool _ -> pr "  rv = Val_bool (r);\n"
8634        | RConstString _ ->
8635            pr "  rv = caml_copy_string (r);\n"
8636        | RConstOptString _ ->
8637            pr "  if (r) { /* Some string */\n";
8638            pr "    v = caml_alloc (1, 0);\n";
8639            pr "    v2 = caml_copy_string (r);\n";
8640            pr "    Store_field (v, 0, v2);\n";
8641            pr "  } else /* None */\n";
8642            pr "    v = Val_int (0);\n";
8643        | RString _ ->
8644            pr "  rv = caml_copy_string (r);\n";
8645            pr "  free (r);\n"
8646        | RStringList _ ->
8647            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8648            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8649            pr "  free (r);\n"
8650        | RStruct (_, typ) ->
8651            pr "  rv = copy_%s (r);\n" typ;
8652            pr "  guestfs_free_%s (r);\n" typ;
8653        | RStructList (_, typ) ->
8654            pr "  rv = copy_%s_list (r);\n" typ;
8655            pr "  guestfs_free_%s_list (r);\n" typ;
8656        | RHashtable _ ->
8657            pr "  rv = copy_table (r);\n";
8658            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8659            pr "  free (r);\n";
8660        | RBufferOut _ ->
8661            pr "  rv = caml_alloc_string (size);\n";
8662            pr "  memcpy (String_val (rv), r, size);\n";
8663       );
8664
8665       pr "  CAMLreturn (rv);\n";
8666       pr "}\n";
8667       pr "\n";
8668
8669       if List.length params > 5 then (
8670         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8671         pr "CAMLprim value ";
8672         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8673         pr "CAMLprim value\n";
8674         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8675         pr "{\n";
8676         pr "  return ocaml_guestfs_%s (argv[0]" name;
8677         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8678         pr ");\n";
8679         pr "}\n";
8680         pr "\n"
8681       )
8682   ) all_functions_sorted
8683
8684 and generate_ocaml_structure_decls () =
8685   List.iter (
8686     fun (typ, cols) ->
8687       pr "type %s = {\n" typ;
8688       List.iter (
8689         function
8690         | name, FString -> pr "  %s : string;\n" name
8691         | name, FBuffer -> pr "  %s : string;\n" name
8692         | name, FUUID -> pr "  %s : string;\n" name
8693         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8694         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8695         | name, FChar -> pr "  %s : char;\n" name
8696         | name, FOptPercent -> pr "  %s : float option;\n" name
8697       ) cols;
8698       pr "}\n";
8699       pr "\n"
8700   ) structs
8701
8702 and generate_ocaml_prototype ?(is_external = false) name style =
8703   if is_external then pr "external " else pr "val ";
8704   pr "%s : t -> " name;
8705   List.iter (
8706     function
8707     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8708     | BufferIn _ -> pr "string -> "
8709     | OptString _ -> pr "string option -> "
8710     | StringList _ | DeviceList _ -> pr "string array -> "
8711     | Bool _ -> pr "bool -> "
8712     | Int _ -> pr "int -> "
8713     | Int64 _ -> pr "int64 -> "
8714   ) (snd style);
8715   (match fst style with
8716    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8717    | RInt _ -> pr "int"
8718    | RInt64 _ -> pr "int64"
8719    | RBool _ -> pr "bool"
8720    | RConstString _ -> pr "string"
8721    | RConstOptString _ -> pr "string option"
8722    | RString _ | RBufferOut _ -> pr "string"
8723    | RStringList _ -> pr "string array"
8724    | RStruct (_, typ) -> pr "%s" typ
8725    | RStructList (_, typ) -> pr "%s array" typ
8726    | RHashtable _ -> pr "(string * string) list"
8727   );
8728   if is_external then (
8729     pr " = ";
8730     if List.length (snd style) + 1 > 5 then
8731       pr "\"ocaml_guestfs_%s_byte\" " name;
8732     pr "\"ocaml_guestfs_%s\"" name
8733   );
8734   pr "\n"
8735
8736 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8737 and generate_perl_xs () =
8738   generate_header CStyle LGPLv2plus;
8739
8740   pr "\
8741 #include \"EXTERN.h\"
8742 #include \"perl.h\"
8743 #include \"XSUB.h\"
8744
8745 #include <guestfs.h>
8746
8747 #ifndef PRId64
8748 #define PRId64 \"lld\"
8749 #endif
8750
8751 static SV *
8752 my_newSVll(long long val) {
8753 #ifdef USE_64_BIT_ALL
8754   return newSViv(val);
8755 #else
8756   char buf[100];
8757   int len;
8758   len = snprintf(buf, 100, \"%%\" PRId64, val);
8759   return newSVpv(buf, len);
8760 #endif
8761 }
8762
8763 #ifndef PRIu64
8764 #define PRIu64 \"llu\"
8765 #endif
8766
8767 static SV *
8768 my_newSVull(unsigned long long val) {
8769 #ifdef USE_64_BIT_ALL
8770   return newSVuv(val);
8771 #else
8772   char buf[100];
8773   int len;
8774   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8775   return newSVpv(buf, len);
8776 #endif
8777 }
8778
8779 /* http://www.perlmonks.org/?node_id=680842 */
8780 static char **
8781 XS_unpack_charPtrPtr (SV *arg) {
8782   char **ret;
8783   AV *av;
8784   I32 i;
8785
8786   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8787     croak (\"array reference expected\");
8788
8789   av = (AV *)SvRV (arg);
8790   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8791   if (!ret)
8792     croak (\"malloc failed\");
8793
8794   for (i = 0; i <= av_len (av); i++) {
8795     SV **elem = av_fetch (av, i, 0);
8796
8797     if (!elem || !*elem)
8798       croak (\"missing element in list\");
8799
8800     ret[i] = SvPV_nolen (*elem);
8801   }
8802
8803   ret[i] = NULL;
8804
8805   return ret;
8806 }
8807
8808 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8809
8810 PROTOTYPES: ENABLE
8811
8812 guestfs_h *
8813 _create ()
8814    CODE:
8815       RETVAL = guestfs_create ();
8816       if (!RETVAL)
8817         croak (\"could not create guestfs handle\");
8818       guestfs_set_error_handler (RETVAL, NULL, NULL);
8819  OUTPUT:
8820       RETVAL
8821
8822 void
8823 DESTROY (sv)
8824       SV *sv;
8825  PPCODE:
8826       /* For the 'g' argument above we do the conversion explicitly and
8827        * don't rely on the typemap, because if the handle has been
8828        * explicitly closed we don't want the typemap conversion to
8829        * display an error.
8830        */
8831       HV *hv = (HV *) SvRV (sv);
8832       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8833       if (svp != NULL) {
8834         guestfs_h *g = (guestfs_h *) SvIV (*svp);
8835         assert (g != NULL);
8836         guestfs_close (g);
8837       }
8838
8839 void
8840 close (g)
8841       guestfs_h *g;
8842  PPCODE:
8843       guestfs_close (g);
8844       /* Avoid double-free in DESTROY method. */
8845       HV *hv = (HV *) SvRV (ST(0));
8846       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8847
8848 ";
8849
8850   List.iter (
8851     fun (name, style, _, _, _, _, _) ->
8852       (match fst style with
8853        | RErr -> pr "void\n"
8854        | RInt _ -> pr "SV *\n"
8855        | RInt64 _ -> pr "SV *\n"
8856        | RBool _ -> pr "SV *\n"
8857        | RConstString _ -> pr "SV *\n"
8858        | RConstOptString _ -> pr "SV *\n"
8859        | RString _ -> pr "SV *\n"
8860        | RBufferOut _ -> pr "SV *\n"
8861        | RStringList _
8862        | RStruct _ | RStructList _
8863        | RHashtable _ ->
8864            pr "void\n" (* all lists returned implictly on the stack *)
8865       );
8866       (* Call and arguments. *)
8867       pr "%s (g" name;
8868       List.iter (
8869         fun arg -> pr ", %s" (name_of_argt arg)
8870       ) (snd style);
8871       pr ")\n";
8872       pr "      guestfs_h *g;\n";
8873       iteri (
8874         fun i ->
8875           function
8876           | Pathname n | Device n | Dev_or_Path n | String n
8877           | FileIn n | FileOut n ->
8878               pr "      char *%s;\n" n
8879           | BufferIn n ->
8880               pr "      char *%s;\n" n;
8881               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8882           | OptString n ->
8883               (* http://www.perlmonks.org/?node_id=554277
8884                * Note that the implicit handle argument means we have
8885                * to add 1 to the ST(x) operator.
8886                *)
8887               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8888           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8889           | Bool n -> pr "      int %s;\n" n
8890           | Int n -> pr "      int %s;\n" n
8891           | Int64 n -> pr "      int64_t %s;\n" n
8892       ) (snd style);
8893
8894       let do_cleanups () =
8895         List.iter (
8896           function
8897           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8898           | Bool _ | Int _ | Int64 _
8899           | FileIn _ | FileOut _
8900           | BufferIn _ -> ()
8901           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8902         ) (snd style)
8903       in
8904
8905       (* Code. *)
8906       (match fst style with
8907        | RErr ->
8908            pr "PREINIT:\n";
8909            pr "      int r;\n";
8910            pr " PPCODE:\n";
8911            pr "      r = guestfs_%s " name;
8912            generate_c_call_args ~handle:"g" style;
8913            pr ";\n";
8914            do_cleanups ();
8915            pr "      if (r == -1)\n";
8916            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8917        | RInt n
8918        | RBool n ->
8919            pr "PREINIT:\n";
8920            pr "      int %s;\n" n;
8921            pr "   CODE:\n";
8922            pr "      %s = guestfs_%s " n name;
8923            generate_c_call_args ~handle:"g" style;
8924            pr ";\n";
8925            do_cleanups ();
8926            pr "      if (%s == -1)\n" n;
8927            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8928            pr "      RETVAL = newSViv (%s);\n" n;
8929            pr " OUTPUT:\n";
8930            pr "      RETVAL\n"
8931        | RInt64 n ->
8932            pr "PREINIT:\n";
8933            pr "      int64_t %s;\n" n;
8934            pr "   CODE:\n";
8935            pr "      %s = guestfs_%s " n name;
8936            generate_c_call_args ~handle:"g" style;
8937            pr ";\n";
8938            do_cleanups ();
8939            pr "      if (%s == -1)\n" n;
8940            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8941            pr "      RETVAL = my_newSVll (%s);\n" n;
8942            pr " OUTPUT:\n";
8943            pr "      RETVAL\n"
8944        | RConstString n ->
8945            pr "PREINIT:\n";
8946            pr "      const char *%s;\n" n;
8947            pr "   CODE:\n";
8948            pr "      %s = guestfs_%s " n name;
8949            generate_c_call_args ~handle:"g" style;
8950            pr ";\n";
8951            do_cleanups ();
8952            pr "      if (%s == NULL)\n" n;
8953            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8954            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8955            pr " OUTPUT:\n";
8956            pr "      RETVAL\n"
8957        | RConstOptString n ->
8958            pr "PREINIT:\n";
8959            pr "      const char *%s;\n" n;
8960            pr "   CODE:\n";
8961            pr "      %s = guestfs_%s " n name;
8962            generate_c_call_args ~handle:"g" style;
8963            pr ";\n";
8964            do_cleanups ();
8965            pr "      if (%s == NULL)\n" n;
8966            pr "        RETVAL = &PL_sv_undef;\n";
8967            pr "      else\n";
8968            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8969            pr " OUTPUT:\n";
8970            pr "      RETVAL\n"
8971        | RString n ->
8972            pr "PREINIT:\n";
8973            pr "      char *%s;\n" n;
8974            pr "   CODE:\n";
8975            pr "      %s = guestfs_%s " n name;
8976            generate_c_call_args ~handle:"g" style;
8977            pr ";\n";
8978            do_cleanups ();
8979            pr "      if (%s == NULL)\n" n;
8980            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8981            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8982            pr "      free (%s);\n" n;
8983            pr " OUTPUT:\n";
8984            pr "      RETVAL\n"
8985        | RStringList n | RHashtable n ->
8986            pr "PREINIT:\n";
8987            pr "      char **%s;\n" n;
8988            pr "      size_t i, n;\n";
8989            pr " PPCODE:\n";
8990            pr "      %s = guestfs_%s " n name;
8991            generate_c_call_args ~handle:"g" style;
8992            pr ";\n";
8993            do_cleanups ();
8994            pr "      if (%s == NULL)\n" n;
8995            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8996            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8997            pr "      EXTEND (SP, n);\n";
8998            pr "      for (i = 0; i < n; ++i) {\n";
8999            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9000            pr "        free (%s[i]);\n" n;
9001            pr "      }\n";
9002            pr "      free (%s);\n" n;
9003        | RStruct (n, typ) ->
9004            let cols = cols_of_struct typ in
9005            generate_perl_struct_code typ cols name style n do_cleanups
9006        | RStructList (n, typ) ->
9007            let cols = cols_of_struct typ in
9008            generate_perl_struct_list_code typ cols name style n do_cleanups
9009        | RBufferOut n ->
9010            pr "PREINIT:\n";
9011            pr "      char *%s;\n" n;
9012            pr "      size_t size;\n";
9013            pr "   CODE:\n";
9014            pr "      %s = guestfs_%s " n name;
9015            generate_c_call_args ~handle:"g" style;
9016            pr ";\n";
9017            do_cleanups ();
9018            pr "      if (%s == NULL)\n" n;
9019            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9020            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9021            pr "      free (%s);\n" n;
9022            pr " OUTPUT:\n";
9023            pr "      RETVAL\n"
9024       );
9025
9026       pr "\n"
9027   ) all_functions
9028
9029 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9030   pr "PREINIT:\n";
9031   pr "      struct guestfs_%s_list *%s;\n" typ n;
9032   pr "      size_t i;\n";
9033   pr "      HV *hv;\n";
9034   pr " PPCODE:\n";
9035   pr "      %s = guestfs_%s " n name;
9036   generate_c_call_args ~handle:"g" style;
9037   pr ";\n";
9038   do_cleanups ();
9039   pr "      if (%s == NULL)\n" n;
9040   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9041   pr "      EXTEND (SP, %s->len);\n" n;
9042   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9043   pr "        hv = newHV ();\n";
9044   List.iter (
9045     function
9046     | name, FString ->
9047         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9048           name (String.length name) n name
9049     | name, FUUID ->
9050         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9051           name (String.length name) n name
9052     | name, FBuffer ->
9053         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9054           name (String.length name) n name n name
9055     | name, (FBytes|FUInt64) ->
9056         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9057           name (String.length name) n name
9058     | name, FInt64 ->
9059         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9060           name (String.length name) n name
9061     | name, (FInt32|FUInt32) ->
9062         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9063           name (String.length name) n name
9064     | name, FChar ->
9065         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9066           name (String.length name) n name
9067     | name, FOptPercent ->
9068         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9069           name (String.length name) n name
9070   ) cols;
9071   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9072   pr "      }\n";
9073   pr "      guestfs_free_%s_list (%s);\n" typ n
9074
9075 and generate_perl_struct_code typ cols name style n do_cleanups =
9076   pr "PREINIT:\n";
9077   pr "      struct guestfs_%s *%s;\n" typ n;
9078   pr " PPCODE:\n";
9079   pr "      %s = guestfs_%s " n name;
9080   generate_c_call_args ~handle:"g" style;
9081   pr ";\n";
9082   do_cleanups ();
9083   pr "      if (%s == NULL)\n" n;
9084   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9085   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9086   List.iter (
9087     fun ((name, _) as col) ->
9088       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9089
9090       match col with
9091       | name, FString ->
9092           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9093             n name
9094       | name, FBuffer ->
9095           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9096             n name n name
9097       | name, FUUID ->
9098           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9099             n name
9100       | name, (FBytes|FUInt64) ->
9101           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9102             n name
9103       | name, FInt64 ->
9104           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9105             n name
9106       | name, (FInt32|FUInt32) ->
9107           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9108             n name
9109       | name, FChar ->
9110           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9111             n name
9112       | name, FOptPercent ->
9113           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9114             n name
9115   ) cols;
9116   pr "      free (%s);\n" n
9117
9118 (* Generate Sys/Guestfs.pm. *)
9119 and generate_perl_pm () =
9120   generate_header HashStyle LGPLv2plus;
9121
9122   pr "\
9123 =pod
9124
9125 =head1 NAME
9126
9127 Sys::Guestfs - Perl bindings for libguestfs
9128
9129 =head1 SYNOPSIS
9130
9131  use Sys::Guestfs;
9132
9133  my $h = Sys::Guestfs->new ();
9134  $h->add_drive ('guest.img');
9135  $h->launch ();
9136  $h->mount ('/dev/sda1', '/');
9137  $h->touch ('/hello');
9138  $h->sync ();
9139
9140 =head1 DESCRIPTION
9141
9142 The C<Sys::Guestfs> module provides a Perl XS binding to the
9143 libguestfs API for examining and modifying virtual machine
9144 disk images.
9145
9146 Amongst the things this is good for: making batch configuration
9147 changes to guests, getting disk used/free statistics (see also:
9148 virt-df), migrating between virtualization systems (see also:
9149 virt-p2v), performing partial backups, performing partial guest
9150 clones, cloning guests and changing registry/UUID/hostname info, and
9151 much else besides.
9152
9153 Libguestfs uses Linux kernel and qemu code, and can access any type of
9154 guest filesystem that Linux and qemu can, including but not limited
9155 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9156 schemes, qcow, qcow2, vmdk.
9157
9158 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9159 LVs, what filesystem is in each LV, etc.).  It can also run commands
9160 in the context of the guest.  Also you can access filesystems over
9161 FUSE.
9162
9163 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9164 functions for using libguestfs from Perl, including integration
9165 with libvirt.
9166
9167 =head1 ERRORS
9168
9169 All errors turn into calls to C<croak> (see L<Carp(3)>).
9170
9171 =head1 METHODS
9172
9173 =over 4
9174
9175 =cut
9176
9177 package Sys::Guestfs;
9178
9179 use strict;
9180 use warnings;
9181
9182 # This version number changes whenever a new function
9183 # is added to the libguestfs API.  It is not directly
9184 # related to the libguestfs version number.
9185 use vars qw($VERSION);
9186 $VERSION = '0.%d';
9187
9188 require XSLoader;
9189 XSLoader::load ('Sys::Guestfs');
9190
9191 =item $h = Sys::Guestfs->new ();
9192
9193 Create a new guestfs handle.
9194
9195 =cut
9196
9197 sub new {
9198   my $proto = shift;
9199   my $class = ref ($proto) || $proto;
9200
9201   my $g = Sys::Guestfs::_create ();
9202   my $self = { _g => $g };
9203   bless $self, $class;
9204   return $self;
9205 }
9206
9207 =item $h->close ();
9208
9209 Explicitly close the guestfs handle.
9210
9211 B<Note:> You should not usually call this function.  The handle will
9212 be closed implicitly when its reference count goes to zero (eg.
9213 when it goes out of scope or the program ends).  This call is
9214 only required in some exceptional cases, such as where the program
9215 may contain cached references to the handle 'somewhere' and you
9216 really have to have the close happen right away.  After calling
9217 C<close> the program must not call any method (including C<close>)
9218 on the handle (but the implicit call to C<DESTROY> that happens
9219 when the final reference is cleaned up is OK).
9220
9221 =cut
9222
9223 " max_proc_nr;
9224
9225   (* Actions.  We only need to print documentation for these as
9226    * they are pulled in from the XS code automatically.
9227    *)
9228   List.iter (
9229     fun (name, style, _, flags, _, _, longdesc) ->
9230       if not (List.mem NotInDocs flags) then (
9231         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9232         pr "=item ";
9233         generate_perl_prototype name style;
9234         pr "\n\n";
9235         pr "%s\n\n" longdesc;
9236         if List.mem ProtocolLimitWarning flags then
9237           pr "%s\n\n" protocol_limit_warning;
9238         if List.mem DangerWillRobinson flags then
9239           pr "%s\n\n" danger_will_robinson;
9240         match deprecation_notice flags with
9241         | None -> ()
9242         | Some txt -> pr "%s\n\n" txt
9243       )
9244   ) all_functions_sorted;
9245
9246   (* End of file. *)
9247   pr "\
9248 =cut
9249
9250 1;
9251
9252 =back
9253
9254 =head1 AVAILABILITY
9255
9256 From time to time we add new libguestfs APIs.  Also some libguestfs
9257 APIs won't be available in all builds of libguestfs (the Fedora
9258 build is full-featured, but other builds may disable features).
9259 How do you test whether the APIs that your Perl program needs are
9260 available in the version of C<Sys::Guestfs> that you are using?
9261
9262 To test if a particular function is available in the C<Sys::Guestfs>
9263 class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
9264 (see L<perlobj(1)>).  For example:
9265
9266  use Sys::Guestfs;
9267  if (defined (Sys::Guestfs->can (\"set_verbose\"))) {
9268    print \"\\$h->set_verbose is available\\n\";
9269  }
9270
9271 To test if particular features are supported by the current
9272 build, use the L</available> method like the example below.  Note
9273 that the appliance must be launched first.
9274
9275  $h->available ( [\"augeas\"] );
9276
9277 Since the L</available> method croaks if the feature is not supported,
9278 you might also want to wrap this in an eval and return a boolean.
9279 In fact this has already been done for you: use
9280 L<Sys::Guestfs::Lib(3)/feature_available>.
9281
9282 For further discussion on this topic, refer to
9283 L<guestfs(3)/AVAILABILITY>.
9284
9285 =head1 STORING DATA IN THE HANDLE
9286
9287 The handle returned from L</new> is a hash reference.  The hash
9288 normally contains a single element:
9289
9290  {
9291    _g => [private data used by libguestfs]
9292  }
9293
9294 Callers can add other elements to this hash to store data for their own
9295 purposes.  The data lasts for the lifetime of the handle.
9296
9297 Any fields whose names begin with an underscore are reserved
9298 for private use by libguestfs.  We may add more in future.
9299
9300 It is recommended that callers prefix the name of their field(s)
9301 with some unique string, to avoid conflicts with other users.
9302
9303 =head1 COPYRIGHT
9304
9305 Copyright (C) %s Red Hat Inc.
9306
9307 =head1 LICENSE
9308
9309 Please see the file COPYING.LIB for the full license.
9310
9311 =head1 SEE ALSO
9312
9313 L<guestfs(3)>,
9314 L<guestfish(1)>,
9315 L<http://libguestfs.org>,
9316 L<Sys::Guestfs::Lib(3)>.
9317
9318 =cut
9319 " copyright_years
9320
9321 and generate_perl_prototype name style =
9322   (match fst style with
9323    | RErr -> ()
9324    | RBool n
9325    | RInt n
9326    | RInt64 n
9327    | RConstString n
9328    | RConstOptString n
9329    | RString n
9330    | RBufferOut n -> pr "$%s = " n
9331    | RStruct (n,_)
9332    | RHashtable n -> pr "%%%s = " n
9333    | RStringList n
9334    | RStructList (n,_) -> pr "@%s = " n
9335   );
9336   pr "$h->%s (" name;
9337   let comma = ref false in
9338   List.iter (
9339     fun arg ->
9340       if !comma then pr ", ";
9341       comma := true;
9342       match arg with
9343       | Pathname n | Device n | Dev_or_Path n | String n
9344       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9345       | BufferIn n ->
9346           pr "$%s" n
9347       | StringList n | DeviceList n ->
9348           pr "\\@%s" n
9349   ) (snd style);
9350   pr ");"
9351
9352 (* Generate Python C module. *)
9353 and generate_python_c () =
9354   generate_header CStyle LGPLv2plus;
9355
9356   pr "\
9357 #define PY_SSIZE_T_CLEAN 1
9358 #include <Python.h>
9359
9360 #if PY_VERSION_HEX < 0x02050000
9361 typedef int Py_ssize_t;
9362 #define PY_SSIZE_T_MAX INT_MAX
9363 #define PY_SSIZE_T_MIN INT_MIN
9364 #endif
9365
9366 #include <stdio.h>
9367 #include <stdlib.h>
9368 #include <assert.h>
9369
9370 #include \"guestfs.h\"
9371
9372 typedef struct {
9373   PyObject_HEAD
9374   guestfs_h *g;
9375 } Pyguestfs_Object;
9376
9377 static guestfs_h *
9378 get_handle (PyObject *obj)
9379 {
9380   assert (obj);
9381   assert (obj != Py_None);
9382   return ((Pyguestfs_Object *) obj)->g;
9383 }
9384
9385 static PyObject *
9386 put_handle (guestfs_h *g)
9387 {
9388   assert (g);
9389   return
9390     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9391 }
9392
9393 /* This list should be freed (but not the strings) after use. */
9394 static char **
9395 get_string_list (PyObject *obj)
9396 {
9397   size_t i, len;
9398   char **r;
9399
9400   assert (obj);
9401
9402   if (!PyList_Check (obj)) {
9403     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9404     return NULL;
9405   }
9406
9407   Py_ssize_t slen = PyList_Size (obj);
9408   if (slen == -1) {
9409     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9410     return NULL;
9411   }
9412   len = (size_t) slen;
9413   r = malloc (sizeof (char *) * (len+1));
9414   if (r == NULL) {
9415     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9416     return NULL;
9417   }
9418
9419   for (i = 0; i < len; ++i)
9420     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9421   r[len] = NULL;
9422
9423   return r;
9424 }
9425
9426 static PyObject *
9427 put_string_list (char * const * const argv)
9428 {
9429   PyObject *list;
9430   int argc, i;
9431
9432   for (argc = 0; argv[argc] != NULL; ++argc)
9433     ;
9434
9435   list = PyList_New (argc);
9436   for (i = 0; i < argc; ++i)
9437     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9438
9439   return list;
9440 }
9441
9442 static PyObject *
9443 put_table (char * const * const argv)
9444 {
9445   PyObject *list, *item;
9446   int argc, i;
9447
9448   for (argc = 0; argv[argc] != NULL; ++argc)
9449     ;
9450
9451   list = PyList_New (argc >> 1);
9452   for (i = 0; i < argc; i += 2) {
9453     item = PyTuple_New (2);
9454     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9455     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9456     PyList_SetItem (list, i >> 1, item);
9457   }
9458
9459   return list;
9460 }
9461
9462 static void
9463 free_strings (char **argv)
9464 {
9465   int argc;
9466
9467   for (argc = 0; argv[argc] != NULL; ++argc)
9468     free (argv[argc]);
9469   free (argv);
9470 }
9471
9472 static PyObject *
9473 py_guestfs_create (PyObject *self, PyObject *args)
9474 {
9475   guestfs_h *g;
9476
9477   g = guestfs_create ();
9478   if (g == NULL) {
9479     PyErr_SetString (PyExc_RuntimeError,
9480                      \"guestfs.create: failed to allocate handle\");
9481     return NULL;
9482   }
9483   guestfs_set_error_handler (g, NULL, NULL);
9484   return put_handle (g);
9485 }
9486
9487 static PyObject *
9488 py_guestfs_close (PyObject *self, PyObject *args)
9489 {
9490   PyObject *py_g;
9491   guestfs_h *g;
9492
9493   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9494     return NULL;
9495   g = get_handle (py_g);
9496
9497   guestfs_close (g);
9498
9499   Py_INCREF (Py_None);
9500   return Py_None;
9501 }
9502
9503 ";
9504
9505   let emit_put_list_function typ =
9506     pr "static PyObject *\n";
9507     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9508     pr "{\n";
9509     pr "  PyObject *list;\n";
9510     pr "  size_t i;\n";
9511     pr "\n";
9512     pr "  list = PyList_New (%ss->len);\n" typ;
9513     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9514     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9515     pr "  return list;\n";
9516     pr "};\n";
9517     pr "\n"
9518   in
9519
9520   (* Structures, turned into Python dictionaries. *)
9521   List.iter (
9522     fun (typ, cols) ->
9523       pr "static PyObject *\n";
9524       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9525       pr "{\n";
9526       pr "  PyObject *dict;\n";
9527       pr "\n";
9528       pr "  dict = PyDict_New ();\n";
9529       List.iter (
9530         function
9531         | name, FString ->
9532             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9533             pr "                        PyString_FromString (%s->%s));\n"
9534               typ name
9535         | name, FBuffer ->
9536             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9537             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9538               typ name typ name
9539         | name, FUUID ->
9540             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9541             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9542               typ name
9543         | name, (FBytes|FUInt64) ->
9544             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9545             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9546               typ name
9547         | name, FInt64 ->
9548             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9549             pr "                        PyLong_FromLongLong (%s->%s));\n"
9550               typ name
9551         | name, FUInt32 ->
9552             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9553             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9554               typ name
9555         | name, FInt32 ->
9556             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9557             pr "                        PyLong_FromLong (%s->%s));\n"
9558               typ name
9559         | name, FOptPercent ->
9560             pr "  if (%s->%s >= 0)\n" typ name;
9561             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9562             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9563               typ name;
9564             pr "  else {\n";
9565             pr "    Py_INCREF (Py_None);\n";
9566             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9567             pr "  }\n"
9568         | name, FChar ->
9569             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9570             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9571       ) cols;
9572       pr "  return dict;\n";
9573       pr "};\n";
9574       pr "\n";
9575
9576   ) structs;
9577
9578   (* Emit a put_TYPE_list function definition only if that function is used. *)
9579   List.iter (
9580     function
9581     | typ, (RStructListOnly | RStructAndList) ->
9582         (* generate the function for typ *)
9583         emit_put_list_function typ
9584     | typ, _ -> () (* empty *)
9585   ) (rstructs_used_by all_functions);
9586
9587   (* Python wrapper functions. *)
9588   List.iter (
9589     fun (name, style, _, _, _, _, _) ->
9590       pr "static PyObject *\n";
9591       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9592       pr "{\n";
9593
9594       pr "  PyObject *py_g;\n";
9595       pr "  guestfs_h *g;\n";
9596       pr "  PyObject *py_r;\n";
9597
9598       let error_code =
9599         match fst style with
9600         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9601         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9602         | RConstString _ | RConstOptString _ ->
9603             pr "  const char *r;\n"; "NULL"
9604         | RString _ -> pr "  char *r;\n"; "NULL"
9605         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9606         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9607         | RStructList (_, typ) ->
9608             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9609         | RBufferOut _ ->
9610             pr "  char *r;\n";
9611             pr "  size_t size;\n";
9612             "NULL" in
9613
9614       List.iter (
9615         function
9616         | Pathname n | Device n | Dev_or_Path n | String n
9617         | FileIn n | FileOut n ->
9618             pr "  const char *%s;\n" n
9619         | OptString n -> pr "  const char *%s;\n" n
9620         | BufferIn n ->
9621             pr "  const char *%s;\n" n;
9622             pr "  Py_ssize_t %s_size;\n" n
9623         | StringList n | DeviceList n ->
9624             pr "  PyObject *py_%s;\n" n;
9625             pr "  char **%s;\n" n
9626         | Bool n -> pr "  int %s;\n" n
9627         | Int n -> pr "  int %s;\n" n
9628         | Int64 n -> pr "  long long %s;\n" n
9629       ) (snd style);
9630
9631       pr "\n";
9632
9633       (* Convert the parameters. *)
9634       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9635       List.iter (
9636         function
9637         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9638         | OptString _ -> pr "z"
9639         | StringList _ | DeviceList _ -> pr "O"
9640         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9641         | Int _ -> pr "i"
9642         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9643                              * emulate C's int/long/long long in Python?
9644                              *)
9645         | BufferIn _ -> pr "s#"
9646       ) (snd style);
9647       pr ":guestfs_%s\",\n" name;
9648       pr "                         &py_g";
9649       List.iter (
9650         function
9651         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9652         | OptString n -> pr ", &%s" n
9653         | StringList n | DeviceList n -> pr ", &py_%s" n
9654         | Bool n -> pr ", &%s" n
9655         | Int n -> pr ", &%s" n
9656         | Int64 n -> pr ", &%s" n
9657         | BufferIn n -> pr ", &%s, &%s_size" n n
9658       ) (snd style);
9659
9660       pr "))\n";
9661       pr "    return NULL;\n";
9662
9663       pr "  g = get_handle (py_g);\n";
9664       List.iter (
9665         function
9666         | Pathname _ | Device _ | Dev_or_Path _ | String _
9667         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9668         | BufferIn _ -> ()
9669         | StringList n | DeviceList n ->
9670             pr "  %s = get_string_list (py_%s);\n" n n;
9671             pr "  if (!%s) return NULL;\n" n
9672       ) (snd style);
9673
9674       pr "\n";
9675
9676       pr "  r = guestfs_%s " name;
9677       generate_c_call_args ~handle:"g" style;
9678       pr ";\n";
9679
9680       List.iter (
9681         function
9682         | Pathname _ | Device _ | Dev_or_Path _ | String _
9683         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9684         | BufferIn _ -> ()
9685         | StringList n | DeviceList n ->
9686             pr "  free (%s);\n" n
9687       ) (snd style);
9688
9689       pr "  if (r == %s) {\n" error_code;
9690       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9691       pr "    return NULL;\n";
9692       pr "  }\n";
9693       pr "\n";
9694
9695       (match fst style with
9696        | RErr ->
9697            pr "  Py_INCREF (Py_None);\n";
9698            pr "  py_r = Py_None;\n"
9699        | RInt _
9700        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9701        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9702        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9703        | RConstOptString _ ->
9704            pr "  if (r)\n";
9705            pr "    py_r = PyString_FromString (r);\n";
9706            pr "  else {\n";
9707            pr "    Py_INCREF (Py_None);\n";
9708            pr "    py_r = Py_None;\n";
9709            pr "  }\n"
9710        | RString _ ->
9711            pr "  py_r = PyString_FromString (r);\n";
9712            pr "  free (r);\n"
9713        | RStringList _ ->
9714            pr "  py_r = put_string_list (r);\n";
9715            pr "  free_strings (r);\n"
9716        | RStruct (_, typ) ->
9717            pr "  py_r = put_%s (r);\n" typ;
9718            pr "  guestfs_free_%s (r);\n" typ
9719        | RStructList (_, typ) ->
9720            pr "  py_r = put_%s_list (r);\n" typ;
9721            pr "  guestfs_free_%s_list (r);\n" typ
9722        | RHashtable n ->
9723            pr "  py_r = put_table (r);\n";
9724            pr "  free_strings (r);\n"
9725        | RBufferOut _ ->
9726            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9727            pr "  free (r);\n"
9728       );
9729
9730       pr "  return py_r;\n";
9731       pr "}\n";
9732       pr "\n"
9733   ) all_functions;
9734
9735   (* Table of functions. *)
9736   pr "static PyMethodDef methods[] = {\n";
9737   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9738   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9739   List.iter (
9740     fun (name, _, _, _, _, _, _) ->
9741       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9742         name name
9743   ) all_functions;
9744   pr "  { NULL, NULL, 0, NULL }\n";
9745   pr "};\n";
9746   pr "\n";
9747
9748   (* Init function. *)
9749   pr "\
9750 void
9751 initlibguestfsmod (void)
9752 {
9753   static int initialized = 0;
9754
9755   if (initialized) return;
9756   Py_InitModule ((char *) \"libguestfsmod\", methods);
9757   initialized = 1;
9758 }
9759 "
9760
9761 (* Generate Python module. *)
9762 and generate_python_py () =
9763   generate_header HashStyle LGPLv2plus;
9764
9765   pr "\
9766 u\"\"\"Python bindings for libguestfs
9767
9768 import guestfs
9769 g = guestfs.GuestFS ()
9770 g.add_drive (\"guest.img\")
9771 g.launch ()
9772 parts = g.list_partitions ()
9773
9774 The guestfs module provides a Python binding to the libguestfs API
9775 for examining and modifying virtual machine disk images.
9776
9777 Amongst the things this is good for: making batch configuration
9778 changes to guests, getting disk used/free statistics (see also:
9779 virt-df), migrating between virtualization systems (see also:
9780 virt-p2v), performing partial backups, performing partial guest
9781 clones, cloning guests and changing registry/UUID/hostname info, and
9782 much else besides.
9783
9784 Libguestfs uses Linux kernel and qemu code, and can access any type of
9785 guest filesystem that Linux and qemu can, including but not limited
9786 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9787 schemes, qcow, qcow2, vmdk.
9788
9789 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9790 LVs, what filesystem is in each LV, etc.).  It can also run commands
9791 in the context of the guest.  Also you can access filesystems over
9792 FUSE.
9793
9794 Errors which happen while using the API are turned into Python
9795 RuntimeError exceptions.
9796
9797 To create a guestfs handle you usually have to perform the following
9798 sequence of calls:
9799
9800 # Create the handle, call add_drive at least once, and possibly
9801 # several times if the guest has multiple block devices:
9802 g = guestfs.GuestFS ()
9803 g.add_drive (\"guest.img\")
9804
9805 # Launch the qemu subprocess and wait for it to become ready:
9806 g.launch ()
9807
9808 # Now you can issue commands, for example:
9809 logvols = g.lvs ()
9810
9811 \"\"\"
9812
9813 import libguestfsmod
9814
9815 class GuestFS:
9816     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9817
9818     def __init__ (self):
9819         \"\"\"Create a new libguestfs handle.\"\"\"
9820         self._o = libguestfsmod.create ()
9821
9822     def __del__ (self):
9823         libguestfsmod.close (self._o)
9824
9825 ";
9826
9827   List.iter (
9828     fun (name, style, _, flags, _, _, longdesc) ->
9829       pr "    def %s " name;
9830       generate_py_call_args ~handle:"self" (snd style);
9831       pr ":\n";
9832
9833       if not (List.mem NotInDocs flags) then (
9834         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9835         let doc =
9836           match fst style with
9837           | RErr | RInt _ | RInt64 _ | RBool _
9838           | RConstOptString _ | RConstString _
9839           | RString _ | RBufferOut _ -> doc
9840           | RStringList _ ->
9841               doc ^ "\n\nThis function returns a list of strings."
9842           | RStruct (_, typ) ->
9843               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9844           | RStructList (_, typ) ->
9845               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9846           | RHashtable _ ->
9847               doc ^ "\n\nThis function returns a dictionary." in
9848         let doc =
9849           if List.mem ProtocolLimitWarning flags then
9850             doc ^ "\n\n" ^ protocol_limit_warning
9851           else doc in
9852         let doc =
9853           if List.mem DangerWillRobinson flags then
9854             doc ^ "\n\n" ^ danger_will_robinson
9855           else doc in
9856         let doc =
9857           match deprecation_notice flags with
9858           | None -> doc
9859           | Some txt -> doc ^ "\n\n" ^ txt in
9860         let doc = pod2text ~width:60 name doc in
9861         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9862         let doc = String.concat "\n        " doc in
9863         pr "        u\"\"\"%s\"\"\"\n" doc;
9864       );
9865       pr "        return libguestfsmod.%s " name;
9866       generate_py_call_args ~handle:"self._o" (snd style);
9867       pr "\n";
9868       pr "\n";
9869   ) all_functions
9870
9871 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9872 and generate_py_call_args ~handle args =
9873   pr "(%s" handle;
9874   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9875   pr ")"
9876
9877 (* Useful if you need the longdesc POD text as plain text.  Returns a
9878  * list of lines.
9879  *
9880  * Because this is very slow (the slowest part of autogeneration),
9881  * we memoize the results.
9882  *)
9883 and pod2text ~width name longdesc =
9884   let key = width, name, longdesc in
9885   try Hashtbl.find pod2text_memo key
9886   with Not_found ->
9887     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9888     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9889     close_out chan;
9890     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9891     let chan = open_process_in cmd in
9892     let lines = ref [] in
9893     let rec loop i =
9894       let line = input_line chan in
9895       if i = 1 then             (* discard the first line of output *)
9896         loop (i+1)
9897       else (
9898         let line = triml line in
9899         lines := line :: !lines;
9900         loop (i+1)
9901       ) in
9902     let lines = try loop 1 with End_of_file -> List.rev !lines in
9903     unlink filename;
9904     (match close_process_in chan with
9905      | WEXITED 0 -> ()
9906      | WEXITED i ->
9907          failwithf "pod2text: process exited with non-zero status (%d)" i
9908      | WSIGNALED i | WSTOPPED i ->
9909          failwithf "pod2text: process signalled or stopped by signal %d" i
9910     );
9911     Hashtbl.add pod2text_memo key lines;
9912     pod2text_memo_updated ();
9913     lines
9914
9915 (* Generate ruby bindings. *)
9916 and generate_ruby_c () =
9917   generate_header CStyle LGPLv2plus;
9918
9919   pr "\
9920 #include <stdio.h>
9921 #include <stdlib.h>
9922
9923 #include <ruby.h>
9924
9925 #include \"guestfs.h\"
9926
9927 #include \"extconf.h\"
9928
9929 /* For Ruby < 1.9 */
9930 #ifndef RARRAY_LEN
9931 #define RARRAY_LEN(r) (RARRAY((r))->len)
9932 #endif
9933
9934 static VALUE m_guestfs;                 /* guestfs module */
9935 static VALUE c_guestfs;                 /* guestfs_h handle */
9936 static VALUE e_Error;                   /* used for all errors */
9937
9938 static void ruby_guestfs_free (void *p)
9939 {
9940   if (!p) return;
9941   guestfs_close ((guestfs_h *) p);
9942 }
9943
9944 static VALUE ruby_guestfs_create (VALUE m)
9945 {
9946   guestfs_h *g;
9947
9948   g = guestfs_create ();
9949   if (!g)
9950     rb_raise (e_Error, \"failed to create guestfs handle\");
9951
9952   /* Don't print error messages to stderr by default. */
9953   guestfs_set_error_handler (g, NULL, NULL);
9954
9955   /* Wrap it, and make sure the close function is called when the
9956    * handle goes away.
9957    */
9958   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9959 }
9960
9961 static VALUE ruby_guestfs_close (VALUE gv)
9962 {
9963   guestfs_h *g;
9964   Data_Get_Struct (gv, guestfs_h, g);
9965
9966   ruby_guestfs_free (g);
9967   DATA_PTR (gv) = NULL;
9968
9969   return Qnil;
9970 }
9971
9972 ";
9973
9974   List.iter (
9975     fun (name, style, _, _, _, _, _) ->
9976       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9977       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9978       pr ")\n";
9979       pr "{\n";
9980       pr "  guestfs_h *g;\n";
9981       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9982       pr "  if (!g)\n";
9983       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9984         name;
9985       pr "\n";
9986
9987       List.iter (
9988         function
9989         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9990             pr "  Check_Type (%sv, T_STRING);\n" n;
9991             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9992             pr "  if (!%s)\n" n;
9993             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9994             pr "              \"%s\", \"%s\");\n" n name
9995         | BufferIn n ->
9996             pr "  Check_Type (%sv, T_STRING);\n" n;
9997             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9998             pr "  if (!%s)\n" n;
9999             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10000             pr "              \"%s\", \"%s\");\n" n name;
10001             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10002         | OptString n ->
10003             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10004         | StringList n | DeviceList n ->
10005             pr "  char **%s;\n" n;
10006             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10007             pr "  {\n";
10008             pr "    size_t i, len;\n";
10009             pr "    len = RARRAY_LEN (%sv);\n" n;
10010             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10011               n;
10012             pr "    for (i = 0; i < len; ++i) {\n";
10013             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10014             pr "      %s[i] = StringValueCStr (v);\n" n;
10015             pr "    }\n";
10016             pr "    %s[len] = NULL;\n" n;
10017             pr "  }\n";
10018         | Bool n ->
10019             pr "  int %s = RTEST (%sv);\n" n n
10020         | Int n ->
10021             pr "  int %s = NUM2INT (%sv);\n" n n
10022         | Int64 n ->
10023             pr "  long long %s = NUM2LL (%sv);\n" n n
10024       ) (snd style);
10025       pr "\n";
10026
10027       let error_code =
10028         match fst style with
10029         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10030         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10031         | RConstString _ | RConstOptString _ ->
10032             pr "  const char *r;\n"; "NULL"
10033         | RString _ -> pr "  char *r;\n"; "NULL"
10034         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10035         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10036         | RStructList (_, typ) ->
10037             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10038         | RBufferOut _ ->
10039             pr "  char *r;\n";
10040             pr "  size_t size;\n";
10041             "NULL" in
10042       pr "\n";
10043
10044       pr "  r = guestfs_%s " name;
10045       generate_c_call_args ~handle:"g" style;
10046       pr ";\n";
10047
10048       List.iter (
10049         function
10050         | Pathname _ | Device _ | Dev_or_Path _ | String _
10051         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10052         | BufferIn _ -> ()
10053         | StringList n | DeviceList n ->
10054             pr "  free (%s);\n" n
10055       ) (snd style);
10056
10057       pr "  if (r == %s)\n" error_code;
10058       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10059       pr "\n";
10060
10061       (match fst style with
10062        | RErr ->
10063            pr "  return Qnil;\n"
10064        | RInt _ | RBool _ ->
10065            pr "  return INT2NUM (r);\n"
10066        | RInt64 _ ->
10067            pr "  return ULL2NUM (r);\n"
10068        | RConstString _ ->
10069            pr "  return rb_str_new2 (r);\n";
10070        | RConstOptString _ ->
10071            pr "  if (r)\n";
10072            pr "    return rb_str_new2 (r);\n";
10073            pr "  else\n";
10074            pr "    return Qnil;\n";
10075        | RString _ ->
10076            pr "  VALUE rv = rb_str_new2 (r);\n";
10077            pr "  free (r);\n";
10078            pr "  return rv;\n";
10079        | RStringList _ ->
10080            pr "  size_t i, len = 0;\n";
10081            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10082            pr "  VALUE rv = rb_ary_new2 (len);\n";
10083            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10084            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10085            pr "    free (r[i]);\n";
10086            pr "  }\n";
10087            pr "  free (r);\n";
10088            pr "  return rv;\n"
10089        | RStruct (_, typ) ->
10090            let cols = cols_of_struct typ in
10091            generate_ruby_struct_code typ cols
10092        | RStructList (_, typ) ->
10093            let cols = cols_of_struct typ in
10094            generate_ruby_struct_list_code typ cols
10095        | RHashtable _ ->
10096            pr "  VALUE rv = rb_hash_new ();\n";
10097            pr "  size_t i;\n";
10098            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10099            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10100            pr "    free (r[i]);\n";
10101            pr "    free (r[i+1]);\n";
10102            pr "  }\n";
10103            pr "  free (r);\n";
10104            pr "  return rv;\n"
10105        | RBufferOut _ ->
10106            pr "  VALUE rv = rb_str_new (r, size);\n";
10107            pr "  free (r);\n";
10108            pr "  return rv;\n";
10109       );
10110
10111       pr "}\n";
10112       pr "\n"
10113   ) all_functions;
10114
10115   pr "\
10116 /* Initialize the module. */
10117 void Init__guestfs ()
10118 {
10119   m_guestfs = rb_define_module (\"Guestfs\");
10120   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10121   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10122
10123   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10124   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10125
10126 ";
10127   (* Define the rest of the methods. *)
10128   List.iter (
10129     fun (name, style, _, _, _, _, _) ->
10130       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10131       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10132   ) all_functions;
10133
10134   pr "}\n"
10135
10136 (* Ruby code to return a struct. *)
10137 and generate_ruby_struct_code typ cols =
10138   pr "  VALUE rv = rb_hash_new ();\n";
10139   List.iter (
10140     function
10141     | name, FString ->
10142         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10143     | name, FBuffer ->
10144         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10145     | name, FUUID ->
10146         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10147     | name, (FBytes|FUInt64) ->
10148         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10149     | name, FInt64 ->
10150         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10151     | name, FUInt32 ->
10152         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10153     | name, FInt32 ->
10154         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10155     | name, FOptPercent ->
10156         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10157     | name, FChar -> (* XXX wrong? *)
10158         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10159   ) cols;
10160   pr "  guestfs_free_%s (r);\n" typ;
10161   pr "  return rv;\n"
10162
10163 (* Ruby code to return a struct list. *)
10164 and generate_ruby_struct_list_code typ cols =
10165   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10166   pr "  size_t i;\n";
10167   pr "  for (i = 0; i < r->len; ++i) {\n";
10168   pr "    VALUE hv = rb_hash_new ();\n";
10169   List.iter (
10170     function
10171     | name, FString ->
10172         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10173     | name, FBuffer ->
10174         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
10175     | name, FUUID ->
10176         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10177     | name, (FBytes|FUInt64) ->
10178         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10179     | name, FInt64 ->
10180         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10181     | name, FUInt32 ->
10182         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10183     | name, FInt32 ->
10184         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10185     | name, FOptPercent ->
10186         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10187     | name, FChar -> (* XXX wrong? *)
10188         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10189   ) cols;
10190   pr "    rb_ary_push (rv, hv);\n";
10191   pr "  }\n";
10192   pr "  guestfs_free_%s_list (r);\n" typ;
10193   pr "  return rv;\n"
10194
10195 (* Generate Java bindings GuestFS.java file. *)
10196 and generate_java_java () =
10197   generate_header CStyle LGPLv2plus;
10198
10199   pr "\
10200 package com.redhat.et.libguestfs;
10201
10202 import java.util.HashMap;
10203 import com.redhat.et.libguestfs.LibGuestFSException;
10204 import com.redhat.et.libguestfs.PV;
10205 import com.redhat.et.libguestfs.VG;
10206 import com.redhat.et.libguestfs.LV;
10207 import com.redhat.et.libguestfs.Stat;
10208 import com.redhat.et.libguestfs.StatVFS;
10209 import com.redhat.et.libguestfs.IntBool;
10210 import com.redhat.et.libguestfs.Dirent;
10211
10212 /**
10213  * The GuestFS object is a libguestfs handle.
10214  *
10215  * @author rjones
10216  */
10217 public class GuestFS {
10218   // Load the native code.
10219   static {
10220     System.loadLibrary (\"guestfs_jni\");
10221   }
10222
10223   /**
10224    * The native guestfs_h pointer.
10225    */
10226   long g;
10227
10228   /**
10229    * Create a libguestfs handle.
10230    *
10231    * @throws LibGuestFSException
10232    */
10233   public GuestFS () throws LibGuestFSException
10234   {
10235     g = _create ();
10236   }
10237   private native long _create () throws LibGuestFSException;
10238
10239   /**
10240    * Close a libguestfs handle.
10241    *
10242    * You can also leave handles to be collected by the garbage
10243    * collector, but this method ensures that the resources used
10244    * by the handle are freed up immediately.  If you call any
10245    * other methods after closing the handle, you will get an
10246    * exception.
10247    *
10248    * @throws LibGuestFSException
10249    */
10250   public void close () throws LibGuestFSException
10251   {
10252     if (g != 0)
10253       _close (g);
10254     g = 0;
10255   }
10256   private native void _close (long g) throws LibGuestFSException;
10257
10258   public void finalize () throws LibGuestFSException
10259   {
10260     close ();
10261   }
10262
10263 ";
10264
10265   List.iter (
10266     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10267       if not (List.mem NotInDocs flags); then (
10268         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10269         let doc =
10270           if List.mem ProtocolLimitWarning flags then
10271             doc ^ "\n\n" ^ protocol_limit_warning
10272           else doc in
10273         let doc =
10274           if List.mem DangerWillRobinson flags then
10275             doc ^ "\n\n" ^ danger_will_robinson
10276           else doc in
10277         let doc =
10278           match deprecation_notice flags with
10279           | None -> doc
10280           | Some txt -> doc ^ "\n\n" ^ txt in
10281         let doc = pod2text ~width:60 name doc in
10282         let doc = List.map (            (* RHBZ#501883 *)
10283           function
10284           | "" -> "<p>"
10285           | nonempty -> nonempty
10286         ) doc in
10287         let doc = String.concat "\n   * " doc in
10288
10289         pr "  /**\n";
10290         pr "   * %s\n" shortdesc;
10291         pr "   * <p>\n";
10292         pr "   * %s\n" doc;
10293         pr "   * @throws LibGuestFSException\n";
10294         pr "   */\n";
10295         pr "  ";
10296       );
10297       generate_java_prototype ~public:true ~semicolon:false name style;
10298       pr "\n";
10299       pr "  {\n";
10300       pr "    if (g == 0)\n";
10301       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10302         name;
10303       pr "    ";
10304       if fst style <> RErr then pr "return ";
10305       pr "_%s " name;
10306       generate_java_call_args ~handle:"g" (snd style);
10307       pr ";\n";
10308       pr "  }\n";
10309       pr "  ";
10310       generate_java_prototype ~privat:true ~native:true name style;
10311       pr "\n";
10312       pr "\n";
10313   ) all_functions;
10314
10315   pr "}\n"
10316
10317 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10318 and generate_java_call_args ~handle args =
10319   pr "(%s" handle;
10320   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10321   pr ")"
10322
10323 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10324     ?(semicolon=true) name style =
10325   if privat then pr "private ";
10326   if public then pr "public ";
10327   if native then pr "native ";
10328
10329   (* return type *)
10330   (match fst style with
10331    | RErr -> pr "void ";
10332    | RInt _ -> pr "int ";
10333    | RInt64 _ -> pr "long ";
10334    | RBool _ -> pr "boolean ";
10335    | RConstString _ | RConstOptString _ | RString _
10336    | RBufferOut _ -> pr "String ";
10337    | RStringList _ -> pr "String[] ";
10338    | RStruct (_, typ) ->
10339        let name = java_name_of_struct typ in
10340        pr "%s " name;
10341    | RStructList (_, typ) ->
10342        let name = java_name_of_struct typ in
10343        pr "%s[] " name;
10344    | RHashtable _ -> pr "HashMap<String,String> ";
10345   );
10346
10347   if native then pr "_%s " name else pr "%s " name;
10348   pr "(";
10349   let needs_comma = ref false in
10350   if native then (
10351     pr "long g";
10352     needs_comma := true
10353   );
10354
10355   (* args *)
10356   List.iter (
10357     fun arg ->
10358       if !needs_comma then pr ", ";
10359       needs_comma := true;
10360
10361       match arg with
10362       | Pathname n
10363       | Device n | Dev_or_Path n
10364       | String n
10365       | OptString n
10366       | FileIn n
10367       | FileOut n ->
10368           pr "String %s" n
10369       | BufferIn n ->
10370           pr "byte[] %s" n
10371       | StringList n | DeviceList n ->
10372           pr "String[] %s" n
10373       | Bool n ->
10374           pr "boolean %s" n
10375       | Int n ->
10376           pr "int %s" n
10377       | Int64 n ->
10378           pr "long %s" n
10379   ) (snd style);
10380
10381   pr ")\n";
10382   pr "    throws LibGuestFSException";
10383   if semicolon then pr ";"
10384
10385 and generate_java_struct jtyp cols () =
10386   generate_header CStyle LGPLv2plus;
10387
10388   pr "\
10389 package com.redhat.et.libguestfs;
10390
10391 /**
10392  * Libguestfs %s structure.
10393  *
10394  * @author rjones
10395  * @see GuestFS
10396  */
10397 public class %s {
10398 " jtyp jtyp;
10399
10400   List.iter (
10401     function
10402     | name, FString
10403     | name, FUUID
10404     | name, FBuffer -> pr "  public String %s;\n" name
10405     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10406     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10407     | name, FChar -> pr "  public char %s;\n" name
10408     | name, FOptPercent ->
10409         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10410         pr "  public float %s;\n" name
10411   ) cols;
10412
10413   pr "}\n"
10414
10415 and generate_java_c () =
10416   generate_header CStyle LGPLv2plus;
10417
10418   pr "\
10419 #include <stdio.h>
10420 #include <stdlib.h>
10421 #include <string.h>
10422
10423 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10424 #include \"guestfs.h\"
10425
10426 /* Note that this function returns.  The exception is not thrown
10427  * until after the wrapper function returns.
10428  */
10429 static void
10430 throw_exception (JNIEnv *env, const char *msg)
10431 {
10432   jclass cl;
10433   cl = (*env)->FindClass (env,
10434                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10435   (*env)->ThrowNew (env, cl, msg);
10436 }
10437
10438 JNIEXPORT jlong JNICALL
10439 Java_com_redhat_et_libguestfs_GuestFS__1create
10440   (JNIEnv *env, jobject obj)
10441 {
10442   guestfs_h *g;
10443
10444   g = guestfs_create ();
10445   if (g == NULL) {
10446     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10447     return 0;
10448   }
10449   guestfs_set_error_handler (g, NULL, NULL);
10450   return (jlong) (long) g;
10451 }
10452
10453 JNIEXPORT void JNICALL
10454 Java_com_redhat_et_libguestfs_GuestFS__1close
10455   (JNIEnv *env, jobject obj, jlong jg)
10456 {
10457   guestfs_h *g = (guestfs_h *) (long) jg;
10458   guestfs_close (g);
10459 }
10460
10461 ";
10462
10463   List.iter (
10464     fun (name, style, _, _, _, _, _) ->
10465       pr "JNIEXPORT ";
10466       (match fst style with
10467        | RErr -> pr "void ";
10468        | RInt _ -> pr "jint ";
10469        | RInt64 _ -> pr "jlong ";
10470        | RBool _ -> pr "jboolean ";
10471        | RConstString _ | RConstOptString _ | RString _
10472        | RBufferOut _ -> pr "jstring ";
10473        | RStruct _ | RHashtable _ ->
10474            pr "jobject ";
10475        | RStringList _ | RStructList _ ->
10476            pr "jobjectArray ";
10477       );
10478       pr "JNICALL\n";
10479       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10480       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10481       pr "\n";
10482       pr "  (JNIEnv *env, jobject obj, jlong jg";
10483       List.iter (
10484         function
10485         | Pathname n
10486         | Device n | Dev_or_Path n
10487         | String n
10488         | OptString n
10489         | FileIn n
10490         | FileOut n ->
10491             pr ", jstring j%s" n
10492         | BufferIn n ->
10493             pr ", jbyteArray j%s" n
10494         | StringList n | DeviceList n ->
10495             pr ", jobjectArray j%s" n
10496         | Bool n ->
10497             pr ", jboolean j%s" n
10498         | Int n ->
10499             pr ", jint j%s" n
10500         | Int64 n ->
10501             pr ", jlong j%s" n
10502       ) (snd style);
10503       pr ")\n";
10504       pr "{\n";
10505       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10506       let error_code, no_ret =
10507         match fst style with
10508         | RErr -> pr "  int r;\n"; "-1", ""
10509         | RBool _
10510         | RInt _ -> pr "  int r;\n"; "-1", "0"
10511         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10512         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10513         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10514         | RString _ ->
10515             pr "  jstring jr;\n";
10516             pr "  char *r;\n"; "NULL", "NULL"
10517         | RStringList _ ->
10518             pr "  jobjectArray jr;\n";
10519             pr "  int r_len;\n";
10520             pr "  jclass cl;\n";
10521             pr "  jstring jstr;\n";
10522             pr "  char **r;\n"; "NULL", "NULL"
10523         | RStruct (_, typ) ->
10524             pr "  jobject jr;\n";
10525             pr "  jclass cl;\n";
10526             pr "  jfieldID fl;\n";
10527             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10528         | RStructList (_, typ) ->
10529             pr "  jobjectArray jr;\n";
10530             pr "  jclass cl;\n";
10531             pr "  jfieldID fl;\n";
10532             pr "  jobject jfl;\n";
10533             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10534         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10535         | RBufferOut _ ->
10536             pr "  jstring jr;\n";
10537             pr "  char *r;\n";
10538             pr "  size_t size;\n";
10539             "NULL", "NULL" in
10540       List.iter (
10541         function
10542         | Pathname n
10543         | Device n | Dev_or_Path n
10544         | String n
10545         | OptString n
10546         | FileIn n
10547         | FileOut n ->
10548             pr "  const char *%s;\n" n
10549         | BufferIn n ->
10550             pr "  jbyte *%s;\n" n;
10551             pr "  size_t %s_size;\n" n
10552         | StringList n | DeviceList n ->
10553             pr "  int %s_len;\n" n;
10554             pr "  const char **%s;\n" n
10555         | Bool n
10556         | Int n ->
10557             pr "  int %s;\n" n
10558         | Int64 n ->
10559             pr "  int64_t %s;\n" n
10560       ) (snd style);
10561
10562       let needs_i =
10563         (match fst style with
10564          | RStringList _ | RStructList _ -> true
10565          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10566          | RConstOptString _
10567          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10568           List.exists (function
10569                        | StringList _ -> true
10570                        | DeviceList _ -> true
10571                        | _ -> false) (snd style) in
10572       if needs_i then
10573         pr "  size_t i;\n";
10574
10575       pr "\n";
10576
10577       (* Get the parameters. *)
10578       List.iter (
10579         function
10580         | Pathname n
10581         | Device n | Dev_or_Path n
10582         | String n
10583         | FileIn n
10584         | FileOut n ->
10585             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10586         | OptString n ->
10587             (* This is completely undocumented, but Java null becomes
10588              * a NULL parameter.
10589              *)
10590             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10591         | BufferIn n ->
10592             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10593             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10594         | StringList n | DeviceList n ->
10595             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10596             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10597             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10598             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10599               n;
10600             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10601             pr "  }\n";
10602             pr "  %s[%s_len] = NULL;\n" n n;
10603         | Bool n
10604         | Int n
10605         | Int64 n ->
10606             pr "  %s = j%s;\n" n n
10607       ) (snd style);
10608
10609       (* Make the call. *)
10610       pr "  r = guestfs_%s " name;
10611       generate_c_call_args ~handle:"g" style;
10612       pr ";\n";
10613
10614       (* Release the parameters. *)
10615       List.iter (
10616         function
10617         | Pathname n
10618         | Device n | Dev_or_Path n
10619         | String n
10620         | FileIn n
10621         | FileOut n ->
10622             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10623         | OptString n ->
10624             pr "  if (j%s)\n" n;
10625             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10626         | BufferIn n ->
10627             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10628         | StringList n | DeviceList n ->
10629             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10630             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10631               n;
10632             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10633             pr "  }\n";
10634             pr "  free (%s);\n" n
10635         | Bool n
10636         | Int n
10637         | Int64 n -> ()
10638       ) (snd style);
10639
10640       (* Check for errors. *)
10641       pr "  if (r == %s) {\n" error_code;
10642       pr "    throw_exception (env, guestfs_last_error (g));\n";
10643       pr "    return %s;\n" no_ret;
10644       pr "  }\n";
10645
10646       (* Return value. *)
10647       (match fst style with
10648        | RErr -> ()
10649        | RInt _ -> pr "  return (jint) r;\n"
10650        | RBool _ -> pr "  return (jboolean) r;\n"
10651        | RInt64 _ -> pr "  return (jlong) r;\n"
10652        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10653        | RConstOptString _ ->
10654            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10655        | RString _ ->
10656            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10657            pr "  free (r);\n";
10658            pr "  return jr;\n"
10659        | RStringList _ ->
10660            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10661            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10662            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10663            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10664            pr "  for (i = 0; i < r_len; ++i) {\n";
10665            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10666            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10667            pr "    free (r[i]);\n";
10668            pr "  }\n";
10669            pr "  free (r);\n";
10670            pr "  return jr;\n"
10671        | RStruct (_, typ) ->
10672            let jtyp = java_name_of_struct typ in
10673            let cols = cols_of_struct typ in
10674            generate_java_struct_return typ jtyp cols
10675        | RStructList (_, typ) ->
10676            let jtyp = java_name_of_struct typ in
10677            let cols = cols_of_struct typ in
10678            generate_java_struct_list_return typ jtyp cols
10679        | RHashtable _ ->
10680            (* XXX *)
10681            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10682            pr "  return NULL;\n"
10683        | RBufferOut _ ->
10684            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10685            pr "  free (r);\n";
10686            pr "  return jr;\n"
10687       );
10688
10689       pr "}\n";
10690       pr "\n"
10691   ) all_functions
10692
10693 and generate_java_struct_return typ jtyp cols =
10694   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10695   pr "  jr = (*env)->AllocObject (env, cl);\n";
10696   List.iter (
10697     function
10698     | name, FString ->
10699         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10700         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10701     | name, FUUID ->
10702         pr "  {\n";
10703         pr "    char s[33];\n";
10704         pr "    memcpy (s, r->%s, 32);\n" name;
10705         pr "    s[32] = 0;\n";
10706         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10707         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10708         pr "  }\n";
10709     | name, FBuffer ->
10710         pr "  {\n";
10711         pr "    int len = r->%s_len;\n" name;
10712         pr "    char s[len+1];\n";
10713         pr "    memcpy (s, r->%s, len);\n" name;
10714         pr "    s[len] = 0;\n";
10715         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10716         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10717         pr "  }\n";
10718     | name, (FBytes|FUInt64|FInt64) ->
10719         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10720         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10721     | name, (FUInt32|FInt32) ->
10722         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10723         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10724     | name, FOptPercent ->
10725         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10726         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10727     | name, FChar ->
10728         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10729         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10730   ) cols;
10731   pr "  free (r);\n";
10732   pr "  return jr;\n"
10733
10734 and generate_java_struct_list_return typ jtyp cols =
10735   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10736   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10737   pr "  for (i = 0; i < r->len; ++i) {\n";
10738   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10739   List.iter (
10740     function
10741     | name, FString ->
10742         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10743         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10744     | name, FUUID ->
10745         pr "    {\n";
10746         pr "      char s[33];\n";
10747         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10748         pr "      s[32] = 0;\n";
10749         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10750         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10751         pr "    }\n";
10752     | name, FBuffer ->
10753         pr "    {\n";
10754         pr "      int len = r->val[i].%s_len;\n" name;
10755         pr "      char s[len+1];\n";
10756         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10757         pr "      s[len] = 0;\n";
10758         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10759         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10760         pr "    }\n";
10761     | name, (FBytes|FUInt64|FInt64) ->
10762         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10763         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10764     | name, (FUInt32|FInt32) ->
10765         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10766         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10767     | name, FOptPercent ->
10768         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10769         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10770     | name, FChar ->
10771         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10772         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10773   ) cols;
10774   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10775   pr "  }\n";
10776   pr "  guestfs_free_%s_list (r);\n" typ;
10777   pr "  return jr;\n"
10778
10779 and generate_java_makefile_inc () =
10780   generate_header HashStyle GPLv2plus;
10781
10782   pr "java_built_sources = \\\n";
10783   List.iter (
10784     fun (typ, jtyp) ->
10785         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10786   ) java_structs;
10787   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10788
10789 and generate_haskell_hs () =
10790   generate_header HaskellStyle LGPLv2plus;
10791
10792   (* XXX We only know how to generate partial FFI for Haskell
10793    * at the moment.  Please help out!
10794    *)
10795   let can_generate style =
10796     match style with
10797     | RErr, _
10798     | RInt _, _
10799     | RInt64 _, _ -> true
10800     | RBool _, _
10801     | RConstString _, _
10802     | RConstOptString _, _
10803     | RString _, _
10804     | RStringList _, _
10805     | RStruct _, _
10806     | RStructList _, _
10807     | RHashtable _, _
10808     | RBufferOut _, _ -> false in
10809
10810   pr "\
10811 {-# INCLUDE <guestfs.h> #-}
10812 {-# LANGUAGE ForeignFunctionInterface #-}
10813
10814 module Guestfs (
10815   create";
10816
10817   (* List out the names of the actions we want to export. *)
10818   List.iter (
10819     fun (name, style, _, _, _, _, _) ->
10820       if can_generate style then pr ",\n  %s" name
10821   ) all_functions;
10822
10823   pr "
10824   ) where
10825
10826 -- Unfortunately some symbols duplicate ones already present
10827 -- in Prelude.  We don't know which, so we hard-code a list
10828 -- here.
10829 import Prelude hiding (truncate)
10830
10831 import Foreign
10832 import Foreign.C
10833 import Foreign.C.Types
10834 import IO
10835 import Control.Exception
10836 import Data.Typeable
10837
10838 data GuestfsS = GuestfsS            -- represents the opaque C struct
10839 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10840 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10841
10842 -- XXX define properly later XXX
10843 data PV = PV
10844 data VG = VG
10845 data LV = LV
10846 data IntBool = IntBool
10847 data Stat = Stat
10848 data StatVFS = StatVFS
10849 data Hashtable = Hashtable
10850
10851 foreign import ccall unsafe \"guestfs_create\" c_create
10852   :: IO GuestfsP
10853 foreign import ccall unsafe \"&guestfs_close\" c_close
10854   :: FunPtr (GuestfsP -> IO ())
10855 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10856   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10857
10858 create :: IO GuestfsH
10859 create = do
10860   p <- c_create
10861   c_set_error_handler p nullPtr nullPtr
10862   h <- newForeignPtr c_close p
10863   return h
10864
10865 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10866   :: GuestfsP -> IO CString
10867
10868 -- last_error :: GuestfsH -> IO (Maybe String)
10869 -- last_error h = do
10870 --   str <- withForeignPtr h (\\p -> c_last_error p)
10871 --   maybePeek peekCString str
10872
10873 last_error :: GuestfsH -> IO (String)
10874 last_error h = do
10875   str <- withForeignPtr h (\\p -> c_last_error p)
10876   if (str == nullPtr)
10877     then return \"no error\"
10878     else peekCString str
10879
10880 ";
10881
10882   (* Generate wrappers for each foreign function. *)
10883   List.iter (
10884     fun (name, style, _, _, _, _, _) ->
10885       if can_generate style then (
10886         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10887         pr "  :: ";
10888         generate_haskell_prototype ~handle:"GuestfsP" style;
10889         pr "\n";
10890         pr "\n";
10891         pr "%s :: " name;
10892         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10893         pr "\n";
10894         pr "%s %s = do\n" name
10895           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10896         pr "  r <- ";
10897         (* Convert pointer arguments using with* functions. *)
10898         List.iter (
10899           function
10900           | FileIn n
10901           | FileOut n
10902           | Pathname n | Device n | Dev_or_Path n | String n ->
10903               pr "withCString %s $ \\%s -> " n n
10904           | BufferIn n ->
10905               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10906           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10907           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10908           | Bool _ | Int _ | Int64 _ -> ()
10909         ) (snd style);
10910         (* Convert integer arguments. *)
10911         let args =
10912           List.map (
10913             function
10914             | Bool n -> sprintf "(fromBool %s)" n
10915             | Int n -> sprintf "(fromIntegral %s)" n
10916             | Int64 n -> sprintf "(fromIntegral %s)" n
10917             | FileIn n | FileOut n
10918             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10919             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10920           ) (snd style) in
10921         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10922           (String.concat " " ("p" :: args));
10923         (match fst style with
10924          | RErr | RInt _ | RInt64 _ | RBool _ ->
10925              pr "  if (r == -1)\n";
10926              pr "    then do\n";
10927              pr "      err <- last_error h\n";
10928              pr "      fail err\n";
10929          | RConstString _ | RConstOptString _ | RString _
10930          | RStringList _ | RStruct _
10931          | RStructList _ | RHashtable _ | RBufferOut _ ->
10932              pr "  if (r == nullPtr)\n";
10933              pr "    then do\n";
10934              pr "      err <- last_error h\n";
10935              pr "      fail err\n";
10936         );
10937         (match fst style with
10938          | RErr ->
10939              pr "    else return ()\n"
10940          | RInt _ ->
10941              pr "    else return (fromIntegral r)\n"
10942          | RInt64 _ ->
10943              pr "    else return (fromIntegral r)\n"
10944          | RBool _ ->
10945              pr "    else return (toBool r)\n"
10946          | RConstString _
10947          | RConstOptString _
10948          | RString _
10949          | RStringList _
10950          | RStruct _
10951          | RStructList _
10952          | RHashtable _
10953          | RBufferOut _ ->
10954              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10955         );
10956         pr "\n";
10957       )
10958   ) all_functions
10959
10960 and generate_haskell_prototype ~handle ?(hs = false) style =
10961   pr "%s -> " handle;
10962   let string = if hs then "String" else "CString" in
10963   let int = if hs then "Int" else "CInt" in
10964   let bool = if hs then "Bool" else "CInt" in
10965   let int64 = if hs then "Integer" else "Int64" in
10966   List.iter (
10967     fun arg ->
10968       (match arg with
10969        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10970        | BufferIn _ ->
10971            if hs then pr "String"
10972            else pr "CString -> CInt"
10973        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10974        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10975        | Bool _ -> pr "%s" bool
10976        | Int _ -> pr "%s" int
10977        | Int64 _ -> pr "%s" int
10978        | FileIn _ -> pr "%s" string
10979        | FileOut _ -> pr "%s" string
10980       );
10981       pr " -> ";
10982   ) (snd style);
10983   pr "IO (";
10984   (match fst style with
10985    | RErr -> if not hs then pr "CInt"
10986    | RInt _ -> pr "%s" int
10987    | RInt64 _ -> pr "%s" int64
10988    | RBool _ -> pr "%s" bool
10989    | RConstString _ -> pr "%s" string
10990    | RConstOptString _ -> pr "Maybe %s" string
10991    | RString _ -> pr "%s" string
10992    | RStringList _ -> pr "[%s]" string
10993    | RStruct (_, typ) ->
10994        let name = java_name_of_struct typ in
10995        pr "%s" name
10996    | RStructList (_, typ) ->
10997        let name = java_name_of_struct typ in
10998        pr "[%s]" name
10999    | RHashtable _ -> pr "Hashtable"
11000    | RBufferOut _ -> pr "%s" string
11001   );
11002   pr ")"
11003
11004 and generate_csharp () =
11005   generate_header CPlusPlusStyle LGPLv2plus;
11006
11007   (* XXX Make this configurable by the C# assembly users. *)
11008   let library = "libguestfs.so.0" in
11009
11010   pr "\
11011 // These C# bindings are highly experimental at present.
11012 //
11013 // Firstly they only work on Linux (ie. Mono).  In order to get them
11014 // to work on Windows (ie. .Net) you would need to port the library
11015 // itself to Windows first.
11016 //
11017 // The second issue is that some calls are known to be incorrect and
11018 // can cause Mono to segfault.  Particularly: calls which pass or
11019 // return string[], or return any structure value.  This is because
11020 // we haven't worked out the correct way to do this from C#.
11021 //
11022 // The third issue is that when compiling you get a lot of warnings.
11023 // We are not sure whether the warnings are important or not.
11024 //
11025 // Fourthly we do not routinely build or test these bindings as part
11026 // of the make && make check cycle, which means that regressions might
11027 // go unnoticed.
11028 //
11029 // Suggestions and patches are welcome.
11030
11031 // To compile:
11032 //
11033 // gmcs Libguestfs.cs
11034 // mono Libguestfs.exe
11035 //
11036 // (You'll probably want to add a Test class / static main function
11037 // otherwise this won't do anything useful).
11038
11039 using System;
11040 using System.IO;
11041 using System.Runtime.InteropServices;
11042 using System.Runtime.Serialization;
11043 using System.Collections;
11044
11045 namespace Guestfs
11046 {
11047   class Error : System.ApplicationException
11048   {
11049     public Error (string message) : base (message) {}
11050     protected Error (SerializationInfo info, StreamingContext context) {}
11051   }
11052
11053   class Guestfs
11054   {
11055     IntPtr _handle;
11056
11057     [DllImport (\"%s\")]
11058     static extern IntPtr guestfs_create ();
11059
11060     public Guestfs ()
11061     {
11062       _handle = guestfs_create ();
11063       if (_handle == IntPtr.Zero)
11064         throw new Error (\"could not create guestfs handle\");
11065     }
11066
11067     [DllImport (\"%s\")]
11068     static extern void guestfs_close (IntPtr h);
11069
11070     ~Guestfs ()
11071     {
11072       guestfs_close (_handle);
11073     }
11074
11075     [DllImport (\"%s\")]
11076     static extern string guestfs_last_error (IntPtr h);
11077
11078 " library library library;
11079
11080   (* Generate C# structure bindings.  We prefix struct names with
11081    * underscore because C# cannot have conflicting struct names and
11082    * method names (eg. "class stat" and "stat").
11083    *)
11084   List.iter (
11085     fun (typ, cols) ->
11086       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11087       pr "    public class _%s {\n" typ;
11088       List.iter (
11089         function
11090         | name, FChar -> pr "      char %s;\n" name
11091         | name, FString -> pr "      string %s;\n" name
11092         | name, FBuffer ->
11093             pr "      uint %s_len;\n" name;
11094             pr "      string %s;\n" name
11095         | name, FUUID ->
11096             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11097             pr "      string %s;\n" name
11098         | name, FUInt32 -> pr "      uint %s;\n" name
11099         | name, FInt32 -> pr "      int %s;\n" name
11100         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11101         | name, FInt64 -> pr "      long %s;\n" name
11102         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11103       ) cols;
11104       pr "    }\n";
11105       pr "\n"
11106   ) structs;
11107
11108   (* Generate C# function bindings. *)
11109   List.iter (
11110     fun (name, style, _, _, _, shortdesc, _) ->
11111       let rec csharp_return_type () =
11112         match fst style with
11113         | RErr -> "void"
11114         | RBool n -> "bool"
11115         | RInt n -> "int"
11116         | RInt64 n -> "long"
11117         | RConstString n
11118         | RConstOptString n
11119         | RString n
11120         | RBufferOut n -> "string"
11121         | RStruct (_,n) -> "_" ^ n
11122         | RHashtable n -> "Hashtable"
11123         | RStringList n -> "string[]"
11124         | RStructList (_,n) -> sprintf "_%s[]" n
11125
11126       and c_return_type () =
11127         match fst style with
11128         | RErr
11129         | RBool _
11130         | RInt _ -> "int"
11131         | RInt64 _ -> "long"
11132         | RConstString _
11133         | RConstOptString _
11134         | RString _
11135         | RBufferOut _ -> "string"
11136         | RStruct (_,n) -> "_" ^ n
11137         | RHashtable _
11138         | RStringList _ -> "string[]"
11139         | RStructList (_,n) -> sprintf "_%s[]" n
11140
11141       and c_error_comparison () =
11142         match fst style with
11143         | RErr
11144         | RBool _
11145         | RInt _
11146         | RInt64 _ -> "== -1"
11147         | RConstString _
11148         | RConstOptString _
11149         | RString _
11150         | RBufferOut _
11151         | RStruct (_,_)
11152         | RHashtable _
11153         | RStringList _
11154         | RStructList (_,_) -> "== null"
11155
11156       and generate_extern_prototype () =
11157         pr "    static extern %s guestfs_%s (IntPtr h"
11158           (c_return_type ()) name;
11159         List.iter (
11160           function
11161           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11162           | FileIn n | FileOut n
11163           | BufferIn n ->
11164               pr ", [In] string %s" n
11165           | StringList n | DeviceList n ->
11166               pr ", [In] string[] %s" n
11167           | Bool n ->
11168               pr ", bool %s" n
11169           | Int n ->
11170               pr ", int %s" n
11171           | Int64 n ->
11172               pr ", long %s" n
11173         ) (snd style);
11174         pr ");\n"
11175
11176       and generate_public_prototype () =
11177         pr "    public %s %s (" (csharp_return_type ()) name;
11178         let comma = ref false in
11179         let next () =
11180           if !comma then pr ", ";
11181           comma := true
11182         in
11183         List.iter (
11184           function
11185           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11186           | FileIn n | FileOut n
11187           | BufferIn n ->
11188               next (); pr "string %s" n
11189           | StringList n | DeviceList n ->
11190               next (); pr "string[] %s" n
11191           | Bool n ->
11192               next (); pr "bool %s" n
11193           | Int n ->
11194               next (); pr "int %s" n
11195           | Int64 n ->
11196               next (); pr "long %s" n
11197         ) (snd style);
11198         pr ")\n"
11199
11200       and generate_call () =
11201         pr "guestfs_%s (_handle" name;
11202         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11203         pr ");\n";
11204       in
11205
11206       pr "    [DllImport (\"%s\")]\n" library;
11207       generate_extern_prototype ();
11208       pr "\n";
11209       pr "    /// <summary>\n";
11210       pr "    /// %s\n" shortdesc;
11211       pr "    /// </summary>\n";
11212       generate_public_prototype ();
11213       pr "    {\n";
11214       pr "      %s r;\n" (c_return_type ());
11215       pr "      r = ";
11216       generate_call ();
11217       pr "      if (r %s)\n" (c_error_comparison ());
11218       pr "        throw new Error (guestfs_last_error (_handle));\n";
11219       (match fst style with
11220        | RErr -> ()
11221        | RBool _ ->
11222            pr "      return r != 0 ? true : false;\n"
11223        | RHashtable _ ->
11224            pr "      Hashtable rr = new Hashtable ();\n";
11225            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11226            pr "        rr.Add (r[i], r[i+1]);\n";
11227            pr "      return rr;\n"
11228        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11229        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11230        | RStructList _ ->
11231            pr "      return r;\n"
11232       );
11233       pr "    }\n";
11234       pr "\n";
11235   ) all_functions_sorted;
11236
11237   pr "  }
11238 }
11239 "
11240
11241 and generate_bindtests () =
11242   generate_header CStyle LGPLv2plus;
11243
11244   pr "\
11245 #include <stdio.h>
11246 #include <stdlib.h>
11247 #include <inttypes.h>
11248 #include <string.h>
11249
11250 #include \"guestfs.h\"
11251 #include \"guestfs-internal.h\"
11252 #include \"guestfs-internal-actions.h\"
11253 #include \"guestfs_protocol.h\"
11254
11255 #define error guestfs_error
11256 #define safe_calloc guestfs_safe_calloc
11257 #define safe_malloc guestfs_safe_malloc
11258
11259 static void
11260 print_strings (char *const *argv)
11261 {
11262   size_t argc;
11263
11264   printf (\"[\");
11265   for (argc = 0; argv[argc] != NULL; ++argc) {
11266     if (argc > 0) printf (\", \");
11267     printf (\"\\\"%%s\\\"\", argv[argc]);
11268   }
11269   printf (\"]\\n\");
11270 }
11271
11272 /* The test0 function prints its parameters to stdout. */
11273 ";
11274
11275   let test0, tests =
11276     match test_functions with
11277     | [] -> assert false
11278     | test0 :: tests -> test0, tests in
11279
11280   let () =
11281     let (name, style, _, _, _, _, _) = test0 in
11282     generate_prototype ~extern:false ~semicolon:false ~newline:true
11283       ~handle:"g" ~prefix:"guestfs__" name style;
11284     pr "{\n";
11285     List.iter (
11286       function
11287       | Pathname n
11288       | Device n | Dev_or_Path n
11289       | String n
11290       | FileIn n
11291       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11292       | BufferIn n ->
11293           pr "  {\n";
11294           pr "    size_t i;\n";
11295           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11296           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11297           pr "    printf (\"\\n\");\n";
11298           pr "  }\n";
11299       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11300       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11301       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11302       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11303       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11304     ) (snd style);
11305     pr "  /* Java changes stdout line buffering so we need this: */\n";
11306     pr "  fflush (stdout);\n";
11307     pr "  return 0;\n";
11308     pr "}\n";
11309     pr "\n" in
11310
11311   List.iter (
11312     fun (name, style, _, _, _, _, _) ->
11313       if String.sub name (String.length name - 3) 3 <> "err" then (
11314         pr "/* Test normal return. */\n";
11315         generate_prototype ~extern:false ~semicolon:false ~newline:true
11316           ~handle:"g" ~prefix:"guestfs__" name style;
11317         pr "{\n";
11318         (match fst style with
11319          | RErr ->
11320              pr "  return 0;\n"
11321          | RInt _ ->
11322              pr "  int r;\n";
11323              pr "  sscanf (val, \"%%d\", &r);\n";
11324              pr "  return r;\n"
11325          | RInt64 _ ->
11326              pr "  int64_t r;\n";
11327              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11328              pr "  return r;\n"
11329          | RBool _ ->
11330              pr "  return STREQ (val, \"true\");\n"
11331          | RConstString _
11332          | RConstOptString _ ->
11333              (* Can't return the input string here.  Return a static
11334               * string so we ensure we get a segfault if the caller
11335               * tries to free it.
11336               *)
11337              pr "  return \"static string\";\n"
11338          | RString _ ->
11339              pr "  return strdup (val);\n"
11340          | RStringList _ ->
11341              pr "  char **strs;\n";
11342              pr "  int n, i;\n";
11343              pr "  sscanf (val, \"%%d\", &n);\n";
11344              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11345              pr "  for (i = 0; i < n; ++i) {\n";
11346              pr "    strs[i] = safe_malloc (g, 16);\n";
11347              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11348              pr "  }\n";
11349              pr "  strs[n] = NULL;\n";
11350              pr "  return strs;\n"
11351          | RStruct (_, typ) ->
11352              pr "  struct guestfs_%s *r;\n" typ;
11353              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11354              pr "  return r;\n"
11355          | RStructList (_, typ) ->
11356              pr "  struct guestfs_%s_list *r;\n" typ;
11357              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11358              pr "  sscanf (val, \"%%d\", &r->len);\n";
11359              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11360              pr "  return r;\n"
11361          | RHashtable _ ->
11362              pr "  char **strs;\n";
11363              pr "  int n, i;\n";
11364              pr "  sscanf (val, \"%%d\", &n);\n";
11365              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11366              pr "  for (i = 0; i < n; ++i) {\n";
11367              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11368              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11369              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11370              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11371              pr "  }\n";
11372              pr "  strs[n*2] = NULL;\n";
11373              pr "  return strs;\n"
11374          | RBufferOut _ ->
11375              pr "  return strdup (val);\n"
11376         );
11377         pr "}\n";
11378         pr "\n"
11379       ) else (
11380         pr "/* Test error return. */\n";
11381         generate_prototype ~extern:false ~semicolon:false ~newline:true
11382           ~handle:"g" ~prefix:"guestfs__" name style;
11383         pr "{\n";
11384         pr "  error (g, \"error\");\n";
11385         (match fst style with
11386          | RErr | RInt _ | RInt64 _ | RBool _ ->
11387              pr "  return -1;\n"
11388          | RConstString _ | RConstOptString _
11389          | RString _ | RStringList _ | RStruct _
11390          | RStructList _
11391          | RHashtable _
11392          | RBufferOut _ ->
11393              pr "  return NULL;\n"
11394         );
11395         pr "}\n";
11396         pr "\n"
11397       )
11398   ) tests
11399
11400 and generate_ocaml_bindtests () =
11401   generate_header OCamlStyle GPLv2plus;
11402
11403   pr "\
11404 let () =
11405   let g = Guestfs.create () in
11406 ";
11407
11408   let mkargs args =
11409     String.concat " " (
11410       List.map (
11411         function
11412         | CallString s -> "\"" ^ s ^ "\""
11413         | CallOptString None -> "None"
11414         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11415         | CallStringList xs ->
11416             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11417         | CallInt i when i >= 0 -> string_of_int i
11418         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11419         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11420         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11421         | CallBool b -> string_of_bool b
11422         | CallBuffer s -> sprintf "%S" s
11423       ) args
11424     )
11425   in
11426
11427   generate_lang_bindtests (
11428     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11429   );
11430
11431   pr "print_endline \"EOF\"\n"
11432
11433 and generate_perl_bindtests () =
11434   pr "#!/usr/bin/perl -w\n";
11435   generate_header HashStyle GPLv2plus;
11436
11437   pr "\
11438 use strict;
11439
11440 use Sys::Guestfs;
11441
11442 my $g = Sys::Guestfs->new ();
11443 ";
11444
11445   let mkargs args =
11446     String.concat ", " (
11447       List.map (
11448         function
11449         | CallString s -> "\"" ^ s ^ "\""
11450         | CallOptString None -> "undef"
11451         | CallOptString (Some s) -> sprintf "\"%s\"" s
11452         | CallStringList xs ->
11453             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11454         | CallInt i -> string_of_int i
11455         | CallInt64 i -> Int64.to_string i
11456         | CallBool b -> if b then "1" else "0"
11457         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11458       ) args
11459     )
11460   in
11461
11462   generate_lang_bindtests (
11463     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11464   );
11465
11466   pr "print \"EOF\\n\"\n"
11467
11468 and generate_python_bindtests () =
11469   generate_header HashStyle GPLv2plus;
11470
11471   pr "\
11472 import guestfs
11473
11474 g = guestfs.GuestFS ()
11475 ";
11476
11477   let mkargs args =
11478     String.concat ", " (
11479       List.map (
11480         function
11481         | CallString s -> "\"" ^ s ^ "\""
11482         | CallOptString None -> "None"
11483         | CallOptString (Some s) -> sprintf "\"%s\"" s
11484         | CallStringList xs ->
11485             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11486         | CallInt i -> string_of_int i
11487         | CallInt64 i -> Int64.to_string i
11488         | CallBool b -> if b then "1" else "0"
11489         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11490       ) args
11491     )
11492   in
11493
11494   generate_lang_bindtests (
11495     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11496   );
11497
11498   pr "print \"EOF\"\n"
11499
11500 and generate_ruby_bindtests () =
11501   generate_header HashStyle GPLv2plus;
11502
11503   pr "\
11504 require 'guestfs'
11505
11506 g = Guestfs::create()
11507 ";
11508
11509   let mkargs args =
11510     String.concat ", " (
11511       List.map (
11512         function
11513         | CallString s -> "\"" ^ s ^ "\""
11514         | CallOptString None -> "nil"
11515         | CallOptString (Some s) -> sprintf "\"%s\"" s
11516         | CallStringList xs ->
11517             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11518         | CallInt i -> string_of_int i
11519         | CallInt64 i -> Int64.to_string i
11520         | CallBool b -> string_of_bool b
11521         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11522       ) args
11523     )
11524   in
11525
11526   generate_lang_bindtests (
11527     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11528   );
11529
11530   pr "print \"EOF\\n\"\n"
11531
11532 and generate_java_bindtests () =
11533   generate_header CStyle GPLv2plus;
11534
11535   pr "\
11536 import com.redhat.et.libguestfs.*;
11537
11538 public class Bindtests {
11539     public static void main (String[] argv)
11540     {
11541         try {
11542             GuestFS g = new GuestFS ();
11543 ";
11544
11545   let mkargs args =
11546     String.concat ", " (
11547       List.map (
11548         function
11549         | CallString s -> "\"" ^ s ^ "\""
11550         | CallOptString None -> "null"
11551         | CallOptString (Some s) -> sprintf "\"%s\"" s
11552         | CallStringList xs ->
11553             "new String[]{" ^
11554               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11555         | CallInt i -> string_of_int i
11556         | CallInt64 i -> Int64.to_string i
11557         | CallBool b -> string_of_bool b
11558         | CallBuffer s ->
11559             "new byte[] { " ^ String.concat "," (
11560               map_chars (fun c -> string_of_int (Char.code c)) s
11561             ) ^ " }"
11562       ) args
11563     )
11564   in
11565
11566   generate_lang_bindtests (
11567     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11568   );
11569
11570   pr "
11571             System.out.println (\"EOF\");
11572         }
11573         catch (Exception exn) {
11574             System.err.println (exn);
11575             System.exit (1);
11576         }
11577     }
11578 }
11579 "
11580
11581 and generate_haskell_bindtests () =
11582   generate_header HaskellStyle GPLv2plus;
11583
11584   pr "\
11585 module Bindtests where
11586 import qualified Guestfs
11587
11588 main = do
11589   g <- Guestfs.create
11590 ";
11591
11592   let mkargs args =
11593     String.concat " " (
11594       List.map (
11595         function
11596         | CallString s -> "\"" ^ s ^ "\""
11597         | CallOptString None -> "Nothing"
11598         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11599         | CallStringList xs ->
11600             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11601         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11602         | CallInt i -> string_of_int i
11603         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11604         | CallInt64 i -> Int64.to_string i
11605         | CallBool true -> "True"
11606         | CallBool false -> "False"
11607         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11608       ) args
11609     )
11610   in
11611
11612   generate_lang_bindtests (
11613     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11614   );
11615
11616   pr "  putStrLn \"EOF\"\n"
11617
11618 (* Language-independent bindings tests - we do it this way to
11619  * ensure there is parity in testing bindings across all languages.
11620  *)
11621 and generate_lang_bindtests call =
11622   call "test0" [CallString "abc"; CallOptString (Some "def");
11623                 CallStringList []; CallBool false;
11624                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11625                 CallBuffer "abc\000abc"];
11626   call "test0" [CallString "abc"; CallOptString None;
11627                 CallStringList []; CallBool false;
11628                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11629                 CallBuffer "abc\000abc"];
11630   call "test0" [CallString ""; CallOptString (Some "def");
11631                 CallStringList []; CallBool false;
11632                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11633                 CallBuffer "abc\000abc"];
11634   call "test0" [CallString ""; CallOptString (Some "");
11635                 CallStringList []; CallBool false;
11636                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11637                 CallBuffer "abc\000abc"];
11638   call "test0" [CallString "abc"; CallOptString (Some "def");
11639                 CallStringList ["1"]; CallBool false;
11640                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11641                 CallBuffer "abc\000abc"];
11642   call "test0" [CallString "abc"; CallOptString (Some "def");
11643                 CallStringList ["1"; "2"]; CallBool false;
11644                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11645                 CallBuffer "abc\000abc"];
11646   call "test0" [CallString "abc"; CallOptString (Some "def");
11647                 CallStringList ["1"]; CallBool true;
11648                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11649                 CallBuffer "abc\000abc"];
11650   call "test0" [CallString "abc"; CallOptString (Some "def");
11651                 CallStringList ["1"]; CallBool false;
11652                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11653                 CallBuffer "abc\000abc"];
11654   call "test0" [CallString "abc"; CallOptString (Some "def");
11655                 CallStringList ["1"]; CallBool false;
11656                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11657                 CallBuffer "abc\000abc"];
11658   call "test0" [CallString "abc"; CallOptString (Some "def");
11659                 CallStringList ["1"]; CallBool false;
11660                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11661                 CallBuffer "abc\000abc"];
11662   call "test0" [CallString "abc"; CallOptString (Some "def");
11663                 CallStringList ["1"]; CallBool false;
11664                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11665                 CallBuffer "abc\000abc"];
11666   call "test0" [CallString "abc"; CallOptString (Some "def");
11667                 CallStringList ["1"]; CallBool false;
11668                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11669                 CallBuffer "abc\000abc"];
11670   call "test0" [CallString "abc"; CallOptString (Some "def");
11671                 CallStringList ["1"]; CallBool false;
11672                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11673                 CallBuffer "abc\000abc"]
11674
11675 (* XXX Add here tests of the return and error functions. *)
11676
11677 (* Code to generator bindings for virt-inspector.  Currently only
11678  * implemented for OCaml code (for virt-p2v 2.0).
11679  *)
11680 let rng_input = "inspector/virt-inspector.rng"
11681
11682 (* Read the input file and parse it into internal structures.  This is
11683  * by no means a complete RELAX NG parser, but is just enough to be
11684  * able to parse the specific input file.
11685  *)
11686 type rng =
11687   | Element of string * rng list        (* <element name=name/> *)
11688   | Attribute of string * rng list        (* <attribute name=name/> *)
11689   | Interleave of rng list                (* <interleave/> *)
11690   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11691   | OneOrMore of rng                        (* <oneOrMore/> *)
11692   | Optional of rng                        (* <optional/> *)
11693   | Choice of string list                (* <choice><value/>*</choice> *)
11694   | Value of string                        (* <value>str</value> *)
11695   | Text                                (* <text/> *)
11696
11697 let rec string_of_rng = function
11698   | Element (name, xs) ->
11699       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11700   | Attribute (name, xs) ->
11701       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11702   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11703   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11704   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11705   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11706   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11707   | Value value -> "Value \"" ^ value ^ "\""
11708   | Text -> "Text"
11709
11710 and string_of_rng_list xs =
11711   String.concat ", " (List.map string_of_rng xs)
11712
11713 let rec parse_rng ?defines context = function
11714   | [] -> []
11715   | Xml.Element ("element", ["name", name], children) :: rest ->
11716       Element (name, parse_rng ?defines context children)
11717       :: parse_rng ?defines context rest
11718   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11719       Attribute (name, parse_rng ?defines context children)
11720       :: parse_rng ?defines context rest
11721   | Xml.Element ("interleave", [], children) :: rest ->
11722       Interleave (parse_rng ?defines context children)
11723       :: parse_rng ?defines context rest
11724   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11725       let rng = parse_rng ?defines context [child] in
11726       (match rng with
11727        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11728        | _ ->
11729            failwithf "%s: <zeroOrMore> contains more than one child element"
11730              context
11731       )
11732   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11733       let rng = parse_rng ?defines context [child] in
11734       (match rng with
11735        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11736        | _ ->
11737            failwithf "%s: <oneOrMore> contains more than one child element"
11738              context
11739       )
11740   | Xml.Element ("optional", [], [child]) :: rest ->
11741       let rng = parse_rng ?defines context [child] in
11742       (match rng with
11743        | [child] -> Optional child :: parse_rng ?defines context rest
11744        | _ ->
11745            failwithf "%s: <optional> contains more than one child element"
11746              context
11747       )
11748   | Xml.Element ("choice", [], children) :: rest ->
11749       let values = List.map (
11750         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11751         | _ ->
11752             failwithf "%s: can't handle anything except <value> in <choice>"
11753               context
11754       ) children in
11755       Choice values
11756       :: parse_rng ?defines context rest
11757   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11758       Value value :: parse_rng ?defines context rest
11759   | Xml.Element ("text", [], []) :: rest ->
11760       Text :: parse_rng ?defines context rest
11761   | Xml.Element ("ref", ["name", name], []) :: rest ->
11762       (* Look up the reference.  Because of limitations in this parser,
11763        * we can't handle arbitrarily nested <ref> yet.  You can only
11764        * use <ref> from inside <start>.
11765        *)
11766       (match defines with
11767        | None ->
11768            failwithf "%s: contains <ref>, but no refs are defined yet" context
11769        | Some map ->
11770            let rng = StringMap.find name map in
11771            rng @ parse_rng ?defines context rest
11772       )
11773   | x :: _ ->
11774       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11775
11776 let grammar =
11777   let xml = Xml.parse_file rng_input in
11778   match xml with
11779   | Xml.Element ("grammar", _,
11780                  Xml.Element ("start", _, gram) :: defines) ->
11781       (* The <define/> elements are referenced in the <start> section,
11782        * so build a map of those first.
11783        *)
11784       let defines = List.fold_left (
11785         fun map ->
11786           function Xml.Element ("define", ["name", name], defn) ->
11787             StringMap.add name defn map
11788           | _ ->
11789               failwithf "%s: expected <define name=name/>" rng_input
11790       ) StringMap.empty defines in
11791       let defines = StringMap.mapi parse_rng defines in
11792
11793       (* Parse the <start> clause, passing the defines. *)
11794       parse_rng ~defines "<start>" gram
11795   | _ ->
11796       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11797         rng_input
11798
11799 let name_of_field = function
11800   | Element (name, _) | Attribute (name, _)
11801   | ZeroOrMore (Element (name, _))
11802   | OneOrMore (Element (name, _))
11803   | Optional (Element (name, _)) -> name
11804   | Optional (Attribute (name, _)) -> name
11805   | Text -> (* an unnamed field in an element *)
11806       "data"
11807   | rng ->
11808       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11809
11810 (* At the moment this function only generates OCaml types.  However we
11811  * should parameterize it later so it can generate types/structs in a
11812  * variety of languages.
11813  *)
11814 let generate_types xs =
11815   (* A simple type is one that can be printed out directly, eg.
11816    * "string option".  A complex type is one which has a name and has
11817    * to be defined via another toplevel definition, eg. a struct.
11818    *
11819    * generate_type generates code for either simple or complex types.
11820    * In the simple case, it returns the string ("string option").  In
11821    * the complex case, it returns the name ("mountpoint").  In the
11822    * complex case it has to print out the definition before returning,
11823    * so it should only be called when we are at the beginning of a
11824    * new line (BOL context).
11825    *)
11826   let rec generate_type = function
11827     | Text ->                                (* string *)
11828         "string", true
11829     | Choice values ->                        (* [`val1|`val2|...] *)
11830         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11831     | ZeroOrMore rng ->                        (* <rng> list *)
11832         let t, is_simple = generate_type rng in
11833         t ^ " list (* 0 or more *)", is_simple
11834     | OneOrMore rng ->                        (* <rng> list *)
11835         let t, is_simple = generate_type rng in
11836         t ^ " list (* 1 or more *)", is_simple
11837                                         (* virt-inspector hack: bool *)
11838     | Optional (Attribute (name, [Value "1"])) ->
11839         "bool", true
11840     | Optional rng ->                        (* <rng> list *)
11841         let t, is_simple = generate_type rng in
11842         t ^ " option", is_simple
11843                                         (* type name = { fields ... } *)
11844     | Element (name, fields) when is_attrs_interleave fields ->
11845         generate_type_struct name (get_attrs_interleave fields)
11846     | Element (name, [field])                (* type name = field *)
11847     | Attribute (name, [field]) ->
11848         let t, is_simple = generate_type field in
11849         if is_simple then (t, true)
11850         else (
11851           pr "type %s = %s\n" name t;
11852           name, false
11853         )
11854     | Element (name, fields) ->              (* type name = { fields ... } *)
11855         generate_type_struct name fields
11856     | rng ->
11857         failwithf "generate_type failed at: %s" (string_of_rng rng)
11858
11859   and is_attrs_interleave = function
11860     | [Interleave _] -> true
11861     | Attribute _ :: fields -> is_attrs_interleave fields
11862     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11863     | _ -> false
11864
11865   and get_attrs_interleave = function
11866     | [Interleave fields] -> fields
11867     | ((Attribute _) as field) :: fields
11868     | ((Optional (Attribute _)) as field) :: fields ->
11869         field :: get_attrs_interleave fields
11870     | _ -> assert false
11871
11872   and generate_types xs =
11873     List.iter (fun x -> ignore (generate_type x)) xs
11874
11875   and generate_type_struct name fields =
11876     (* Calculate the types of the fields first.  We have to do this
11877      * before printing anything so we are still in BOL context.
11878      *)
11879     let types = List.map fst (List.map generate_type fields) in
11880
11881     (* Special case of a struct containing just a string and another
11882      * field.  Turn it into an assoc list.
11883      *)
11884     match types with
11885     | ["string"; other] ->
11886         let fname1, fname2 =
11887           match fields with
11888           | [f1; f2] -> name_of_field f1, name_of_field f2
11889           | _ -> assert false in
11890         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11891         name, false
11892
11893     | types ->
11894         pr "type %s = {\n" name;
11895         List.iter (
11896           fun (field, ftype) ->
11897             let fname = name_of_field field in
11898             pr "  %s_%s : %s;\n" name fname ftype
11899         ) (List.combine fields types);
11900         pr "}\n";
11901         (* Return the name of this type, and
11902          * false because it's not a simple type.
11903          *)
11904         name, false
11905   in
11906
11907   generate_types xs
11908
11909 let generate_parsers xs =
11910   (* As for generate_type above, generate_parser makes a parser for
11911    * some type, and returns the name of the parser it has generated.
11912    * Because it (may) need to print something, it should always be
11913    * called in BOL context.
11914    *)
11915   let rec generate_parser = function
11916     | Text ->                                (* string *)
11917         "string_child_or_empty"
11918     | Choice values ->                        (* [`val1|`val2|...] *)
11919         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11920           (String.concat "|"
11921              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11922     | ZeroOrMore rng ->                        (* <rng> list *)
11923         let pa = generate_parser rng in
11924         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11925     | OneOrMore rng ->                        (* <rng> list *)
11926         let pa = generate_parser rng in
11927         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11928                                         (* virt-inspector hack: bool *)
11929     | Optional (Attribute (name, [Value "1"])) ->
11930         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11931     | Optional rng ->                        (* <rng> list *)
11932         let pa = generate_parser rng in
11933         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11934                                         (* type name = { fields ... } *)
11935     | Element (name, fields) when is_attrs_interleave fields ->
11936         generate_parser_struct name (get_attrs_interleave fields)
11937     | Element (name, [field]) ->        (* type name = field *)
11938         let pa = generate_parser field in
11939         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11940         pr "let %s =\n" parser_name;
11941         pr "  %s\n" pa;
11942         pr "let parse_%s = %s\n" name parser_name;
11943         parser_name
11944     | Attribute (name, [field]) ->
11945         let pa = generate_parser field in
11946         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11947         pr "let %s =\n" parser_name;
11948         pr "  %s\n" pa;
11949         pr "let parse_%s = %s\n" name parser_name;
11950         parser_name
11951     | Element (name, fields) ->              (* type name = { fields ... } *)
11952         generate_parser_struct name ([], fields)
11953     | rng ->
11954         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11955
11956   and is_attrs_interleave = function
11957     | [Interleave _] -> true
11958     | Attribute _ :: fields -> is_attrs_interleave fields
11959     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11960     | _ -> false
11961
11962   and get_attrs_interleave = function
11963     | [Interleave fields] -> [], fields
11964     | ((Attribute _) as field) :: fields
11965     | ((Optional (Attribute _)) as field) :: fields ->
11966         let attrs, interleaves = get_attrs_interleave fields in
11967         (field :: attrs), interleaves
11968     | _ -> assert false
11969
11970   and generate_parsers xs =
11971     List.iter (fun x -> ignore (generate_parser x)) xs
11972
11973   and generate_parser_struct name (attrs, interleaves) =
11974     (* Generate parsers for the fields first.  We have to do this
11975      * before printing anything so we are still in BOL context.
11976      *)
11977     let fields = attrs @ interleaves in
11978     let pas = List.map generate_parser fields in
11979
11980     (* Generate an intermediate tuple from all the fields first.
11981      * If the type is just a string + another field, then we will
11982      * return this directly, otherwise it is turned into a record.
11983      *
11984      * RELAX NG note: This code treats <interleave> and plain lists of
11985      * fields the same.  In other words, it doesn't bother enforcing
11986      * any ordering of fields in the XML.
11987      *)
11988     pr "let parse_%s x =\n" name;
11989     pr "  let t = (\n    ";
11990     let comma = ref false in
11991     List.iter (
11992       fun x ->
11993         if !comma then pr ",\n    ";
11994         comma := true;
11995         match x with
11996         | Optional (Attribute (fname, [field])), pa ->
11997             pr "%s x" pa
11998         | Optional (Element (fname, [field])), pa ->
11999             pr "%s (optional_child %S x)" pa fname
12000         | Attribute (fname, [Text]), _ ->
12001             pr "attribute %S x" fname
12002         | (ZeroOrMore _ | OneOrMore _), pa ->
12003             pr "%s x" pa
12004         | Text, pa ->
12005             pr "%s x" pa
12006         | (field, pa) ->
12007             let fname = name_of_field field in
12008             pr "%s (child %S x)" pa fname
12009     ) (List.combine fields pas);
12010     pr "\n  ) in\n";
12011
12012     (match fields with
12013      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12014          pr "  t\n"
12015
12016      | _ ->
12017          pr "  (Obj.magic t : %s)\n" name
12018 (*
12019          List.iter (
12020            function
12021            | (Optional (Attribute (fname, [field])), pa) ->
12022                pr "  %s_%s =\n" name fname;
12023                pr "    %s x;\n" pa
12024            | (Optional (Element (fname, [field])), pa) ->
12025                pr "  %s_%s =\n" name fname;
12026                pr "    (let x = optional_child %S x in\n" fname;
12027                pr "     %s x);\n" pa
12028            | (field, pa) ->
12029                let fname = name_of_field field in
12030                pr "  %s_%s =\n" name fname;
12031                pr "    (let x = child %S x in\n" fname;
12032                pr "     %s x);\n" pa
12033          ) (List.combine fields pas);
12034          pr "}\n"
12035 *)
12036     );
12037     sprintf "parse_%s" name
12038   in
12039
12040   generate_parsers xs
12041
12042 (* Generate ocaml/guestfs_inspector.mli. *)
12043 let generate_ocaml_inspector_mli () =
12044   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12045
12046   pr "\
12047 (** This is an OCaml language binding to the external [virt-inspector]
12048     program.
12049
12050     For more information, please read the man page [virt-inspector(1)].
12051 *)
12052
12053 ";
12054
12055   generate_types grammar;
12056   pr "(** The nested information returned from the {!inspect} function. *)\n";
12057   pr "\n";
12058
12059   pr "\
12060 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12061 (** To inspect a libvirt domain called [name], pass a singleton
12062     list: [inspect [name]].  When using libvirt only, you may
12063     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12064
12065     To inspect a disk image or images, pass a list of the filenames
12066     of the disk images: [inspect filenames]
12067
12068     This function inspects the given guest or disk images and
12069     returns a list of operating system(s) found and a large amount
12070     of information about them.  In the vast majority of cases,
12071     a virtual machine only contains a single operating system.
12072
12073     If the optional [~xml] parameter is given, then this function
12074     skips running the external virt-inspector program and just
12075     parses the given XML directly (which is expected to be XML
12076     produced from a previous run of virt-inspector).  The list of
12077     names and connect URI are ignored in this case.
12078
12079     This function can throw a wide variety of exceptions, for example
12080     if the external virt-inspector program cannot be found, or if
12081     it doesn't generate valid XML.
12082 *)
12083 "
12084
12085 (* Generate ocaml/guestfs_inspector.ml. *)
12086 let generate_ocaml_inspector_ml () =
12087   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12088
12089   pr "open Unix\n";
12090   pr "\n";
12091
12092   generate_types grammar;
12093   pr "\n";
12094
12095   pr "\
12096 (* Misc functions which are used by the parser code below. *)
12097 let first_child = function
12098   | Xml.Element (_, _, c::_) -> c
12099   | Xml.Element (name, _, []) ->
12100       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12101   | Xml.PCData str ->
12102       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12103
12104 let string_child_or_empty = function
12105   | Xml.Element (_, _, [Xml.PCData s]) -> s
12106   | Xml.Element (_, _, []) -> \"\"
12107   | Xml.Element (x, _, _) ->
12108       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12109                 x ^ \" instead\")
12110   | Xml.PCData str ->
12111       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12112
12113 let optional_child name xml =
12114   let children = Xml.children xml in
12115   try
12116     Some (List.find (function
12117                      | Xml.Element (n, _, _) when n = name -> true
12118                      | _ -> false) children)
12119   with
12120     Not_found -> None
12121
12122 let child name xml =
12123   match optional_child name xml with
12124   | Some c -> c
12125   | None ->
12126       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12127
12128 let attribute name xml =
12129   try Xml.attrib xml name
12130   with Xml.No_attribute _ ->
12131     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12132
12133 ";
12134
12135   generate_parsers grammar;
12136   pr "\n";
12137
12138   pr "\
12139 (* Run external virt-inspector, then use parser to parse the XML. *)
12140 let inspect ?connect ?xml names =
12141   let xml =
12142     match xml with
12143     | None ->
12144         if names = [] then invalid_arg \"inspect: no names given\";
12145         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12146           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12147           names in
12148         let cmd = List.map Filename.quote cmd in
12149         let cmd = String.concat \" \" cmd in
12150         let chan = open_process_in cmd in
12151         let xml = Xml.parse_in chan in
12152         (match close_process_in chan with
12153          | WEXITED 0 -> ()
12154          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12155          | WSIGNALED i | WSTOPPED i ->
12156              failwith (\"external virt-inspector command died or stopped on sig \" ^
12157                        string_of_int i)
12158         );
12159         xml
12160     | Some doc ->
12161         Xml.parse_string doc in
12162   parse_operatingsystems xml
12163 "
12164
12165 and generate_max_proc_nr () =
12166   pr "%d\n" max_proc_nr
12167
12168 let output_to filename k =
12169   let filename_new = filename ^ ".new" in
12170   chan := open_out filename_new;
12171   k ();
12172   close_out !chan;
12173   chan := Pervasives.stdout;
12174
12175   (* Is the new file different from the current file? *)
12176   if Sys.file_exists filename && files_equal filename filename_new then
12177     unlink filename_new                 (* same, so skip it *)
12178   else (
12179     (* different, overwrite old one *)
12180     (try chmod filename 0o644 with Unix_error _ -> ());
12181     rename filename_new filename;
12182     chmod filename 0o444;
12183     printf "written %s\n%!" filename;
12184   )
12185
12186 let perror msg = function
12187   | Unix_error (err, _, _) ->
12188       eprintf "%s: %s\n" msg (error_message err)
12189   | exn ->
12190       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12191
12192 (* Main program. *)
12193 let () =
12194   let lock_fd =
12195     try openfile "HACKING" [O_RDWR] 0
12196     with
12197     | Unix_error (ENOENT, _, _) ->
12198         eprintf "\
12199 You are probably running this from the wrong directory.
12200 Run it from the top source directory using the command
12201   src/generator.ml
12202 ";
12203         exit 1
12204     | exn ->
12205         perror "open: HACKING" exn;
12206         exit 1 in
12207
12208   (* Acquire a lock so parallel builds won't try to run the generator
12209    * twice at the same time.  Subsequent builds will wait for the first
12210    * one to finish.  Note the lock is released implicitly when the
12211    * program exits.
12212    *)
12213   (try lockf lock_fd F_LOCK 1
12214    with exn ->
12215      perror "lock: HACKING" exn;
12216      exit 1);
12217
12218   check_functions ();
12219
12220   output_to "src/guestfs_protocol.x" generate_xdr;
12221   output_to "src/guestfs-structs.h" generate_structs_h;
12222   output_to "src/guestfs-actions.h" generate_actions_h;
12223   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12224   output_to "src/actions.c" generate_client_actions;
12225   output_to "src/bindtests.c" generate_bindtests;
12226   output_to "src/guestfs-structs.pod" generate_structs_pod;
12227   output_to "src/guestfs-actions.pod" generate_actions_pod;
12228   output_to "src/guestfs-availability.pod" generate_availability_pod;
12229   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12230   output_to "src/libguestfs.syms" generate_linker_script;
12231   output_to "daemon/actions.h" generate_daemon_actions_h;
12232   output_to "daemon/stubs.c" generate_daemon_actions;
12233   output_to "daemon/names.c" generate_daemon_names;
12234   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12235   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12236   output_to "capitests/tests.c" generate_tests;
12237   output_to "fish/cmds.c" generate_fish_cmds;
12238   output_to "fish/completion.c" generate_fish_completion;
12239   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12240   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12241   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12242   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12243   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12244   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12245   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12246   output_to "perl/Guestfs.xs" generate_perl_xs;
12247   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12248   output_to "perl/bindtests.pl" generate_perl_bindtests;
12249   output_to "python/guestfs-py.c" generate_python_c;
12250   output_to "python/guestfs.py" generate_python_py;
12251   output_to "python/bindtests.py" generate_python_bindtests;
12252   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12253   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12254   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12255
12256   List.iter (
12257     fun (typ, jtyp) ->
12258       let cols = cols_of_struct typ in
12259       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12260       output_to filename (generate_java_struct jtyp cols);
12261   ) java_structs;
12262
12263   output_to "java/Makefile.inc" generate_java_makefile_inc;
12264   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12265   output_to "java/Bindtests.java" generate_java_bindtests;
12266   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12267   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12268   output_to "csharp/Libguestfs.cs" generate_csharp;
12269
12270   (* Always generate this file last, and unconditionally.  It's used
12271    * by the Makefile to know when we must re-run the generator.
12272    *)
12273   let chan = open_out "src/stamp-generator" in
12274   fprintf chan "1\n";
12275   close_out chan;
12276
12277   printf "generated %d lines of code\n" !lines