14cf462afcc2a144922925e9fca69adf08306f2a
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless 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 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then 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 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
963
964   ("sync", (RErr, []), 2, [],
965    [ InitEmpty, Always, TestRun [["sync"]]],
966    "sync disks, writes are flushed through to the disk image",
967    "\
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
970
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
973
974   ("touch", (RErr, [Pathname "path"]), 3, [],
975    [InitBasicFS, Always, TestOutputTrue (
976       [["touch"; "/new"];
977        ["exists"; "/new"]])],
978    "update file timestamps or create a new file",
979    "\
980 Touch acts like the L<touch(1)> command.  It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
983
984   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985    [InitISOFS, Always, TestOutput (
986       [["cat"; "/known-2"]], "abcdef\n")],
987    "list the contents of a file",
988    "\
989 Return the contents of the file named C<path>.
990
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string).  For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
995
996   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997    [], (* XXX Tricky to test because it depends on the exact format
998         * of the 'ls -l' command, which changes between F10 and F11.
999         *)
1000    "list the files in a directory (long format)",
1001    "\
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1004
1005 This command is mostly useful for interactive sessions.  It
1006 is I<not> intended that you try to parse the output string.");
1007
1008   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009    [InitBasicFS, Always, TestOutputList (
1010       [["touch"; "/new"];
1011        ["touch"; "/newer"];
1012        ["touch"; "/newest"];
1013        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014    "list the files in a directory",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd).  The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1019
1020 This command is mostly useful for interactive sessions.  Programs
1021 should probably use C<guestfs_readdir> instead.");
1022
1023   ("list_devices", (RStringList "devices", []), 7, [],
1024    [InitEmpty, Always, TestOutputListOfDevices (
1025       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026    "list the block devices",
1027    "\
1028 List all the block devices.
1029
1030 The full block device names are returned, eg. C</dev/sda>");
1031
1032   ("list_partitions", (RStringList "partitions", []), 8, [],
1033    [InitBasicFS, Always, TestOutputListOfDevices (
1034       [["list_partitions"]], ["/dev/sda1"]);
1035     InitEmpty, Always, TestOutputListOfDevices (
1036       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038    "list the partitions",
1039    "\
1040 List all the partitions detected on all block devices.
1041
1042 The full partition device names are returned, eg. C</dev/sda1>
1043
1044 This does not return logical volumes.  For that you will need to
1045 call C<guestfs_lvs>.");
1046
1047   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049       [["pvs"]], ["/dev/sda1"]);
1050     InitEmpty, Always, TestOutputListOfDevices (
1051       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052        ["pvcreate"; "/dev/sda1"];
1053        ["pvcreate"; "/dev/sda2"];
1054        ["pvcreate"; "/dev/sda3"];
1055        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.
1060
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1063
1064 See also C<guestfs_pvs_full>.");
1065
1066   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067    [InitBasicFSonLVM, Always, TestOutputList (
1068       [["vgs"]], ["VG"]);
1069     InitEmpty, Always, TestOutputList (
1070       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071        ["pvcreate"; "/dev/sda1"];
1072        ["pvcreate"; "/dev/sda2"];
1073        ["pvcreate"; "/dev/sda3"];
1074        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075        ["vgcreate"; "VG2"; "/dev/sda3"];
1076        ["vgs"]], ["VG1"; "VG2"])],
1077    "list the LVM volume groups (VGs)",
1078    "\
1079 List all the volumes groups detected.  This is the equivalent
1080 of the L<vgs(8)> command.
1081
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1084
1085 See also C<guestfs_vgs_full>.");
1086
1087   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088    [InitBasicFSonLVM, Always, TestOutputList (
1089       [["lvs"]], ["/dev/VG/LV"]);
1090     InitEmpty, Always, TestOutputList (
1091       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092        ["pvcreate"; "/dev/sda1"];
1093        ["pvcreate"; "/dev/sda2"];
1094        ["pvcreate"; "/dev/sda3"];
1095        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096        ["vgcreate"; "VG2"; "/dev/sda3"];
1097        ["lvcreate"; "LV1"; "VG1"; "50"];
1098        ["lvcreate"; "LV2"; "VG1"; "50"];
1099        ["lvcreate"; "LV3"; "VG2"; "50"];
1100        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101    "list the LVM logical volumes (LVs)",
1102    "\
1103 List all the logical volumes detected.  This is the equivalent
1104 of the L<lvs(8)> command.
1105
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1108
1109 See also C<guestfs_lvs_full>.");
1110
1111   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112    [], (* XXX how to test? *)
1113    "list the LVM physical volumes (PVs)",
1114    "\
1115 List all the physical volumes detected.  This is the equivalent
1116 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1117
1118   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM volume groups (VGs)",
1121    "\
1122 List all the volumes groups detected.  This is the equivalent
1123 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM logical volumes (LVs)",
1128    "\
1129 List all the logical volumes detected.  This is the equivalent
1130 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133    [InitISOFS, Always, TestOutputList (
1134       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135     InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/empty"]], [])],
1137    "read file as lines",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 The file contents are returned as a list of lines.  Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1143
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line).  For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1148
1149   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150    [], (* XXX Augeas code needs tests. *)
1151    "create a new Augeas handle",
1152    "\
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1156
1157 You must call this before using any other C<guestfs_aug_*>
1158 commands.
1159
1160 C<root> is the filesystem root.  C<root> must not be NULL,
1161 use C</> instead.
1162
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1165 integers:
1166
1167 =over 4
1168
1169 =item C<AUG_SAVE_BACKUP> = 1
1170
1171 Keep the original file with a C<.augsave> extension.
1172
1173 =item C<AUG_SAVE_NEWFILE> = 2
1174
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1177
1178 =item C<AUG_TYPE_CHECK> = 4
1179
1180 Typecheck lenses (can be expensive).
1181
1182 =item C<AUG_NO_STDINC> = 8
1183
1184 Do not use standard load path for modules.
1185
1186 =item C<AUG_SAVE_NOOP> = 16
1187
1188 Make save a no-op, just record what would have been changed.
1189
1190 =item C<AUG_NO_LOAD> = 32
1191
1192 Do not load the tree in C<guestfs_aug_init>.
1193
1194 =back
1195
1196 To close the handle, you can call C<guestfs_aug_close>.
1197
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1199
1200   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201    [], (* XXX Augeas code needs tests. *)
1202    "close the current Augeas handle",
1203    "\
1204 Close the current Augeas handle and free up any resources
1205 used by it.  After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1208
1209   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210    [], (* XXX Augeas code needs tests. *)
1211    "define an Augeas variable",
1212    "\
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1215 undefined.
1216
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1219
1220   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221    [], (* XXX Augeas code needs tests. *)
1222    "define an Augeas node",
1223    "\
1224 Defines a variable C<name> whose value is the result of
1225 evaluating C<expr>.
1226
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1230
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1234
1235   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "look up the value of an Augeas path",
1238    "\
1239 Look up the value associated with C<path>.  If C<path>
1240 matches exactly one node, the C<value> is returned.");
1241
1242   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "set Augeas path to value",
1245    "\
1246 Set the value associated with C<path> to C<val>.
1247
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL.  Due to an oversight in the libguestfs API
1250 you cannot do that with this call.  Instead you must use the
1251 C<guestfs_aug_clear> call.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1394
1395 The mode actually set is affected by the umask.");
1396
1397   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398    [], (* XXX Need stat command to test *)
1399    "change file owner and group",
1400    "\
1401 Change the file owner to C<owner> and group to C<group>.
1402
1403 Only numeric uid and gid are supported.  If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1406
1407   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/empty"]]);
1410     InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/directory"]])],
1412    "test if file or directory exists",
1413    "\
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1416
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1418
1419   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420    [InitISOFS, Always, TestOutputTrue (
1421       [["is_file"; "/known-1"]]);
1422     InitISOFS, Always, TestOutputFalse (
1423       [["is_file"; "/directory"]])],
1424    "test if file exists",
1425    "\
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name.  Note that it returns false for
1428 other objects like directories.
1429
1430 See also C<guestfs_stat>.");
1431
1432   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433    [InitISOFS, Always, TestOutputFalse (
1434       [["is_dir"; "/known-3"]]);
1435     InitISOFS, Always, TestOutputTrue (
1436       [["is_dir"; "/directory"]])],
1437    "test if file exists",
1438    "\
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name.  Note that it returns false for
1441 other objects like files.
1442
1443 See also C<guestfs_stat>.");
1444
1445   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446    [InitEmpty, Always, TestOutputListOfDevices (
1447       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448        ["pvcreate"; "/dev/sda1"];
1449        ["pvcreate"; "/dev/sda2"];
1450        ["pvcreate"; "/dev/sda3"];
1451        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452    "create an LVM physical volume",
1453    "\
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1456 as C</dev/sda1>.");
1457
1458   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459    [InitEmpty, Always, TestOutputList (
1460       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461        ["pvcreate"; "/dev/sda1"];
1462        ["pvcreate"; "/dev/sda2"];
1463        ["pvcreate"; "/dev/sda3"];
1464        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465        ["vgcreate"; "VG2"; "/dev/sda3"];
1466        ["vgs"]], ["VG1"; "VG2"])],
1467    "create an LVM volume group",
1468    "\
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1471
1472   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [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        ["lvcreate"; "LV1"; "VG1"; "50"];
1481        ["lvcreate"; "LV2"; "VG1"; "50"];
1482        ["lvcreate"; "LV3"; "VG2"; "50"];
1483        ["lvcreate"; "LV4"; "VG2"; "50"];
1484        ["lvcreate"; "LV5"; "VG2"; "50"];
1485        ["lvs"]],
1486       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488    "create an LVM logical volume",
1489    "\
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1492
1493   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494    [InitEmpty, Always, TestOutput (
1495       [["part_disk"; "/dev/sda"; "mbr"];
1496        ["mkfs"; "ext2"; "/dev/sda1"];
1497        ["mount_options"; ""; "/dev/sda1"; "/"];
1498        ["write_file"; "/new"; "new file contents"; "0"];
1499        ["cat"; "/new"]], "new file contents")],
1500    "make a filesystem",
1501    "\
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume).  The filesystem type is C<fstype>, for
1504 example C<ext3>.");
1505
1506   ("sfdisk", (RErr, [Device "device";
1507                      Int "cyls"; Int "heads"; Int "sectors";
1508                      StringList "lines"]), 43, [DangerWillRobinson],
1509    [],
1510    "create partitions on a block device",
1511    "\
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1514
1515 C<device> should be a block device, for example C</dev/sda>.
1516
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted.  Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1524
1525 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1526 information refer to the L<sfdisk(8)> manpage.
1527
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1531
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1534
1535   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536    [InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "new file contents"; "0"];
1538        ["cat"; "/new"]], "new file contents");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541        ["cat"; "/new"]], "\nnew file contents\n");
1542     InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "\n\n"; "0"];
1544        ["cat"; "/new"]], "\n\n");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; ""; "0"];
1547        ["cat"; "/new"]], "");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; "\n"; "0"];
1553        ["cat"; "/new"]], "\n")],
1554    "create a file",
1555    "\
1556 This call creates a file called C<path>.  The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1559
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1563
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version.  In the meantime
1567 use C<guestfs_upload>.");
1568
1569   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570    [InitEmpty, Always, TestOutputListOfDevices (
1571       [["part_disk"; "/dev/sda"; "mbr"];
1572        ["mkfs"; "ext2"; "/dev/sda1"];
1573        ["mount_options"; ""; "/dev/sda1"; "/"];
1574        ["mounts"]], ["/dev/sda1"]);
1575     InitEmpty, Always, TestOutputList (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["umount"; "/"];
1580        ["mounts"]], [])],
1581    "unmount a filesystem",
1582    "\
1583 This unmounts the given filesystem.  The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1586
1587   ("mounts", (RStringList "devices", []), 46, [],
1588    [InitBasicFS, Always, TestOutputListOfDevices (
1589       [["mounts"]], ["/dev/sda1"])],
1590    "show mounted filesystems",
1591    "\
1592 This returns the list of currently mounted filesystems.  It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1594
1595 Some internal mounts are not shown.
1596
1597 See also: C<guestfs_mountpoints>");
1598
1599   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600    [InitBasicFS, Always, TestOutputList (
1601       [["umount_all"];
1602        ["mounts"]], []);
1603     (* check that umount_all can unmount nested mounts correctly: *)
1604     InitEmpty, Always, TestOutputList (
1605       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606        ["mkfs"; "ext2"; "/dev/sda1"];
1607        ["mkfs"; "ext2"; "/dev/sda2"];
1608        ["mkfs"; "ext2"; "/dev/sda3"];
1609        ["mount_options"; ""; "/dev/sda1"; "/"];
1610        ["mkdir"; "/mp1"];
1611        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612        ["mkdir"; "/mp1/mp2"];
1613        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614        ["mkdir"; "/mp1/mp2/mp3"];
1615        ["umount_all"];
1616        ["mounts"]], [])],
1617    "unmount all filesystems",
1618    "\
1619 This unmounts all mounted filesystems.
1620
1621 Some internal mounts are not unmounted by this call.");
1622
1623   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1624    [],
1625    "remove all LVM LVs, VGs and PVs",
1626    "\
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1629
1630   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631    [InitISOFS, Always, TestOutput (
1632       [["file"; "/empty"]], "empty");
1633     InitISOFS, Always, TestOutput (
1634       [["file"; "/known-1"]], "ASCII text");
1635     InitISOFS, Always, TestLastFail (
1636       [["file"; "/notexists"]])],
1637    "determine file type",
1638    "\
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file.  This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
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 -zbsL path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1649
1650   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651    [InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 1"]], "Result1");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 2"]], "Result2\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 3"]], "\nResult3");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 4"]], "\nResult4\n");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 5"]], "\nResult5\n\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 7"]], "");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 8"]], "\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 9"]], "\n\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691     InitBasicFS, Always, TestOutput (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695     InitBasicFS, Always, TestLastFail (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command"; "/test-command"]])],
1699    "run a command from the guest filesystem",
1700    "\
1701 This call runs a command from the guest filesystem.  The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1705
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters.  The list must be
1709 non-empty (ie. must contain a program name).  Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1712
1713 The return value is anything printed to I<stdout> by
1714 the command.
1715
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message.  The error message
1718 string is the content of I<stderr> from the command.
1719
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>.  If you require a program from
1722 another location, you should provide the full path in the
1723 first parameter.
1724
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places.  It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1729 locations.");
1730
1731   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732    [InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 1"]], ["Result1"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 2"]], ["Result2"]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 7"]], []);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 8"]], [""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 9"]], ["";""]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772     InitBasicFS, Always, TestOutputList (
1773       [["upload"; "test-command"; "/test-command"];
1774        ["chmod"; "0o755"; "/test-command"];
1775        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776    "run a command, returning lines",
1777    "\
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1780
1781 See also: C<guestfs_sh_lines>");
1782
1783   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as the C<stat(2)> system call.");
1791
1792   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795    "get file information for a symbolic link",
1796    "\
1797 Returns file information for the given C<path>.
1798
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1801 refers to.
1802
1803 This is the same as the C<lstat(2)> system call.");
1804
1805   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806    [InitISOFS, Always, TestOutputStruct (
1807       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808    "get file system statistics",
1809    "\
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1813
1814 This is the same as the C<statvfs(2)> system call.");
1815
1816   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1817    [], (* XXX test *)
1818    "get ext2/ext3/ext4 superblock details",
1819    "\
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1822
1823 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1824 manpage for more details.  The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1827
1828   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829    [InitEmpty, Always, TestOutputTrue (
1830       [["blockdev_setro"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-only",
1833    "\
1834 Sets the block device named C<device> to read-only.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839    [InitEmpty, Always, TestOutputFalse (
1840       [["blockdev_setrw"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-write",
1843    "\
1844 Sets the block device named C<device> to read-write.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849    [InitEmpty, Always, TestOutputTrue (
1850       [["blockdev_setro"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "is block device set to read-only",
1853    "\
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getss"; "/dev/sda"]], 512)],
1862    "get sectorsize of block device",
1863    "\
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1866
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 for that).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873    [InitEmpty, Always, TestOutputInt (
1874       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875    "get blocksize of block device",
1876    "\
1877 This returns the block size of a device.
1878
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1885    [], (* XXX test *)
1886    "set blocksize of block device",
1887    "\
1888 This sets the block size of a device.
1889
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898    "get total size of device in 512-byte sectors",
1899    "\
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1902
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1906
1907 This uses the L<blockdev(8)> command.");
1908
1909   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910    [InitEmpty, Always, TestOutputInt (
1911       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912    "get total size of device in bytes",
1913    "\
1914 This returns the size of the device in bytes.
1915
1916 See also C<guestfs_blockdev_getsz>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_flushbufs"; "/dev/sda"]]],
1923    "flush device buffers",
1924    "\
1925 This tells the kernel to flush internal buffers associated
1926 with C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_rereadpt"; "/dev/sda"]]],
1933    "reread partition table",
1934    "\
1935 Reread the partition table on C<device>.
1936
1937 This uses the L<blockdev(8)> command.");
1938
1939   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940    [InitBasicFS, Always, TestOutput (
1941       (* Pick a file from cwd which isn't likely to change. *)
1942       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943        ["checksum"; "md5"; "/COPYING.LIB"]],
1944       Digest.to_hex (Digest.file "COPYING.LIB"))],
1945    "upload a file from the local machine",
1946    "\
1947 Upload local file C<filename> to C<remotefilename> on the
1948 filesystem.
1949
1950 C<filename> can also be a named pipe.
1951
1952 See also C<guestfs_download>.");
1953
1954   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955    [InitBasicFS, Always, TestOutput (
1956       (* Pick a file from cwd which isn't likely to change. *)
1957       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959        ["upload"; "testdownload.tmp"; "/upload"];
1960        ["checksum"; "md5"; "/upload"]],
1961       Digest.to_hex (Digest.file "COPYING.LIB"))],
1962    "download a file to the local machine",
1963    "\
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1966
1967 C<filename> can also be a named pipe.
1968
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1970
1971   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972    [InitISOFS, Always, TestOutput (
1973       [["checksum"; "crc"; "/known-3"]], "2891671662");
1974     InitISOFS, Always, TestLastFail (
1975       [["checksum"; "crc"; "/notexists"]]);
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988    "compute MD5, SHAx or CRC checksum of file",
1989    "\
1990 This call computes the MD5, SHAx or CRC checksum of the
1991 file named C<path>.
1992
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
1995
1996 =over 4
1997
1998 =item C<crc>
1999
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2002
2003 =item C<md5>
2004
2005 Compute the MD5 hash (using the C<md5sum> program).
2006
2007 =item C<sha1>
2008
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2010
2011 =item C<sha224>
2012
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2014
2015 =item C<sha256>
2016
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2018
2019 =item C<sha384>
2020
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2022
2023 =item C<sha512>
2024
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2026
2027 =back
2028
2029 The checksum is returned as a printable string.
2030
2031 To get the checksum for a device, use C<guestfs_checksum_device>.
2032
2033 To get the checksums for many files, use C<guestfs_checksums_out>.");
2034
2035   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2036    [InitBasicFS, Always, TestOutput (
2037       [["tar_in"; "../images/helloworld.tar"; "/"];
2038        ["cat"; "/hello"]], "hello\n")],
2039    "unpack tarfile to directory",
2040    "\
2041 This command uploads and unpacks local file C<tarfile> (an
2042 I<uncompressed> tar file) into C<directory>.
2043
2044 To upload a compressed tarball, use C<guestfs_tgz_in>
2045 or C<guestfs_txz_in>.");
2046
2047   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2048    [],
2049    "pack directory into tarfile",
2050    "\
2051 This command packs the contents of C<directory> and downloads
2052 it to local file C<tarfile>.
2053
2054 To download a compressed tarball, use C<guestfs_tgz_out>
2055 or C<guestfs_txz_out>.");
2056
2057   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2058    [InitBasicFS, Always, TestOutput (
2059       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2060        ["cat"; "/hello"]], "hello\n")],
2061    "unpack compressed tarball to directory",
2062    "\
2063 This command uploads and unpacks local file C<tarball> (a
2064 I<gzip compressed> tar file) into C<directory>.
2065
2066 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2067
2068   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2069    [],
2070    "pack directory into compressed tarball",
2071    "\
2072 This command packs the contents of C<directory> and downloads
2073 it to local file C<tarball>.
2074
2075 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2076
2077   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2078    [InitBasicFS, Always, TestLastFail (
2079       [["umount"; "/"];
2080        ["mount_ro"; "/dev/sda1"; "/"];
2081        ["touch"; "/new"]]);
2082     InitBasicFS, Always, TestOutput (
2083       [["write_file"; "/new"; "data"; "0"];
2084        ["umount"; "/"];
2085        ["mount_ro"; "/dev/sda1"; "/"];
2086        ["cat"; "/new"]], "data")],
2087    "mount a guest disk, read-only",
2088    "\
2089 This is the same as the C<guestfs_mount> command, but it
2090 mounts the filesystem with the read-only (I<-o ro>) flag.");
2091
2092   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2093    [],
2094    "mount a guest disk with mount options",
2095    "\
2096 This is the same as the C<guestfs_mount> command, but it
2097 allows you to set the mount options as for the
2098 L<mount(8)> I<-o> flag.");
2099
2100   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2101    [],
2102    "mount a guest disk with mount options and vfstype",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set both the mount options and the vfstype
2106 as for the L<mount(8)> I<-o> and I<-t> flags.");
2107
2108   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2109    [],
2110    "debugging and internals",
2111    "\
2112 The C<guestfs_debug> command exposes some internals of
2113 C<guestfsd> (the guestfs daemon) that runs inside the
2114 qemu subprocess.
2115
2116 There is no comprehensive help for this command.  You have
2117 to look at the file C<daemon/debug.c> in the libguestfs source
2118 to find out what you can do.");
2119
2120   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2121    [InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG/LV1"];
2128        ["lvs"]], ["/dev/VG/LV2"]);
2129     InitEmpty, Always, TestOutputList (
2130       [["part_disk"; "/dev/sda"; "mbr"];
2131        ["pvcreate"; "/dev/sda1"];
2132        ["vgcreate"; "VG"; "/dev/sda1"];
2133        ["lvcreate"; "LV1"; "VG"; "50"];
2134        ["lvcreate"; "LV2"; "VG"; "50"];
2135        ["lvremove"; "/dev/VG"];
2136        ["lvs"]], []);
2137     InitEmpty, Always, TestOutputList (
2138       [["part_disk"; "/dev/sda"; "mbr"];
2139        ["pvcreate"; "/dev/sda1"];
2140        ["vgcreate"; "VG"; "/dev/sda1"];
2141        ["lvcreate"; "LV1"; "VG"; "50"];
2142        ["lvcreate"; "LV2"; "VG"; "50"];
2143        ["lvremove"; "/dev/VG"];
2144        ["vgs"]], ["VG"])],
2145    "remove an LVM logical volume",
2146    "\
2147 Remove an LVM logical volume C<device>, where C<device> is
2148 the path to the LV, such as C</dev/VG/LV>.
2149
2150 You can also remove all LVs in a volume group by specifying
2151 the VG name, C</dev/VG>.");
2152
2153   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2154    [InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["vgremove"; "VG"];
2161        ["lvs"]], []);
2162     InitEmpty, Always, TestOutputList (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["vgs"]], [])],
2170    "remove an LVM volume group",
2171    "\
2172 Remove an LVM volume group C<vgname>, (for example C<VG>).
2173
2174 This also forcibly removes all logical volumes in the volume
2175 group (if any).");
2176
2177   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2178    [InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["lvs"]], []);
2187     InitEmpty, Always, TestOutputListOfDevices (
2188       [["part_disk"; "/dev/sda"; "mbr"];
2189        ["pvcreate"; "/dev/sda1"];
2190        ["vgcreate"; "VG"; "/dev/sda1"];
2191        ["lvcreate"; "LV1"; "VG"; "50"];
2192        ["lvcreate"; "LV2"; "VG"; "50"];
2193        ["vgremove"; "VG"];
2194        ["pvremove"; "/dev/sda1"];
2195        ["vgs"]], []);
2196     InitEmpty, Always, TestOutputListOfDevices (
2197       [["part_disk"; "/dev/sda"; "mbr"];
2198        ["pvcreate"; "/dev/sda1"];
2199        ["vgcreate"; "VG"; "/dev/sda1"];
2200        ["lvcreate"; "LV1"; "VG"; "50"];
2201        ["lvcreate"; "LV2"; "VG"; "50"];
2202        ["vgremove"; "VG"];
2203        ["pvremove"; "/dev/sda1"];
2204        ["pvs"]], [])],
2205    "remove an LVM physical volume",
2206    "\
2207 This wipes a physical volume C<device> so that LVM will no longer
2208 recognise it.
2209
2210 The implementation uses the C<pvremove> command which refuses to
2211 wipe physical volumes that contain any volume groups, so you have
2212 to remove those first.");
2213
2214   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["set_e2label"; "/dev/sda1"; "testlabel"];
2217        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2218    "set the ext2/3/4 filesystem label",
2219    "\
2220 This sets the ext2/3/4 filesystem label of the filesystem on
2221 C<device> to C<label>.  Filesystem labels are limited to
2222 16 characters.
2223
2224 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2225 to return the existing label on a filesystem.");
2226
2227   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2228    [],
2229    "get the ext2/3/4 filesystem label",
2230    "\
2231 This returns the ext2/3/4 filesystem label of the filesystem on
2232 C<device>.");
2233
2234   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2235    (let uuid = uuidgen () in
2236     [InitBasicFS, Always, TestOutput (
2237        [["set_e2uuid"; "/dev/sda1"; uuid];
2238         ["get_e2uuid"; "/dev/sda1"]], uuid);
2239      InitBasicFS, Always, TestOutput (
2240        [["set_e2uuid"; "/dev/sda1"; "clear"];
2241         ["get_e2uuid"; "/dev/sda1"]], "");
2242      (* We can't predict what UUIDs will be, so just check the commands run. *)
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2245      InitBasicFS, Always, TestRun (
2246        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2247    "set the ext2/3/4 filesystem UUID",
2248    "\
2249 This sets the ext2/3/4 filesystem UUID of the filesystem on
2250 C<device> to C<uuid>.  The format of the UUID and alternatives
2251 such as C<clear>, C<random> and C<time> are described in the
2252 L<tune2fs(8)> manpage.
2253
2254 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2255 to return the existing UUID of a filesystem.");
2256
2257   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2258    [],
2259    "get the ext2/3/4 filesystem UUID",
2260    "\
2261 This returns the ext2/3/4 filesystem UUID of the filesystem on
2262 C<device>.");
2263
2264   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2265    [InitBasicFS, Always, TestOutputInt (
2266       [["umount"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2268     InitBasicFS, Always, TestOutputInt (
2269       [["umount"; "/dev/sda1"];
2270        ["zero"; "/dev/sda1"];
2271        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2272    "run the filesystem checker",
2273    "\
2274 This runs the filesystem checker (fsck) on C<device> which
2275 should have filesystem type C<fstype>.
2276
2277 The returned integer is the status.  See L<fsck(8)> for the
2278 list of status codes from C<fsck>.
2279
2280 Notes:
2281
2282 =over 4
2283
2284 =item *
2285
2286 Multiple status codes can be summed together.
2287
2288 =item *
2289
2290 A non-zero return code can mean \"success\", for example if
2291 errors have been corrected on the filesystem.
2292
2293 =item *
2294
2295 Checking or repairing NTFS volumes is not supported
2296 (by linux-ntfs).
2297
2298 =back
2299
2300 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2301
2302   ("zero", (RErr, [Device "device"]), 85, [],
2303    [InitBasicFS, Always, TestOutput (
2304       [["umount"; "/dev/sda1"];
2305        ["zero"; "/dev/sda1"];
2306        ["file"; "/dev/sda1"]], "data")],
2307    "write zeroes to the device",
2308    "\
2309 This command writes zeroes over the first few blocks of C<device>.
2310
2311 How many blocks are zeroed isn't specified (but it's I<not> enough
2312 to securely wipe the device).  It should be sufficient to remove
2313 any partition tables, filesystem superblocks and so on.
2314
2315 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2316
2317   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2318    (* Test disabled because grub-install incompatible with virtio-blk driver.
2319     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2320     *)
2321    [InitBasicFS, Disabled, TestOutputTrue (
2322       [["grub_install"; "/"; "/dev/sda1"];
2323        ["is_dir"; "/boot"]])],
2324    "install GRUB",
2325    "\
2326 This command installs GRUB (the Grand Unified Bootloader) on
2327 C<device>, with the root directory being C<root>.");
2328
2329   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2330    [InitBasicFS, Always, TestOutput (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["cat"; "/new"]], "file content");
2334     InitBasicFS, Always, TestOutputTrue (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["cp"; "/old"; "/new"];
2337        ["is_file"; "/old"]]);
2338     InitBasicFS, Always, TestOutput (
2339       [["write_file"; "/old"; "file content"; "0"];
2340        ["mkdir"; "/dir"];
2341        ["cp"; "/old"; "/dir/new"];
2342        ["cat"; "/dir/new"]], "file content")],
2343    "copy a file",
2344    "\
2345 This copies a file from C<src> to C<dest> where C<dest> is
2346 either a destination filename or destination directory.");
2347
2348   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2349    [InitBasicFS, Always, TestOutput (
2350       [["mkdir"; "/olddir"];
2351        ["mkdir"; "/newdir"];
2352        ["write_file"; "/olddir/file"; "file content"; "0"];
2353        ["cp_a"; "/olddir"; "/newdir"];
2354        ["cat"; "/newdir/olddir/file"]], "file content")],
2355    "copy a file or directory recursively",
2356    "\
2357 This copies a file or directory from C<src> to C<dest>
2358 recursively using the C<cp -a> command.");
2359
2360   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2361    [InitBasicFS, Always, TestOutput (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["cat"; "/new"]], "file content");
2365     InitBasicFS, Always, TestOutputFalse (
2366       [["write_file"; "/old"; "file content"; "0"];
2367        ["mv"; "/old"; "/new"];
2368        ["is_file"; "/old"]])],
2369    "move a file",
2370    "\
2371 This moves a file from C<src> to C<dest> where C<dest> is
2372 either a destination filename or destination directory.");
2373
2374   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2375    [InitEmpty, Always, TestRun (
2376       [["drop_caches"; "3"]])],
2377    "drop kernel page cache, dentries and inodes",
2378    "\
2379 This instructs the guest kernel to drop its page cache,
2380 and/or dentries and inode caches.  The parameter C<whattodrop>
2381 tells the kernel what precisely to drop, see
2382 L<http://linux-mm.org/Drop_Caches>
2383
2384 Setting C<whattodrop> to 3 should drop everything.
2385
2386 This automatically calls L<sync(2)> before the operation,
2387 so that the maximum guest memory is freed.");
2388
2389   ("dmesg", (RString "kmsgs", []), 91, [],
2390    [InitEmpty, Always, TestRun (
2391       [["dmesg"]])],
2392    "return kernel messages",
2393    "\
2394 This returns the kernel messages (C<dmesg> output) from
2395 the guest kernel.  This is sometimes useful for extended
2396 debugging of problems.
2397
2398 Another way to get the same information is to enable
2399 verbose messages with C<guestfs_set_verbose> or by setting
2400 the environment variable C<LIBGUESTFS_DEBUG=1> before
2401 running the program.");
2402
2403   ("ping_daemon", (RErr, []), 92, [],
2404    [InitEmpty, Always, TestRun (
2405       [["ping_daemon"]])],
2406    "ping the guest daemon",
2407    "\
2408 This is a test probe into the guestfs daemon running inside
2409 the qemu subprocess.  Calling this function checks that the
2410 daemon responds to the ping message, without affecting the daemon
2411 or attached block device(s) in any other way.");
2412
2413   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2414    [InitBasicFS, Always, TestOutputTrue (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["cp"; "/file1"; "/file2"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestOutputFalse (
2419       [["write_file"; "/file1"; "contents of a file"; "0"];
2420        ["write_file"; "/file2"; "contents of another file"; "0"];
2421        ["equal"; "/file1"; "/file2"]]);
2422     InitBasicFS, Always, TestLastFail (
2423       [["equal"; "/file1"; "/file2"]])],
2424    "test if two files have equal contents",
2425    "\
2426 This compares the two files C<file1> and C<file2> and returns
2427 true if their content is exactly equal, or false otherwise.
2428
2429 The external L<cmp(1)> program is used for the comparison.");
2430
2431   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2432    [InitISOFS, Always, TestOutputList (
2433       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2434     InitISOFS, Always, TestOutputList (
2435       [["strings"; "/empty"]], [])],
2436    "print the printable strings in a file",
2437    "\
2438 This runs the L<strings(1)> command on a file and returns
2439 the list of printable strings found.");
2440
2441   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutputList (
2443       [["strings_e"; "b"; "/known-5"]], []);
2444     InitBasicFS, Disabled, TestOutputList (
2445       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2446        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2447    "print the printable strings in a file",
2448    "\
2449 This is like the C<guestfs_strings> command, but allows you to
2450 specify the encoding.
2451
2452 See the L<strings(1)> manpage for the full list of encodings.
2453
2454 Commonly useful encodings are C<l> (lower case L) which will
2455 show strings inside Windows/x86 files.
2456
2457 The returned strings are transcoded to UTF-8.");
2458
2459   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2460    [InitISOFS, Always, TestOutput (
2461       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2462     (* Test for RHBZ#501888c2 regression which caused large hexdump
2463      * commands to segfault.
2464      *)
2465     InitISOFS, Always, TestRun (
2466       [["hexdump"; "/100krandom"]])],
2467    "dump a file in hexadecimal",
2468    "\
2469 This runs C<hexdump -C> on the given C<path>.  The result is
2470 the human-readable, canonical hex dump of the file.");
2471
2472   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2473    [InitNone, Always, TestOutput (
2474       [["part_disk"; "/dev/sda"; "mbr"];
2475        ["mkfs"; "ext3"; "/dev/sda1"];
2476        ["mount_options"; ""; "/dev/sda1"; "/"];
2477        ["write_file"; "/new"; "test file"; "0"];
2478        ["umount"; "/dev/sda1"];
2479        ["zerofree"; "/dev/sda1"];
2480        ["mount_options"; ""; "/dev/sda1"; "/"];
2481        ["cat"; "/new"]], "test file")],
2482    "zero unused inodes and disk blocks on ext2/3 filesystem",
2483    "\
2484 This runs the I<zerofree> program on C<device>.  This program
2485 claims to zero unused inodes and disk blocks on an ext2/3
2486 filesystem, thus making it possible to compress the filesystem
2487 more effectively.
2488
2489 You should B<not> run this program if the filesystem is
2490 mounted.
2491
2492 It is possible that using this program can damage the filesystem
2493 or data on the filesystem.");
2494
2495   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2496    [],
2497    "resize an LVM physical volume",
2498    "\
2499 This resizes (expands or shrinks) an existing LVM physical
2500 volume to match the new size of the underlying device.");
2501
2502   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2503                        Int "cyls"; Int "heads"; Int "sectors";
2504                        String "line"]), 99, [DangerWillRobinson],
2505    [],
2506    "modify a single partition on a block device",
2507    "\
2508 This runs L<sfdisk(8)> option to modify just the single
2509 partition C<n> (note: C<n> counts from 1).
2510
2511 For other parameters, see C<guestfs_sfdisk>.  You should usually
2512 pass C<0> for the cyls/heads/sectors parameters.
2513
2514 See also: C<guestfs_part_add>");
2515
2516   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2517    [],
2518    "display the partition table",
2519    "\
2520 This displays the partition table on C<device>, in the
2521 human-readable output of the L<sfdisk(8)> command.  It is
2522 not intended to be parsed.
2523
2524 See also: C<guestfs_part_list>");
2525
2526   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2527    [],
2528    "display the kernel geometry",
2529    "\
2530 This displays the kernel's idea of the geometry of C<device>.
2531
2532 The result is in human-readable format, and not designed to
2533 be parsed.");
2534
2535   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2536    [],
2537    "display the disk geometry from the partition table",
2538    "\
2539 This displays the disk geometry of C<device> read from the
2540 partition table.  Especially in the case where the underlying
2541 block device has been resized, this can be different from the
2542 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2543
2544 The result is in human-readable format, and not designed to
2545 be parsed.");
2546
2547   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2548    [],
2549    "activate or deactivate all volume groups",
2550    "\
2551 This command activates or (if C<activate> is false) deactivates
2552 all logical volumes in all volume groups.
2553 If activated, then they are made known to the
2554 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2555 then those devices disappear.
2556
2557 This command is the same as running C<vgchange -a y|n>");
2558
2559   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2560    [],
2561    "activate or deactivate some volume groups",
2562    "\
2563 This command activates or (if C<activate> is false) deactivates
2564 all logical volumes in the listed volume groups C<volgroups>.
2565 If activated, then they are made known to the
2566 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2567 then those devices disappear.
2568
2569 This command is the same as running C<vgchange -a y|n volgroups...>
2570
2571 Note that if C<volgroups> is an empty list then B<all> volume groups
2572 are activated or deactivated.");
2573
2574   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2575    [InitNone, Always, TestOutput (
2576       [["part_disk"; "/dev/sda"; "mbr"];
2577        ["pvcreate"; "/dev/sda1"];
2578        ["vgcreate"; "VG"; "/dev/sda1"];
2579        ["lvcreate"; "LV"; "VG"; "10"];
2580        ["mkfs"; "ext2"; "/dev/VG/LV"];
2581        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2582        ["write_file"; "/new"; "test content"; "0"];
2583        ["umount"; "/"];
2584        ["lvresize"; "/dev/VG/LV"; "20"];
2585        ["e2fsck_f"; "/dev/VG/LV"];
2586        ["resize2fs"; "/dev/VG/LV"];
2587        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2588        ["cat"; "/new"]], "test content")],
2589    "resize an LVM logical volume",
2590    "\
2591 This resizes (expands or shrinks) an existing LVM logical
2592 volume to C<mbytes>.  When reducing, data in the reduced part
2593 is lost.");
2594
2595   ("resize2fs", (RErr, [Device "device"]), 106, [],
2596    [], (* lvresize tests this *)
2597    "resize an ext2/ext3 filesystem",
2598    "\
2599 This resizes an ext2 or ext3 filesystem to match the size of
2600 the underlying device.
2601
2602 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2603 on the C<device> before calling this command.  For unknown reasons
2604 C<resize2fs> sometimes gives an error about this and sometimes not.
2605 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2606 calling this function.");
2607
2608   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2609    [InitBasicFS, Always, TestOutputList (
2610       [["find"; "/"]], ["lost+found"]);
2611     InitBasicFS, Always, TestOutputList (
2612       [["touch"; "/a"];
2613        ["mkdir"; "/b"];
2614        ["touch"; "/b/c"];
2615        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2616     InitBasicFS, Always, TestOutputList (
2617       [["mkdir_p"; "/a/b/c"];
2618        ["touch"; "/a/b/c/d"];
2619        ["find"; "/a/b/"]], ["c"; "c/d"])],
2620    "find all files and directories",
2621    "\
2622 This command lists out all files and directories, recursively,
2623 starting at C<directory>.  It is essentially equivalent to
2624 running the shell command C<find directory -print> but some
2625 post-processing happens on the output, described below.
2626
2627 This returns a list of strings I<without any prefix>.  Thus
2628 if the directory structure was:
2629
2630  /tmp/a
2631  /tmp/b
2632  /tmp/c/d
2633
2634 then the returned list from C<guestfs_find> C</tmp> would be
2635 4 elements:
2636
2637  a
2638  b
2639  c
2640  c/d
2641
2642 If C<directory> is not a directory, then this command returns
2643 an error.
2644
2645 The returned list is sorted.
2646
2647 See also C<guestfs_find0>.");
2648
2649   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2650    [], (* lvresize tests this *)
2651    "check an ext2/ext3 filesystem",
2652    "\
2653 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2654 filesystem checker on C<device>, noninteractively (C<-p>),
2655 even if the filesystem appears to be clean (C<-f>).
2656
2657 This command is only needed because of C<guestfs_resize2fs>
2658 (q.v.).  Normally you should use C<guestfs_fsck>.");
2659
2660   ("sleep", (RErr, [Int "secs"]), 109, [],
2661    [InitNone, Always, TestRun (
2662       [["sleep"; "1"]])],
2663    "sleep for some seconds",
2664    "\
2665 Sleep for C<secs> seconds.");
2666
2667   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2668    [InitNone, Always, TestOutputInt (
2669       [["part_disk"; "/dev/sda"; "mbr"];
2670        ["mkfs"; "ntfs"; "/dev/sda1"];
2671        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2672     InitNone, Always, TestOutputInt (
2673       [["part_disk"; "/dev/sda"; "mbr"];
2674        ["mkfs"; "ext2"; "/dev/sda1"];
2675        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2676    "probe NTFS volume",
2677    "\
2678 This command runs the L<ntfs-3g.probe(8)> command which probes
2679 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2680 be mounted read-write, and some cannot be mounted at all).
2681
2682 C<rw> is a boolean flag.  Set it to true if you want to test
2683 if the volume can be mounted read-write.  Set it to false if
2684 you want to test if the volume can be mounted read-only.
2685
2686 The return value is an integer which C<0> if the operation
2687 would succeed, or some non-zero value documented in the
2688 L<ntfs-3g.probe(8)> manual page.");
2689
2690   ("sh", (RString "output", [String "command"]), 111, [],
2691    [], (* XXX needs tests *)
2692    "run a command via the shell",
2693    "\
2694 This call runs a command from the guest filesystem via the
2695 guest's C</bin/sh>.
2696
2697 This is like C<guestfs_command>, but passes the command to:
2698
2699  /bin/sh -c \"command\"
2700
2701 Depending on the guest's shell, this usually results in
2702 wildcards being expanded, shell expressions being interpolated
2703 and so on.
2704
2705 All the provisos about C<guestfs_command> apply to this call.");
2706
2707   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2708    [], (* XXX needs tests *)
2709    "run a command via the shell returning lines",
2710    "\
2711 This is the same as C<guestfs_sh>, but splits the result
2712 into a list of lines.
2713
2714 See also: C<guestfs_command_lines>");
2715
2716   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2717    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2718     * code in stubs.c, since all valid glob patterns must start with "/".
2719     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2720     *)
2721    [InitBasicFS, Always, TestOutputList (
2722       [["mkdir_p"; "/a/b/c"];
2723        ["touch"; "/a/b/c/d"];
2724        ["touch"; "/a/b/c/e"];
2725        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2726     InitBasicFS, Always, TestOutputList (
2727       [["mkdir_p"; "/a/b/c"];
2728        ["touch"; "/a/b/c/d"];
2729        ["touch"; "/a/b/c/e"];
2730        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2731     InitBasicFS, Always, TestOutputList (
2732       [["mkdir_p"; "/a/b/c"];
2733        ["touch"; "/a/b/c/d"];
2734        ["touch"; "/a/b/c/e"];
2735        ["glob_expand"; "/a/*/x/*"]], [])],
2736    "expand a wildcard path",
2737    "\
2738 This command searches for all the pathnames matching
2739 C<pattern> according to the wildcard expansion rules
2740 used by the shell.
2741
2742 If no paths match, then this returns an empty list
2743 (note: not an error).
2744
2745 It is just a wrapper around the C L<glob(3)> function
2746 with flags C<GLOB_MARK|GLOB_BRACE>.
2747 See that manual page for more details.");
2748
2749   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2750    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2751       [["scrub_device"; "/dev/sdc"]])],
2752    "scrub (securely wipe) a device",
2753    "\
2754 This command writes patterns over C<device> to make data retrieval
2755 more difficult.
2756
2757 It is an interface to the L<scrub(1)> program.  See that
2758 manual page for more details.");
2759
2760   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2761    [InitBasicFS, Always, TestRun (
2762       [["write_file"; "/file"; "content"; "0"];
2763        ["scrub_file"; "/file"]])],
2764    "scrub (securely wipe) a file",
2765    "\
2766 This command writes patterns over a file to make data retrieval
2767 more difficult.
2768
2769 The file is I<removed> after scrubbing.
2770
2771 It is an interface to the L<scrub(1)> program.  See that
2772 manual page for more details.");
2773
2774   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2775    [], (* XXX needs testing *)
2776    "scrub (securely wipe) free space",
2777    "\
2778 This command creates the directory C<dir> and then fills it
2779 with files until the filesystem is full, and scrubs the files
2780 as for C<guestfs_scrub_file>, and deletes them.
2781 The intention is to scrub any free space on the partition
2782 containing C<dir>.
2783
2784 It is an interface to the L<scrub(1)> program.  See that
2785 manual page for more details.");
2786
2787   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2788    [InitBasicFS, Always, TestRun (
2789       [["mkdir"; "/tmp"];
2790        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2791    "create a temporary directory",
2792    "\
2793 This command creates a temporary directory.  The
2794 C<template> parameter should be a full pathname for the
2795 temporary directory name with the final six characters being
2796 \"XXXXXX\".
2797
2798 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2799 the second one being suitable for Windows filesystems.
2800
2801 The name of the temporary directory that was created
2802 is returned.
2803
2804 The temporary directory is created with mode 0700
2805 and is owned by root.
2806
2807 The caller is responsible for deleting the temporary
2808 directory and its contents after use.
2809
2810 See also: L<mkdtemp(3)>");
2811
2812   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_l"; "/10klines"]], 10000)],
2815    "count lines in a file",
2816    "\
2817 This command counts the lines in a file, using the
2818 C<wc -l> external command.");
2819
2820   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2821    [InitISOFS, Always, TestOutputInt (
2822       [["wc_w"; "/10klines"]], 10000)],
2823    "count words in a file",
2824    "\
2825 This command counts the words in a file, using the
2826 C<wc -w> external command.");
2827
2828   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2829    [InitISOFS, Always, TestOutputInt (
2830       [["wc_c"; "/100kallspaces"]], 102400)],
2831    "count characters in a file",
2832    "\
2833 This command counts the characters in a file, using the
2834 C<wc -c> external command.");
2835
2836   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2837    [InitISOFS, Always, TestOutputList (
2838       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2839    "return first 10 lines of a file",
2840    "\
2841 This command returns up to the first 10 lines of a file as
2842 a list of strings.");
2843
2844   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2845    [InitISOFS, Always, TestOutputList (
2846       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2847     InitISOFS, Always, TestOutputList (
2848       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2849     InitISOFS, Always, TestOutputList (
2850       [["head_n"; "0"; "/10klines"]], [])],
2851    "return first N lines of a file",
2852    "\
2853 If the parameter C<nrlines> is a positive number, this returns the first
2854 C<nrlines> lines of the file C<path>.
2855
2856 If the parameter C<nrlines> is a negative number, this returns lines
2857 from the file C<path>, excluding the last C<nrlines> lines.
2858
2859 If the parameter C<nrlines> is zero, this returns an empty list.");
2860
2861   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2862    [InitISOFS, Always, TestOutputList (
2863       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2864    "return last 10 lines of a file",
2865    "\
2866 This command returns up to the last 10 lines of a file as
2867 a list of strings.");
2868
2869   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2870    [InitISOFS, Always, TestOutputList (
2871       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2872     InitISOFS, Always, TestOutputList (
2873       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2874     InitISOFS, Always, TestOutputList (
2875       [["tail_n"; "0"; "/10klines"]], [])],
2876    "return last N lines of a file",
2877    "\
2878 If the parameter C<nrlines> is a positive number, this returns the last
2879 C<nrlines> lines of the file C<path>.
2880
2881 If the parameter C<nrlines> is a negative number, this returns lines
2882 from the file C<path>, starting with the C<-nrlines>th line.
2883
2884 If the parameter C<nrlines> is zero, this returns an empty list.");
2885
2886   ("df", (RString "output", []), 125, [],
2887    [], (* XXX Tricky to test because it depends on the exact format
2888         * of the 'df' command and other imponderables.
2889         *)
2890    "report file system disk space usage",
2891    "\
2892 This command runs the C<df> command to report disk space used.
2893
2894 This command is mostly useful for interactive sessions.  It
2895 is I<not> intended that you try to parse the output string.
2896 Use C<statvfs> from programs.");
2897
2898   ("df_h", (RString "output", []), 126, [],
2899    [], (* XXX Tricky to test because it depends on the exact format
2900         * of the 'df' command and other imponderables.
2901         *)
2902    "report file system disk space usage (human readable)",
2903    "\
2904 This command runs the C<df -h> command to report disk space used
2905 in human-readable format.
2906
2907 This command is mostly useful for interactive sessions.  It
2908 is I<not> intended that you try to parse the output string.
2909 Use C<statvfs> from programs.");
2910
2911   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2912    [InitISOFS, Always, TestOutputInt (
2913       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2914    "estimate file space usage",
2915    "\
2916 This command runs the C<du -s> command to estimate file space
2917 usage for C<path>.
2918
2919 C<path> can be a file or a directory.  If C<path> is a directory
2920 then the estimate includes the contents of the directory and all
2921 subdirectories (recursively).
2922
2923 The result is the estimated size in I<kilobytes>
2924 (ie. units of 1024 bytes).");
2925
2926   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2927    [InitISOFS, Always, TestOutputList (
2928       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2929    "list files in an initrd",
2930    "\
2931 This command lists out files contained in an initrd.
2932
2933 The files are listed without any initial C</> character.  The
2934 files are listed in the order they appear (not necessarily
2935 alphabetical).  Directory names are listed as separate items.
2936
2937 Old Linux kernels (2.4 and earlier) used a compressed ext2
2938 filesystem as initrd.  We I<only> support the newer initramfs
2939 format (compressed cpio files).");
2940
2941   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2942    [],
2943    "mount a file using the loop device",
2944    "\
2945 This command lets you mount C<file> (a filesystem image
2946 in a file) on a mount point.  It is entirely equivalent to
2947 the command C<mount -o loop file mountpoint>.");
2948
2949   ("mkswap", (RErr, [Device "device"]), 130, [],
2950    [InitEmpty, Always, TestRun (
2951       [["part_disk"; "/dev/sda"; "mbr"];
2952        ["mkswap"; "/dev/sda1"]])],
2953    "create a swap partition",
2954    "\
2955 Create a swap partition on C<device>.");
2956
2957   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2958    [InitEmpty, Always, TestRun (
2959       [["part_disk"; "/dev/sda"; "mbr"];
2960        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2961    "create a swap partition with a label",
2962    "\
2963 Create a swap partition on C<device> with label C<label>.
2964
2965 Note that you cannot attach a swap label to a block device
2966 (eg. C</dev/sda>), just to a partition.  This appears to be
2967 a limitation of the kernel or swap tools.");
2968
2969   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2970    (let uuid = uuidgen () in
2971     [InitEmpty, Always, TestRun (
2972        [["part_disk"; "/dev/sda"; "mbr"];
2973         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2974    "create a swap partition with an explicit UUID",
2975    "\
2976 Create a swap partition on C<device> with UUID C<uuid>.");
2977
2978   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2979    [InitBasicFS, Always, TestOutputStruct (
2980       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2981        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2982        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2983     InitBasicFS, Always, TestOutputStruct (
2984       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2985        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2986    "make block, character or FIFO devices",
2987    "\
2988 This call creates block or character special devices, or
2989 named pipes (FIFOs).
2990
2991 The C<mode> parameter should be the mode, using the standard
2992 constants.  C<devmajor> and C<devminor> are the
2993 device major and minor numbers, only used when creating block
2994 and character special devices.
2995
2996 Note that, just like L<mknod(2)>, the mode must be bitwise
2997 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2998 just creates a regular file).  These constants are
2999 available in the standard Linux header files, or you can use
3000 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3001 which are wrappers around this command which bitwise OR
3002 in the appropriate constant for you.
3003
3004 The mode actually set is affected by the umask.");
3005
3006   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3007    [InitBasicFS, Always, TestOutputStruct (
3008       [["mkfifo"; "0o777"; "/node"];
3009        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3010    "make FIFO (named pipe)",
3011    "\
3012 This call creates a FIFO (named pipe) called C<path> with
3013 mode C<mode>.  It is just a convenient wrapper around
3014 C<guestfs_mknod>.
3015
3016 The mode actually set is affected by the umask.");
3017
3018   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3019    [InitBasicFS, Always, TestOutputStruct (
3020       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3021        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3022    "make block device node",
3023    "\
3024 This call creates a block device node called C<path> with
3025 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3026 It is just a convenient wrapper around C<guestfs_mknod>.
3027
3028 The mode actually set is affected by the umask.");
3029
3030   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3031    [InitBasicFS, Always, TestOutputStruct (
3032       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3033        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3034    "make char device node",
3035    "\
3036 This call creates a char device node called C<path> with
3037 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3038 It is just a convenient wrapper around C<guestfs_mknod>.
3039
3040 The mode actually set is affected by the umask.");
3041
3042   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3043    [InitEmpty, Always, TestOutputInt (
3044       [["umask"; "0o22"]], 0o22)],
3045    "set file mode creation mask (umask)",
3046    "\
3047 This function sets the mask used for creating new files and
3048 device nodes to C<mask & 0777>.
3049
3050 Typical umask values would be C<022> which creates new files
3051 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3052 C<002> which creates new files with permissions like
3053 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3054
3055 The default umask is C<022>.  This is important because it
3056 means that directories and device nodes will be created with
3057 C<0644> or C<0755> mode even if you specify C<0777>.
3058
3059 See also C<guestfs_get_umask>,
3060 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3061
3062 This call returns the previous umask.");
3063
3064   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3065    [],
3066    "read directories entries",
3067    "\
3068 This returns the list of directory entries in directory C<dir>.
3069
3070 All entries in the directory are returned, including C<.> and
3071 C<..>.  The entries are I<not> sorted, but returned in the same
3072 order as the underlying filesystem.
3073
3074 Also this call returns basic file type information about each
3075 file.  The C<ftyp> field will contain one of the following characters:
3076
3077 =over 4
3078
3079 =item 'b'
3080
3081 Block special
3082
3083 =item 'c'
3084
3085 Char special
3086
3087 =item 'd'
3088
3089 Directory
3090
3091 =item 'f'
3092
3093 FIFO (named pipe)
3094
3095 =item 'l'
3096
3097 Symbolic link
3098
3099 =item 'r'
3100
3101 Regular file
3102
3103 =item 's'
3104
3105 Socket
3106
3107 =item 'u'
3108
3109 Unknown file type
3110
3111 =item '?'
3112
3113 The L<readdir(3)> returned a C<d_type> field with an
3114 unexpected value
3115
3116 =back
3117
3118 This function is primarily intended for use by programs.  To
3119 get a simple list of names, use C<guestfs_ls>.  To get a printable
3120 directory for human consumption, use C<guestfs_ll>.");
3121
3122   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3123    [],
3124    "create partitions on a block device",
3125    "\
3126 This is a simplified interface to the C<guestfs_sfdisk>
3127 command, where partition sizes are specified in megabytes
3128 only (rounded to the nearest cylinder) and you don't need
3129 to specify the cyls, heads and sectors parameters which
3130 were rarely if ever used anyway.
3131
3132 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3133 and C<guestfs_part_disk>");
3134
3135   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3136    [],
3137    "determine file type inside a compressed file",
3138    "\
3139 This command runs C<file> after first decompressing C<path>
3140 using C<method>.
3141
3142 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3143
3144 Since 1.0.63, use C<guestfs_file> instead which can now
3145 process compressed files.");
3146
3147   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3148    [],
3149    "list extended attributes of a file or directory",
3150    "\
3151 This call lists the extended attributes of the file or directory
3152 C<path>.
3153
3154 At the system call level, this is a combination of the
3155 L<listxattr(2)> and L<getxattr(2)> calls.
3156
3157 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3158
3159   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3160    [],
3161    "list extended attributes of a file or directory",
3162    "\
3163 This is the same as C<guestfs_getxattrs>, but if C<path>
3164 is a symbolic link, then it returns the extended attributes
3165 of the link itself.");
3166
3167   ("setxattr", (RErr, [String "xattr";
3168                        String "val"; Int "vallen"; (* will be BufferIn *)
3169                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3170    [],
3171    "set extended attribute of a file or directory",
3172    "\
3173 This call sets the extended attribute named C<xattr>
3174 of the file C<path> to the value C<val> (of length C<vallen>).
3175 The value is arbitrary 8 bit data.
3176
3177 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3178
3179   ("lsetxattr", (RErr, [String "xattr";
3180                         String "val"; Int "vallen"; (* will be BufferIn *)
3181                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3182    [],
3183    "set extended attribute of a file or directory",
3184    "\
3185 This is the same as C<guestfs_setxattr>, but if C<path>
3186 is a symbolic link, then it sets an extended attribute
3187 of the link itself.");
3188
3189   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3190    [],
3191    "remove extended attribute of a file or directory",
3192    "\
3193 This call removes the extended attribute named C<xattr>
3194 of the file C<path>.
3195
3196 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3197
3198   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3199    [],
3200    "remove extended attribute of a file or directory",
3201    "\
3202 This is the same as C<guestfs_removexattr>, but if C<path>
3203 is a symbolic link, then it removes an extended attribute
3204 of the link itself.");
3205
3206   ("mountpoints", (RHashtable "mps", []), 147, [],
3207    [],
3208    "show mountpoints",
3209    "\
3210 This call is similar to C<guestfs_mounts>.  That call returns
3211 a list of devices.  This one returns a hash table (map) of
3212 device name to directory where the device is mounted.");
3213
3214   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3215    (* This is a special case: while you would expect a parameter
3216     * of type "Pathname", that doesn't work, because it implies
3217     * NEED_ROOT in the generated calling code in stubs.c, and
3218     * this function cannot use NEED_ROOT.
3219     *)
3220    [],
3221    "create a mountpoint",
3222    "\
3223 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3224 specialized calls that can be used to create extra mountpoints
3225 before mounting the first filesystem.
3226
3227 These calls are I<only> necessary in some very limited circumstances,
3228 mainly the case where you want to mount a mix of unrelated and/or
3229 read-only filesystems together.
3230
3231 For example, live CDs often contain a \"Russian doll\" nest of
3232 filesystems, an ISO outer layer, with a squashfs image inside, with
3233 an ext2/3 image inside that.  You can unpack this as follows
3234 in guestfish:
3235
3236  add-ro Fedora-11-i686-Live.iso
3237  run
3238  mkmountpoint /cd
3239  mkmountpoint /squash
3240  mkmountpoint /ext3
3241  mount /dev/sda /cd
3242  mount-loop /cd/LiveOS/squashfs.img /squash
3243  mount-loop /squash/LiveOS/ext3fs.img /ext3
3244
3245 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3246
3247   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3248    [],
3249    "remove a mountpoint",
3250    "\
3251 This calls removes a mountpoint that was previously created
3252 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3253 for full details.");
3254
3255   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3256    [InitISOFS, Always, TestOutputBuffer (
3257       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3258    "read a file",
3259    "\
3260 This calls returns the contents of the file C<path> as a
3261 buffer.
3262
3263 Unlike C<guestfs_cat>, this function can correctly
3264 handle files that contain embedded ASCII NUL characters.
3265 However unlike C<guestfs_download>, this function is limited
3266 in the total size of file that can be handled.");
3267
3268   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3269    [InitISOFS, Always, TestOutputList (
3270       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3271     InitISOFS, Always, TestOutputList (
3272       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<grep> program and returns the
3276 matching lines.");
3277
3278   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<egrep> program and returns the
3284 matching lines.");
3285
3286   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<fgrep> program and returns the
3292 matching lines.");
3293
3294   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<grep -i> program and returns the
3300 matching lines.");
3301
3302   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<egrep -i> program and returns the
3308 matching lines.");
3309
3310   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<fgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zgrep> program and returns the
3324 matching lines.");
3325
3326   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zegrep> program and returns the
3332 matching lines.");
3333
3334   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3335    [InitISOFS, Always, TestOutputList (
3336       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3337    "return lines matching a pattern",
3338    "\
3339 This calls the external C<zfgrep> program and returns the
3340 matching lines.");
3341
3342   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3345    "return lines matching a pattern",
3346    "\
3347 This calls the external C<zgrep -i> program and returns the
3348 matching lines.");
3349
3350   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3351    [InitISOFS, Always, TestOutputList (
3352       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3353    "return lines matching a pattern",
3354    "\
3355 This calls the external C<zegrep -i> program and returns the
3356 matching lines.");
3357
3358   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3359    [InitISOFS, Always, TestOutputList (
3360       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3361    "return lines matching a pattern",
3362    "\
3363 This calls the external C<zfgrep -i> program and returns the
3364 matching lines.");
3365
3366   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3367    [InitISOFS, Always, TestOutput (
3368       [["realpath"; "/../directory"]], "/directory")],
3369    "canonicalized absolute pathname",
3370    "\
3371 Return the canonicalized absolute pathname of C<path>.  The
3372 returned path has no C<.>, C<..> or symbolic link path elements.");
3373
3374   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3375    [InitBasicFS, Always, TestOutputStruct (
3376       [["touch"; "/a"];
3377        ["ln"; "/a"; "/b"];
3378        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3379    "create a hard link",
3380    "\
3381 This command creates a hard link using the C<ln> command.");
3382
3383   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3384    [InitBasicFS, Always, TestOutputStruct (
3385       [["touch"; "/a"];
3386        ["touch"; "/b"];
3387        ["ln_f"; "/a"; "/b"];
3388        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3389    "create a hard link",
3390    "\
3391 This command creates a hard link using the C<ln -f> command.
3392 The C<-f> option removes the link (C<linkname>) if it exists already.");
3393
3394   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3395    [InitBasicFS, Always, TestOutputStruct (
3396       [["touch"; "/a"];
3397        ["ln_s"; "a"; "/b"];
3398        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3399    "create a symbolic link",
3400    "\
3401 This command creates a symbolic link using the C<ln -s> command.");
3402
3403   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3404    [InitBasicFS, Always, TestOutput (
3405       [["mkdir_p"; "/a/b"];
3406        ["touch"; "/a/b/c"];
3407        ["ln_sf"; "../d"; "/a/b/c"];
3408        ["readlink"; "/a/b/c"]], "../d")],
3409    "create a symbolic link",
3410    "\
3411 This command creates a symbolic link using the C<ln -sf> command,
3412 The C<-f> option removes the link (C<linkname>) if it exists already.");
3413
3414   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3415    [] (* XXX tested above *),
3416    "read the target of a symbolic link",
3417    "\
3418 This command reads the target of a symbolic link.");
3419
3420   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3421    [InitBasicFS, Always, TestOutputStruct (
3422       [["fallocate"; "/a"; "1000000"];
3423        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3424    "preallocate a file in the guest filesystem",
3425    "\
3426 This command preallocates a file (containing zero bytes) named
3427 C<path> of size C<len> bytes.  If the file exists already, it
3428 is overwritten.
3429
3430 Do not confuse this with the guestfish-specific
3431 C<alloc> command which allocates a file in the host and
3432 attaches it as a device.");
3433
3434   ("swapon_device", (RErr, [Device "device"]), 170, [],
3435    [InitPartition, Always, TestRun (
3436       [["mkswap"; "/dev/sda1"];
3437        ["swapon_device"; "/dev/sda1"];
3438        ["swapoff_device"; "/dev/sda1"]])],
3439    "enable swap on device",
3440    "\
3441 This command enables the libguestfs appliance to use the
3442 swap device or partition named C<device>.  The increased
3443 memory is made available for all commands, for example
3444 those run using C<guestfs_command> or C<guestfs_sh>.
3445
3446 Note that you should not swap to existing guest swap
3447 partitions unless you know what you are doing.  They may
3448 contain hibernation information, or other information that
3449 the guest doesn't want you to trash.  You also risk leaking
3450 information about the host to the guest this way.  Instead,
3451 attach a new host device to the guest and swap on that.");
3452
3453   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3454    [], (* XXX tested by swapon_device *)
3455    "disable swap on device",
3456    "\
3457 This command disables the libguestfs appliance swap
3458 device or partition named C<device>.
3459 See C<guestfs_swapon_device>.");
3460
3461   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3462    [InitBasicFS, Always, TestRun (
3463       [["fallocate"; "/swap"; "8388608"];
3464        ["mkswap_file"; "/swap"];
3465        ["swapon_file"; "/swap"];
3466        ["swapoff_file"; "/swap"]])],
3467    "enable swap on file",
3468    "\
3469 This command enables swap to a file.
3470 See C<guestfs_swapon_device> for other notes.");
3471
3472   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3473    [], (* XXX tested by swapon_file *)
3474    "disable swap on file",
3475    "\
3476 This command disables the libguestfs appliance swap on file.");
3477
3478   ("swapon_label", (RErr, [String "label"]), 174, [],
3479    [InitEmpty, Always, TestRun (
3480       [["part_disk"; "/dev/sdb"; "mbr"];
3481        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3482        ["swapon_label"; "swapit"];
3483        ["swapoff_label"; "swapit"];
3484        ["zero"; "/dev/sdb"];
3485        ["blockdev_rereadpt"; "/dev/sdb"]])],
3486    "enable swap on labeled swap partition",
3487    "\
3488 This command enables swap to a labeled swap partition.
3489 See C<guestfs_swapon_device> for other notes.");
3490
3491   ("swapoff_label", (RErr, [String "label"]), 175, [],
3492    [], (* XXX tested by swapon_label *)
3493    "disable swap on labeled swap partition",
3494    "\
3495 This command disables the libguestfs appliance swap on
3496 labeled swap partition.");
3497
3498   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3499    (let uuid = uuidgen () in
3500     [InitEmpty, Always, TestRun (
3501        [["mkswap_U"; uuid; "/dev/sdb"];
3502         ["swapon_uuid"; uuid];
3503         ["swapoff_uuid"; uuid]])]),
3504    "enable swap on swap partition by UUID",
3505    "\
3506 This command enables swap to a swap partition with the given UUID.
3507 See C<guestfs_swapon_device> for other notes.");
3508
3509   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3510    [], (* XXX tested by swapon_uuid *)
3511    "disable swap on swap partition by UUID",
3512    "\
3513 This command disables the libguestfs appliance swap partition
3514 with the given UUID.");
3515
3516   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3517    [InitBasicFS, Always, TestRun (
3518       [["fallocate"; "/swap"; "8388608"];
3519        ["mkswap_file"; "/swap"]])],
3520    "create a swap file",
3521    "\
3522 Create a swap file.
3523
3524 This command just writes a swap file signature to an existing
3525 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3526
3527   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3528    [InitISOFS, Always, TestRun (
3529       [["inotify_init"; "0"]])],
3530    "create an inotify handle",
3531    "\
3532 This command creates a new inotify handle.
3533 The inotify subsystem can be used to notify events which happen to
3534 objects in the guest filesystem.
3535
3536 C<maxevents> is the maximum number of events which will be
3537 queued up between calls to C<guestfs_inotify_read> or
3538 C<guestfs_inotify_files>.
3539 If this is passed as C<0>, then the kernel (or previously set)
3540 default is used.  For Linux 2.6.29 the default was 16384 events.
3541 Beyond this limit, the kernel throws away events, but records
3542 the fact that it threw them away by setting a flag
3543 C<IN_Q_OVERFLOW> in the returned structure list (see
3544 C<guestfs_inotify_read>).
3545
3546 Before any events are generated, you have to add some
3547 watches to the internal watch list.  See:
3548 C<guestfs_inotify_add_watch>,
3549 C<guestfs_inotify_rm_watch> and
3550 C<guestfs_inotify_watch_all>.
3551
3552 Queued up events should be read periodically by calling
3553 C<guestfs_inotify_read>
3554 (or C<guestfs_inotify_files> which is just a helpful
3555 wrapper around C<guestfs_inotify_read>).  If you don't
3556 read the events out often enough then you risk the internal
3557 queue overflowing.
3558
3559 The handle should be closed after use by calling
3560 C<guestfs_inotify_close>.  This also removes any
3561 watches automatically.
3562
3563 See also L<inotify(7)> for an overview of the inotify interface
3564 as exposed by the Linux kernel, which is roughly what we expose
3565 via libguestfs.  Note that there is one global inotify handle
3566 per libguestfs instance.");
3567
3568   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3569    [InitBasicFS, Always, TestOutputList (
3570       [["inotify_init"; "0"];
3571        ["inotify_add_watch"; "/"; "1073741823"];
3572        ["touch"; "/a"];
3573        ["touch"; "/b"];
3574        ["inotify_files"]], ["a"; "b"])],
3575    "add an inotify watch",
3576    "\
3577 Watch C<path> for the events listed in C<mask>.
3578
3579 Note that if C<path> is a directory then events within that
3580 directory are watched, but this does I<not> happen recursively
3581 (in subdirectories).
3582
3583 Note for non-C or non-Linux callers: the inotify events are
3584 defined by the Linux kernel ABI and are listed in
3585 C</usr/include/sys/inotify.h>.");
3586
3587   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3588    [],
3589    "remove an inotify watch",
3590    "\
3591 Remove a previously defined inotify watch.
3592 See C<guestfs_inotify_add_watch>.");
3593
3594   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3595    [],
3596    "return list of inotify events",
3597    "\
3598 Return the complete queue of events that have happened
3599 since the previous read call.
3600
3601 If no events have happened, this returns an empty list.
3602
3603 I<Note>: In order to make sure that all events have been
3604 read, you must call this function repeatedly until it
3605 returns an empty list.  The reason is that the call will
3606 read events up to the maximum appliance-to-host message
3607 size and leave remaining events in the queue.");
3608
3609   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3610    [],
3611    "return list of watched files that had events",
3612    "\
3613 This function is a helpful wrapper around C<guestfs_inotify_read>
3614 which just returns a list of pathnames of objects that were
3615 touched.  The returned pathnames are sorted and deduplicated.");
3616
3617   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3618    [],
3619    "close the inotify handle",
3620    "\
3621 This closes the inotify handle which was previously
3622 opened by inotify_init.  It removes all watches, throws
3623 away any pending events, and deallocates all resources.");
3624
3625   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3626    [],
3627    "set SELinux security context",
3628    "\
3629 This sets the SELinux security context of the daemon
3630 to the string C<context>.
3631
3632 See the documentation about SELINUX in L<guestfs(3)>.");
3633
3634   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3635    [],
3636    "get SELinux security context",
3637    "\
3638 This gets the SELinux security context of the daemon.
3639
3640 See the documentation about SELINUX in L<guestfs(3)>,
3641 and C<guestfs_setcon>");
3642
3643   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3644    [InitEmpty, Always, TestOutput (
3645       [["part_disk"; "/dev/sda"; "mbr"];
3646        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3647        ["mount_options"; ""; "/dev/sda1"; "/"];
3648        ["write_file"; "/new"; "new file contents"; "0"];
3649        ["cat"; "/new"]], "new file contents")],
3650    "make a filesystem with block size",
3651    "\
3652 This call is similar to C<guestfs_mkfs>, but it allows you to
3653 control the block size of the resulting filesystem.  Supported
3654 block sizes depend on the filesystem type, but typically they
3655 are C<1024>, C<2048> or C<4096> only.");
3656
3657   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3658    [InitEmpty, Always, TestOutput (
3659       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3660        ["mke2journal"; "4096"; "/dev/sda1"];
3661        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3662        ["mount_options"; ""; "/dev/sda2"; "/"];
3663        ["write_file"; "/new"; "new file contents"; "0"];
3664        ["cat"; "/new"]], "new file contents")],
3665    "make ext2/3/4 external journal",
3666    "\
3667 This creates an ext2 external journal on C<device>.  It is equivalent
3668 to the command:
3669
3670  mke2fs -O journal_dev -b blocksize device");
3671
3672   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3673    [InitEmpty, Always, TestOutput (
3674       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3675        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3676        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3677        ["mount_options"; ""; "/dev/sda2"; "/"];
3678        ["write_file"; "/new"; "new file contents"; "0"];
3679        ["cat"; "/new"]], "new file contents")],
3680    "make ext2/3/4 external journal with label",
3681    "\
3682 This creates an ext2 external journal on C<device> with label C<label>.");
3683
3684   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3685    (let uuid = uuidgen () in
3686     [InitEmpty, Always, TestOutput (
3687        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3688         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3689         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3690         ["mount_options"; ""; "/dev/sda2"; "/"];
3691         ["write_file"; "/new"; "new file contents"; "0"];
3692         ["cat"; "/new"]], "new file contents")]),
3693    "make ext2/3/4 external journal with UUID",
3694    "\
3695 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3696
3697   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3698    [],
3699    "make ext2/3/4 filesystem with external journal",
3700    "\
3701 This creates an ext2/3/4 filesystem on C<device> with
3702 an external journal on C<journal>.  It is equivalent
3703 to the command:
3704
3705  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3706
3707 See also C<guestfs_mke2journal>.");
3708
3709   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3710    [],
3711    "make ext2/3/4 filesystem with external journal",
3712    "\
3713 This creates an ext2/3/4 filesystem on C<device> with
3714 an external journal on the journal labeled C<label>.
3715
3716 See also C<guestfs_mke2journal_L>.");
3717
3718   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3719    [],
3720    "make ext2/3/4 filesystem with external journal",
3721    "\
3722 This creates an ext2/3/4 filesystem on C<device> with
3723 an external journal on the journal with UUID C<uuid>.
3724
3725 See also C<guestfs_mke2journal_U>.");
3726
3727   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3728    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3729    "load a kernel module",
3730    "\
3731 This loads a kernel module in the appliance.
3732
3733 The kernel module must have been whitelisted when libguestfs
3734 was built (see C<appliance/kmod.whitelist.in> in the source).");
3735
3736   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3737    [InitNone, Always, TestOutput (
3738       [["echo_daemon"; "This is a test"]], "This is a test"
3739     )],
3740    "echo arguments back to the client",
3741    "\
3742 This command concatenate the list of C<words> passed with single spaces between
3743 them and returns the resulting string.
3744
3745 You can use this command to test the connection through to the daemon.
3746
3747 See also C<guestfs_ping_daemon>.");
3748
3749   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3750    [], (* There is a regression test for this. *)
3751    "find all files and directories, returning NUL-separated list",
3752    "\
3753 This command lists out all files and directories, recursively,
3754 starting at C<directory>, placing the resulting list in the
3755 external file called C<files>.
3756
3757 This command works the same way as C<guestfs_find> with the
3758 following exceptions:
3759
3760 =over 4
3761
3762 =item *
3763
3764 The resulting list is written to an external file.
3765
3766 =item *
3767
3768 Items (filenames) in the result are separated
3769 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3770
3771 =item *
3772
3773 This command is not limited in the number of names that it
3774 can return.
3775
3776 =item *
3777
3778 The result list is not sorted.
3779
3780 =back");
3781
3782   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3783    [InitISOFS, Always, TestOutput (
3784       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3785     InitISOFS, Always, TestOutput (
3786       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3787     InitISOFS, Always, TestOutput (
3788       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3789     InitISOFS, Always, TestLastFail (
3790       [["case_sensitive_path"; "/Known-1/"]]);
3791     InitBasicFS, Always, TestOutput (
3792       [["mkdir"; "/a"];
3793        ["mkdir"; "/a/bbb"];
3794        ["touch"; "/a/bbb/c"];
3795        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3796     InitBasicFS, Always, TestOutput (
3797       [["mkdir"; "/a"];
3798        ["mkdir"; "/a/bbb"];
3799        ["touch"; "/a/bbb/c"];
3800        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3801     InitBasicFS, Always, TestLastFail (
3802       [["mkdir"; "/a"];
3803        ["mkdir"; "/a/bbb"];
3804        ["touch"; "/a/bbb/c"];
3805        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3806    "return true path on case-insensitive filesystem",
3807    "\
3808 This can be used to resolve case insensitive paths on
3809 a filesystem which is case sensitive.  The use case is
3810 to resolve paths which you have read from Windows configuration
3811 files or the Windows Registry, to the true path.
3812
3813 The command handles a peculiarity of the Linux ntfs-3g
3814 filesystem driver (and probably others), which is that although
3815 the underlying filesystem is case-insensitive, the driver
3816 exports the filesystem to Linux as case-sensitive.
3817
3818 One consequence of this is that special directories such
3819 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3820 (or other things) depending on the precise details of how
3821 they were created.  In Windows itself this would not be
3822 a problem.
3823
3824 Bug or feature?  You decide:
3825 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3826
3827 This function resolves the true case of each element in the
3828 path and returns the case-sensitive path.
3829
3830 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3831 might return C<\"/WINDOWS/system32\"> (the exact return value
3832 would depend on details of how the directories were originally
3833 created under Windows).
3834
3835 I<Note>:
3836 This function does not handle drive names, backslashes etc.
3837
3838 See also C<guestfs_realpath>.");
3839
3840   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3841    [InitBasicFS, Always, TestOutput (
3842       [["vfs_type"; "/dev/sda1"]], "ext2")],
3843    "get the Linux VFS type corresponding to a mounted device",
3844    "\
3845 This command gets the block device type corresponding to
3846 a mounted device called C<device>.
3847
3848 Usually the result is the name of the Linux VFS module that
3849 is used to mount this device (probably determined automatically
3850 if you used the C<guestfs_mount> call).");
3851
3852   ("truncate", (RErr, [Pathname "path"]), 199, [],
3853    [InitBasicFS, Always, TestOutputStruct (
3854       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3855        ["truncate"; "/test"];
3856        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3857    "truncate a file to zero size",
3858    "\
3859 This command truncates C<path> to a zero-length file.  The
3860 file must exist already.");
3861
3862   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3863    [InitBasicFS, Always, TestOutputStruct (
3864       [["touch"; "/test"];
3865        ["truncate_size"; "/test"; "1000"];
3866        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3867    "truncate a file to a particular size",
3868    "\
3869 This command truncates C<path> to size C<size> bytes.  The file
3870 must exist already.  If the file is smaller than C<size> then
3871 the file is extended to the required size with null bytes.");
3872
3873   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3874    [InitBasicFS, Always, TestOutputStruct (
3875       [["touch"; "/test"];
3876        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3877        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3878    "set timestamp of a file with nanosecond precision",
3879    "\
3880 This command sets the timestamps of a file with nanosecond
3881 precision.
3882
3883 C<atsecs, atnsecs> are the last access time (atime) in secs and
3884 nanoseconds from the epoch.
3885
3886 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3887 secs and nanoseconds from the epoch.
3888
3889 If the C<*nsecs> field contains the special value C<-1> then
3890 the corresponding timestamp is set to the current time.  (The
3891 C<*secs> field is ignored in this case).
3892
3893 If the C<*nsecs> field contains the special value C<-2> then
3894 the corresponding timestamp is left unchanged.  (The
3895 C<*secs> field is ignored in this case).");
3896
3897   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3898    [InitBasicFS, Always, TestOutputStruct (
3899       [["mkdir_mode"; "/test"; "0o111"];
3900        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3901    "create a directory with a particular mode",
3902    "\
3903 This command creates a directory, setting the initial permissions
3904 of the directory to C<mode>.
3905
3906 For common Linux filesystems, the actual mode which is set will
3907 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3908 interpret the mode in other ways.
3909
3910 See also C<guestfs_mkdir>, C<guestfs_umask>");
3911
3912   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3913    [], (* XXX *)
3914    "change file owner and group",
3915    "\
3916 Change the file owner to C<owner> and group to C<group>.
3917 This is like C<guestfs_chown> but if C<path> is a symlink then
3918 the link itself is changed, not the target.
3919
3920 Only numeric uid and gid are supported.  If you want to use
3921 names, you will need to locate and parse the password file
3922 yourself (Augeas support makes this relatively easy).");
3923
3924   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3925    [], (* XXX *)
3926    "lstat on multiple files",
3927    "\
3928 This call allows you to perform the C<guestfs_lstat> operation
3929 on multiple files, where all files are in the directory C<path>.
3930 C<names> is the list of files from this directory.
3931
3932 On return you get a list of stat structs, with a one-to-one
3933 correspondence to the C<names> list.  If any name did not exist
3934 or could not be lstat'd, then the C<ino> field of that structure
3935 is set to C<-1>.
3936
3937 This call is intended for programs that want to efficiently
3938 list a directory contents without making many round-trips.
3939 See also C<guestfs_lxattrlist> for a similarly efficient call
3940 for getting extended attributes.  Very long directory listings
3941 might cause the protocol message size to be exceeded, causing
3942 this call to fail.  The caller must split up such requests
3943 into smaller groups of names.");
3944
3945   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3946    [], (* XXX *)
3947    "lgetxattr on multiple files",
3948    "\
3949 This call allows you to get the extended attributes
3950 of multiple files, where all files are in the directory C<path>.
3951 C<names> is the list of files from this directory.
3952
3953 On return you get a flat list of xattr structs which must be
3954 interpreted sequentially.  The first xattr struct always has a zero-length
3955 C<attrname>.  C<attrval> in this struct is zero-length
3956 to indicate there was an error doing C<lgetxattr> for this
3957 file, I<or> is a C string which is a decimal number
3958 (the number of following attributes for this file, which could
3959 be C<\"0\">).  Then after the first xattr struct are the
3960 zero or more attributes for the first named file.
3961 This repeats for the second and subsequent files.
3962
3963 This call is intended for programs that want to efficiently
3964 list a directory contents without making many round-trips.
3965 See also C<guestfs_lstatlist> for a similarly efficient call
3966 for getting standard stats.  Very long directory listings
3967 might cause the protocol message size to be exceeded, causing
3968 this call to fail.  The caller must split up such requests
3969 into smaller groups of names.");
3970
3971   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3972    [], (* XXX *)
3973    "readlink on multiple files",
3974    "\
3975 This call allows you to do a C<readlink> operation
3976 on multiple files, where all files are in the directory C<path>.
3977 C<names> is the list of files from this directory.
3978
3979 On return you get a list of strings, with a one-to-one
3980 correspondence to the C<names> list.  Each string is the
3981 value of the symbol link.
3982
3983 If the C<readlink(2)> operation fails on any name, then
3984 the corresponding result string is the empty string C<\"\">.
3985 However the whole operation is completed even if there
3986 were C<readlink(2)> errors, and so you can call this
3987 function with names where you don't know if they are
3988 symbolic links already (albeit slightly less efficient).
3989
3990 This call is intended for programs that want to efficiently
3991 list a directory contents without making many round-trips.
3992 Very long directory listings might cause the protocol
3993 message size to be exceeded, causing
3994 this call to fail.  The caller must split up such requests
3995 into smaller groups of names.");
3996
3997   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3998    [InitISOFS, Always, TestOutputBuffer (
3999       [["pread"; "/known-4"; "1"; "3"]], "\n");
4000     InitISOFS, Always, TestOutputBuffer (
4001       [["pread"; "/empty"; "0"; "100"]], "")],
4002    "read part of a file",
4003    "\
4004 This command lets you read part of a file.  It reads C<count>
4005 bytes of the file, starting at C<offset>, from file C<path>.
4006
4007 This may read fewer bytes than requested.  For further details
4008 see the L<pread(2)> system call.");
4009
4010   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4011    [InitEmpty, Always, TestRun (
4012       [["part_init"; "/dev/sda"; "gpt"]])],
4013    "create an empty partition table",
4014    "\
4015 This creates an empty partition table on C<device> of one of the
4016 partition types listed below.  Usually C<parttype> should be
4017 either C<msdos> or C<gpt> (for large disks).
4018
4019 Initially there are no partitions.  Following this, you should
4020 call C<guestfs_part_add> for each partition required.
4021
4022 Possible values for C<parttype> are:
4023
4024 =over 4
4025
4026 =item B<efi> | B<gpt>
4027
4028 Intel EFI / GPT partition table.
4029
4030 This is recommended for >= 2 TB partitions that will be accessed
4031 from Linux and Intel-based Mac OS X.  It also has limited backwards
4032 compatibility with the C<mbr> format.
4033
4034 =item B<mbr> | B<msdos>
4035
4036 The standard PC \"Master Boot Record\" (MBR) format used
4037 by MS-DOS and Windows.  This partition type will B<only> work
4038 for device sizes up to 2 TB.  For large disks we recommend
4039 using C<gpt>.
4040
4041 =back
4042
4043 Other partition table types that may work but are not
4044 supported include:
4045
4046 =over 4
4047
4048 =item B<aix>
4049
4050 AIX disk labels.
4051
4052 =item B<amiga> | B<rdb>
4053
4054 Amiga \"Rigid Disk Block\" format.
4055
4056 =item B<bsd>
4057
4058 BSD disk labels.
4059
4060 =item B<dasd>
4061
4062 DASD, used on IBM mainframes.
4063
4064 =item B<dvh>
4065
4066 MIPS/SGI volumes.
4067
4068 =item B<mac>
4069
4070 Old Mac partition format.  Modern Macs use C<gpt>.
4071
4072 =item B<pc98>
4073
4074 NEC PC-98 format, common in Japan apparently.
4075
4076 =item B<sun>
4077
4078 Sun disk labels.
4079
4080 =back");
4081
4082   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4083    [InitEmpty, Always, TestRun (
4084       [["part_init"; "/dev/sda"; "mbr"];
4085        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4086     InitEmpty, Always, TestRun (
4087       [["part_init"; "/dev/sda"; "gpt"];
4088        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4089        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4090     InitEmpty, Always, TestRun (
4091       [["part_init"; "/dev/sda"; "mbr"];
4092        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4093        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4094        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4095        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4096    "add a partition to the device",
4097    "\
4098 This command adds a partition to C<device>.  If there is no partition
4099 table on the device, call C<guestfs_part_init> first.
4100
4101 The C<prlogex> parameter is the type of partition.  Normally you
4102 should pass C<p> or C<primary> here, but MBR partition tables also
4103 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4104 types.
4105
4106 C<startsect> and C<endsect> are the start and end of the partition
4107 in I<sectors>.  C<endsect> may be negative, which means it counts
4108 backwards from the end of the disk (C<-1> is the last sector).
4109
4110 Creating a partition which covers the whole disk is not so easy.
4111 Use C<guestfs_part_disk> to do that.");
4112
4113   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4114    [InitEmpty, Always, TestRun (
4115       [["part_disk"; "/dev/sda"; "mbr"]]);
4116     InitEmpty, Always, TestRun (
4117       [["part_disk"; "/dev/sda"; "gpt"]])],
4118    "partition whole disk with a single primary partition",
4119    "\
4120 This command is simply a combination of C<guestfs_part_init>
4121 followed by C<guestfs_part_add> to create a single primary partition
4122 covering the whole disk.
4123
4124 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4125 but other possible values are described in C<guestfs_part_init>.");
4126
4127   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4128    [InitEmpty, Always, TestRun (
4129       [["part_disk"; "/dev/sda"; "mbr"];
4130        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4131    "make a partition bootable",
4132    "\
4133 This sets the bootable flag on partition numbered C<partnum> on
4134 device C<device>.  Note that partitions are numbered from 1.
4135
4136 The bootable flag is used by some operating systems (notably
4137 Windows) to determine which partition to boot from.  It is by
4138 no means universally recognized.");
4139
4140   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4141    [InitEmpty, Always, TestRun (
4142       [["part_disk"; "/dev/sda"; "gpt"];
4143        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4144    "set partition name",
4145    "\
4146 This sets the partition name on partition numbered C<partnum> on
4147 device C<device>.  Note that partitions are numbered from 1.
4148
4149 The partition name can only be set on certain types of partition
4150 table.  This works on C<gpt> but not on C<mbr> partitions.");
4151
4152   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4153    [], (* XXX Add a regression test for this. *)
4154    "list partitions on a device",
4155    "\
4156 This command parses the partition table on C<device> and
4157 returns the list of partitions found.
4158
4159 The fields in the returned structure are:
4160
4161 =over 4
4162
4163 =item B<part_num>
4164
4165 Partition number, counting from 1.
4166
4167 =item B<part_start>
4168
4169 Start of the partition I<in bytes>.  To get sectors you have to
4170 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4171
4172 =item B<part_end>
4173
4174 End of the partition in bytes.
4175
4176 =item B<part_size>
4177
4178 Size of the partition in bytes.
4179
4180 =back");
4181
4182   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4183    [InitEmpty, Always, TestOutput (
4184       [["part_disk"; "/dev/sda"; "gpt"];
4185        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4186    "get the partition table type",
4187    "\
4188 This command examines the partition table on C<device> and
4189 returns the partition table type (format) being used.
4190
4191 Common return values include: C<msdos> (a DOS/Windows style MBR
4192 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4193 values are possible, although unusual.  See C<guestfs_part_init>
4194 for a full list.");
4195
4196   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4197    [InitBasicFS, Always, TestOutputBuffer (
4198       [["fill"; "0x63"; "10"; "/test"];
4199        ["read_file"; "/test"]], "cccccccccc")],
4200    "fill a file with octets",
4201    "\
4202 This command creates a new file called C<path>.  The initial
4203 content of the file is C<len> octets of C<c>, where C<c>
4204 must be a number in the range C<[0..255]>.
4205
4206 To fill a file with zero bytes (sparsely), it is
4207 much more efficient to use C<guestfs_truncate_size>.");
4208
4209   ("available", (RErr, [StringList "groups"]), 216, [],
4210    [InitNone, Always, TestRun [["available"; ""]]],
4211    "test availability of some parts of the API",
4212    "\
4213 This command is used to check the availability of some
4214 groups of functionality in the appliance, which not all builds of
4215 the libguestfs appliance will be able to provide.
4216
4217 The libguestfs groups, and the functions that those
4218 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4219
4220 The argument C<groups> is a list of group names, eg:
4221 C<[\"inotify\", \"augeas\"]> would check for the availability of
4222 the Linux inotify functions and Augeas (configuration file
4223 editing) functions.
4224
4225 The command returns no error if I<all> requested groups are available.
4226
4227 It fails with an error if one or more of the requested
4228 groups is unavailable in the appliance.
4229
4230 If an unknown group name is included in the
4231 list of groups then an error is always returned.
4232
4233 I<Notes:>
4234
4235 =over 4
4236
4237 =item *
4238
4239 You must call C<guestfs_launch> before calling this function.
4240
4241 The reason is because we don't know what groups are
4242 supported by the appliance/daemon until it is running and can
4243 be queried.
4244
4245 =item *
4246
4247 If a group of functions is available, this does not necessarily
4248 mean that they will work.  You still have to check for errors
4249 when calling individual API functions even if they are
4250 available.
4251
4252 =item *
4253
4254 It is usually the job of distro packagers to build
4255 complete functionality into the libguestfs appliance.
4256 Upstream libguestfs, if built from source with all
4257 requirements satisfied, will support everything.
4258
4259 =item *
4260
4261 This call was added in version C<1.0.80>.  In previous
4262 versions of libguestfs all you could do would be to speculatively
4263 execute a command to find out if the daemon implemented it.
4264 See also C<guestfs_version>.
4265
4266 =back");
4267
4268   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4269    [InitBasicFS, Always, TestOutputBuffer (
4270       [["write_file"; "/src"; "hello, world"; "0"];
4271        ["dd"; "/src"; "/dest"];
4272        ["read_file"; "/dest"]], "hello, world")],
4273    "copy from source to destination using dd",
4274    "\
4275 This command copies from one source device or file C<src>
4276 to another destination device or file C<dest>.  Normally you
4277 would use this to copy to or from a device or partition, for
4278 example to duplicate a filesystem.
4279
4280 If the destination is a device, it must be as large or larger
4281 than the source file or device, otherwise the copy will fail.
4282 This command cannot do partial copies (see C<guestfs_copy_size>).");
4283
4284   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4285    [InitBasicFS, Always, TestOutputInt (
4286       [["write_file"; "/file"; "hello, world"; "0"];
4287        ["filesize"; "/file"]], 12)],
4288    "return the size of the file in bytes",
4289    "\
4290 This command returns the size of C<file> in bytes.
4291
4292 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4293 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4294 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4295
4296   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4297    [InitBasicFSonLVM, Always, TestOutputList (
4298       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4299        ["lvs"]], ["/dev/VG/LV2"])],
4300    "rename an LVM logical volume",
4301    "\
4302 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4303
4304   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4305    [InitBasicFSonLVM, Always, TestOutputList (
4306       [["umount"; "/"];
4307        ["vg_activate"; "false"; "VG"];
4308        ["vgrename"; "VG"; "VG2"];
4309        ["vg_activate"; "true"; "VG2"];
4310        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4311        ["vgs"]], ["VG2"])],
4312    "rename an LVM volume group",
4313    "\
4314 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4315
4316   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4317    [InitISOFS, Always, TestOutputBuffer (
4318       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4319    "list the contents of a single file in an initrd",
4320    "\
4321 This command unpacks the file C<filename> from the initrd file
4322 called C<initrdpath>.  The filename must be given I<without> the
4323 initial C</> character.
4324
4325 For example, in guestfish you could use the following command
4326 to examine the boot script (usually called C</init>)
4327 contained in a Linux initrd or initramfs image:
4328
4329  initrd-cat /boot/initrd-<version>.img init
4330
4331 See also C<guestfs_initrd_list>.");
4332
4333   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4334    [],
4335    "get the UUID of a physical volume",
4336    "\
4337 This command returns the UUID of the LVM PV C<device>.");
4338
4339   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4340    [],
4341    "get the UUID of a volume group",
4342    "\
4343 This command returns the UUID of the LVM VG named C<vgname>.");
4344
4345   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4346    [],
4347    "get the UUID of a logical volume",
4348    "\
4349 This command returns the UUID of the LVM LV C<device>.");
4350
4351   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4352    [],
4353    "get the PV UUIDs containing the volume group",
4354    "\
4355 Given a VG called C<vgname>, this returns the UUIDs of all
4356 the physical volumes that this volume group resides on.
4357
4358 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4359 calls to associate physical volumes and volume groups.
4360
4361 See also C<guestfs_vglvuuids>.");
4362
4363   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4364    [],
4365    "get the LV UUIDs of all LVs in the volume group",
4366    "\
4367 Given a VG called C<vgname>, this returns the UUIDs of all
4368 the logical volumes created in this volume group.
4369
4370 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4371 calls to associate logical volumes and volume groups.
4372
4373 See also C<guestfs_vgpvuuids>.");
4374
4375   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4376    [InitBasicFS, Always, TestOutputBuffer (
4377       [["write_file"; "/src"; "hello, world"; "0"];
4378        ["copy_size"; "/src"; "/dest"; "5"];
4379        ["read_file"; "/dest"]], "hello")],
4380    "copy size bytes from source to destination using dd",
4381    "\
4382 This command copies exactly C<size> bytes from one source device
4383 or file C<src> to another destination device or file C<dest>.
4384
4385 Note this will fail if the source is too short or if the destination
4386 is not large enough.");
4387
4388   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4389    [InitBasicFSonLVM, Always, TestRun (
4390       [["zero_device"; "/dev/VG/LV"]])],
4391    "write zeroes to an entire device",
4392    "\
4393 This command writes zeroes over the entire C<device>.  Compare
4394 with C<guestfs_zero> which just zeroes the first few blocks of
4395 a device.");
4396
4397   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4398    [InitBasicFS, Always, TestOutput (
4399       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4400        ["cat"; "/hello"]], "hello\n")],
4401    "unpack compressed tarball to directory",
4402    "\
4403 This command uploads and unpacks local file C<tarball> (an
4404 I<xz compressed> tar file) into C<directory>.");
4405
4406   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4407    [],
4408    "pack directory into compressed tarball",
4409    "\
4410 This command packs the contents of C<directory> and downloads
4411 it to local file C<tarball> (as an xz compressed tar archive).");
4412
4413   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4414    [],
4415    "resize an NTFS filesystem",
4416    "\
4417 This command resizes an NTFS filesystem, expanding or
4418 shrinking it to the size of the underlying device.
4419 See also L<ntfsresize(8)>.");
4420
4421   ("vgscan", (RErr, []), 232, [],
4422    [InitEmpty, Always, TestRun (
4423       [["vgscan"]])],
4424    "rescan for LVM physical volumes, volume groups and logical volumes",
4425    "\
4426 This rescans all block devices and rebuilds the list of LVM
4427 physical volumes, volume groups and logical volumes.");
4428
4429   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4430    [InitEmpty, Always, TestRun (
4431       [["part_init"; "/dev/sda"; "mbr"];
4432        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4433        ["part_del"; "/dev/sda"; "1"]])],
4434    "delete a partition",
4435    "\
4436 This command deletes the partition numbered C<partnum> on C<device>.
4437
4438 Note that in the case of MBR partitioning, deleting an
4439 extended partition also deletes any logical partitions
4440 it contains.");
4441
4442   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4443    [InitEmpty, Always, TestOutputTrue (
4444       [["part_init"; "/dev/sda"; "mbr"];
4445        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4446        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4447        ["part_get_bootable"; "/dev/sda"; "1"]])],
4448    "return true if a partition is bootable",
4449    "\
4450 This command returns true if the partition C<partnum> on
4451 C<device> has the bootable flag set.
4452
4453 See also C<guestfs_part_set_bootable>.");
4454
4455   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4456    [InitEmpty, Always, TestOutputInt (
4457       [["part_init"; "/dev/sda"; "mbr"];
4458        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4459        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4460        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4461    "get the MBR type byte (ID byte) from a partition",
4462    "\
4463 Returns the MBR type byte (also known as the ID byte) from
4464 the numbered partition C<partnum>.
4465
4466 Note that only MBR (old DOS-style) partitions have type bytes.
4467 You will get undefined results for other partition table
4468 types (see C<guestfs_part_get_parttype>).");
4469
4470   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4471    [], (* tested by part_get_mbr_id *)
4472    "set the MBR type byte (ID byte) of a partition",
4473    "\
4474 Sets the MBR type byte (also known as the ID byte) of
4475 the numbered partition C<partnum> to C<idbyte>.  Note
4476 that the type bytes quoted in most documentation are
4477 in fact hexadecimal numbers, but usually documented
4478 without any leading \"0x\" which might be confusing.
4479
4480 Note that only MBR (old DOS-style) partitions have type bytes.
4481 You will get undefined results for other partition table
4482 types (see C<guestfs_part_get_parttype>).");
4483
4484   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4485    [InitISOFS, Always, TestOutput (
4486       [["checksum_device"; "md5"; "/dev/sdd"]],
4487       (Digest.to_hex (Digest.file "images/test.iso")))],
4488    "compute MD5, SHAx or CRC checksum of the contents of a device",
4489    "\
4490 This call computes the MD5, SHAx or CRC checksum of the
4491 contents of the device named C<device>.  For the types of
4492 checksums supported see the C<guestfs_checksum> command.");
4493
4494   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4495    [InitNone, Always, TestRun (
4496       [["part_disk"; "/dev/sda"; "mbr"];
4497        ["pvcreate"; "/dev/sda1"];
4498        ["vgcreate"; "VG"; "/dev/sda1"];
4499        ["lvcreate"; "LV"; "VG"; "10"];
4500        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4501    "expand an LV to fill free space",
4502    "\
4503 This expands an existing logical volume C<lv> so that it fills
4504 C<pc>% of the remaining free space in the volume group.  Commonly
4505 you would call this with pc = 100 which expands the logical volume
4506 as much as possible, using all remaining free space in the volume
4507 group.");
4508
4509   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4510    [], (* XXX Augeas code needs tests. *)
4511    "clear Augeas path",
4512    "\
4513 Set the value associated with C<path> to C<NULL>.  This
4514 is the same as the L<augtool(1)> C<clear> command.");
4515
4516   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4517    [InitEmpty, Always, TestOutputInt (
4518       [["get_umask"]], 0o22)],
4519    "get the current umask",
4520    "\
4521 Return the current umask.  By default the umask is C<022>
4522 unless it has been set by calling C<guestfs_umask>.");
4523
4524   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4525    [],
4526    "upload a file to the appliance (internal use only)",
4527    "\
4528 The C<guestfs_debug_upload> command uploads a file to
4529 the libguestfs appliance.
4530
4531 There is no comprehensive help for this command.  You have
4532 to look at the file C<daemon/debug.c> in the libguestfs source
4533 to find out what it is for.");
4534
4535   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4536    [InitBasicFS, Always, TestOutput (
4537       [["base64_in"; "../images/hello.b64"; "/hello"];
4538        ["cat"; "/hello"]], "hello\n")],
4539    "upload base64-encoded data to file",
4540    "\
4541 This command uploads base64-encoded data from C<base64file>
4542 to C<filename>.");
4543
4544   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4545    [],
4546    "download file and encode as base64",
4547    "\
4548 This command downloads the contents of C<filename>, writing
4549 it out to local file C<base64file> encoded as base64.");
4550
4551   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4552    [],
4553    "compute MD5, SHAx or CRC checksum of files in a directory",
4554    "\
4555 This command computes the checksums of all regular files in
4556 C<directory> and then emits a list of those checksums to
4557 the local output file C<sumsfile>.
4558
4559 This can be used for verifying the integrity of a virtual
4560 machine.  However to be properly secure you should pay
4561 attention to the output of the checksum command (it uses
4562 the ones from GNU coreutils).  In particular when the
4563 filename is not printable, coreutils uses a special
4564 backslash syntax.  For more information, see the GNU
4565 coreutils info file.");
4566
4567 ]
4568
4569 let all_functions = non_daemon_functions @ daemon_functions
4570
4571 (* In some places we want the functions to be displayed sorted
4572  * alphabetically, so this is useful:
4573  *)
4574 let all_functions_sorted =
4575   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4576                compare n1 n2) all_functions
4577
4578 (* Field types for structures. *)
4579 type field =
4580   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4581   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4582   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4583   | FUInt32
4584   | FInt32
4585   | FUInt64
4586   | FInt64
4587   | FBytes                      (* Any int measure that counts bytes. *)
4588   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4589   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4590
4591 (* Because we generate extra parsing code for LVM command line tools,
4592  * we have to pull out the LVM columns separately here.
4593  *)
4594 let lvm_pv_cols = [
4595   "pv_name", FString;
4596   "pv_uuid", FUUID;
4597   "pv_fmt", FString;
4598   "pv_size", FBytes;
4599   "dev_size", FBytes;
4600   "pv_free", FBytes;
4601   "pv_used", FBytes;
4602   "pv_attr", FString (* XXX *);
4603   "pv_pe_count", FInt64;
4604   "pv_pe_alloc_count", FInt64;
4605   "pv_tags", FString;
4606   "pe_start", FBytes;
4607   "pv_mda_count", FInt64;
4608   "pv_mda_free", FBytes;
4609   (* Not in Fedora 10:
4610      "pv_mda_size", FBytes;
4611   *)
4612 ]
4613 let lvm_vg_cols = [
4614   "vg_name", FString;
4615   "vg_uuid", FUUID;
4616   "vg_fmt", FString;
4617   "vg_attr", FString (* XXX *);
4618   "vg_size", FBytes;
4619   "vg_free", FBytes;
4620   "vg_sysid", FString;
4621   "vg_extent_size", FBytes;
4622   "vg_extent_count", FInt64;
4623   "vg_free_count", FInt64;
4624   "max_lv", FInt64;
4625   "max_pv", FInt64;
4626   "pv_count", FInt64;
4627   "lv_count", FInt64;
4628   "snap_count", FInt64;
4629   "vg_seqno", FInt64;
4630   "vg_tags", FString;
4631   "vg_mda_count", FInt64;
4632   "vg_mda_free", FBytes;
4633   (* Not in Fedora 10:
4634      "vg_mda_size", FBytes;
4635   *)
4636 ]
4637 let lvm_lv_cols = [
4638   "lv_name", FString;
4639   "lv_uuid", FUUID;
4640   "lv_attr", FString (* XXX *);
4641   "lv_major", FInt64;
4642   "lv_minor", FInt64;
4643   "lv_kernel_major", FInt64;
4644   "lv_kernel_minor", FInt64;
4645   "lv_size", FBytes;
4646   "seg_count", FInt64;
4647   "origin", FString;
4648   "snap_percent", FOptPercent;
4649   "copy_percent", FOptPercent;
4650   "move_pv", FString;
4651   "lv_tags", FString;
4652   "mirror_log", FString;
4653   "modules", FString;
4654 ]
4655
4656 (* Names and fields in all structures (in RStruct and RStructList)
4657  * that we support.
4658  *)
4659 let structs = [
4660   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4661    * not use this struct in any new code.
4662    *)
4663   "int_bool", [
4664     "i", FInt32;                (* for historical compatibility *)
4665     "b", FInt32;                (* for historical compatibility *)
4666   ];
4667
4668   (* LVM PVs, VGs, LVs. *)
4669   "lvm_pv", lvm_pv_cols;
4670   "lvm_vg", lvm_vg_cols;
4671   "lvm_lv", lvm_lv_cols;
4672
4673   (* Column names and types from stat structures.
4674    * NB. Can't use things like 'st_atime' because glibc header files
4675    * define some of these as macros.  Ugh.
4676    *)
4677   "stat", [
4678     "dev", FInt64;
4679     "ino", FInt64;
4680     "mode", FInt64;
4681     "nlink", FInt64;
4682     "uid", FInt64;
4683     "gid", FInt64;
4684     "rdev", FInt64;
4685     "size", FInt64;
4686     "blksize", FInt64;
4687     "blocks", FInt64;
4688     "atime", FInt64;
4689     "mtime", FInt64;
4690     "ctime", FInt64;
4691   ];
4692   "statvfs", [
4693     "bsize", FInt64;
4694     "frsize", FInt64;
4695     "blocks", FInt64;
4696     "bfree", FInt64;
4697     "bavail", FInt64;
4698     "files", FInt64;
4699     "ffree", FInt64;
4700     "favail", FInt64;
4701     "fsid", FInt64;
4702     "flag", FInt64;
4703     "namemax", FInt64;
4704   ];
4705
4706   (* Column names in dirent structure. *)
4707   "dirent", [
4708     "ino", FInt64;
4709     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4710     "ftyp", FChar;
4711     "name", FString;
4712   ];
4713
4714   (* Version numbers. *)
4715   "version", [
4716     "major", FInt64;
4717     "minor", FInt64;
4718     "release", FInt64;
4719     "extra", FString;
4720   ];
4721
4722   (* Extended attribute. *)
4723   "xattr", [
4724     "attrname", FString;
4725     "attrval", FBuffer;
4726   ];
4727
4728   (* Inotify events. *)
4729   "inotify_event", [
4730     "in_wd", FInt64;
4731     "in_mask", FUInt32;
4732     "in_cookie", FUInt32;
4733     "in_name", FString;
4734   ];
4735
4736   (* Partition table entry. *)
4737   "partition", [
4738     "part_num", FInt32;
4739     "part_start", FBytes;
4740     "part_end", FBytes;
4741     "part_size", FBytes;
4742   ];
4743 ] (* end of structs *)
4744
4745 (* Ugh, Java has to be different ..
4746  * These names are also used by the Haskell bindings.
4747  *)
4748 let java_structs = [
4749   "int_bool", "IntBool";
4750   "lvm_pv", "PV";
4751   "lvm_vg", "VG";
4752   "lvm_lv", "LV";
4753   "stat", "Stat";
4754   "statvfs", "StatVFS";
4755   "dirent", "Dirent";
4756   "version", "Version";
4757   "xattr", "XAttr";
4758   "inotify_event", "INotifyEvent";
4759   "partition", "Partition";
4760 ]
4761
4762 (* What structs are actually returned. *)
4763 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4764
4765 (* Returns a list of RStruct/RStructList structs that are returned
4766  * by any function.  Each element of returned list is a pair:
4767  *
4768  * (structname, RStructOnly)
4769  *    == there exists function which returns RStruct (_, structname)
4770  * (structname, RStructListOnly)
4771  *    == there exists function which returns RStructList (_, structname)
4772  * (structname, RStructAndList)
4773  *    == there are functions returning both RStruct (_, structname)
4774  *                                      and RStructList (_, structname)
4775  *)
4776 let rstructs_used_by functions =
4777   (* ||| is a "logical OR" for rstructs_used_t *)
4778   let (|||) a b =
4779     match a, b with
4780     | RStructAndList, _
4781     | _, RStructAndList -> RStructAndList
4782     | RStructOnly, RStructListOnly
4783     | RStructListOnly, RStructOnly -> RStructAndList
4784     | RStructOnly, RStructOnly -> RStructOnly
4785     | RStructListOnly, RStructListOnly -> RStructListOnly
4786   in
4787
4788   let h = Hashtbl.create 13 in
4789
4790   (* if elem->oldv exists, update entry using ||| operator,
4791    * else just add elem->newv to the hash
4792    *)
4793   let update elem newv =
4794     try  let oldv = Hashtbl.find h elem in
4795          Hashtbl.replace h elem (newv ||| oldv)
4796     with Not_found -> Hashtbl.add h elem newv
4797   in
4798
4799   List.iter (
4800     fun (_, style, _, _, _, _, _) ->
4801       match fst style with
4802       | RStruct (_, structname) -> update structname RStructOnly
4803       | RStructList (_, structname) -> update structname RStructListOnly
4804       | _ -> ()
4805   ) functions;
4806
4807   (* return key->values as a list of (key,value) *)
4808   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4809
4810 (* Used for testing language bindings. *)
4811 type callt =
4812   | CallString of string
4813   | CallOptString of string option
4814   | CallStringList of string list
4815   | CallInt of int
4816   | CallInt64 of int64
4817   | CallBool of bool
4818
4819 (* Used to memoize the result of pod2text. *)
4820 let pod2text_memo_filename = "src/.pod2text.data"
4821 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4822   try
4823     let chan = open_in pod2text_memo_filename in
4824     let v = input_value chan in
4825     close_in chan;
4826     v
4827   with
4828     _ -> Hashtbl.create 13
4829 let pod2text_memo_updated () =
4830   let chan = open_out pod2text_memo_filename in
4831   output_value chan pod2text_memo;
4832   close_out chan
4833
4834 (* Useful functions.
4835  * Note we don't want to use any external OCaml libraries which
4836  * makes this a bit harder than it should be.
4837  *)
4838 module StringMap = Map.Make (String)
4839
4840 let failwithf fs = ksprintf failwith fs
4841
4842 let unique = let i = ref 0 in fun () -> incr i; !i
4843
4844 let replace_char s c1 c2 =
4845   let s2 = String.copy s in
4846   let r = ref false in
4847   for i = 0 to String.length s2 - 1 do
4848     if String.unsafe_get s2 i = c1 then (
4849       String.unsafe_set s2 i c2;
4850       r := true
4851     )
4852   done;
4853   if not !r then s else s2
4854
4855 let isspace c =
4856   c = ' '
4857   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4858
4859 let triml ?(test = isspace) str =
4860   let i = ref 0 in
4861   let n = ref (String.length str) in
4862   while !n > 0 && test str.[!i]; do
4863     decr n;
4864     incr i
4865   done;
4866   if !i = 0 then str
4867   else String.sub str !i !n
4868
4869 let trimr ?(test = isspace) str =
4870   let n = ref (String.length str) in
4871   while !n > 0 && test str.[!n-1]; do
4872     decr n
4873   done;
4874   if !n = String.length str then str
4875   else String.sub str 0 !n
4876
4877 let trim ?(test = isspace) str =
4878   trimr ~test (triml ~test str)
4879
4880 let rec find s sub =
4881   let len = String.length s in
4882   let sublen = String.length sub in
4883   let rec loop i =
4884     if i <= len-sublen then (
4885       let rec loop2 j =
4886         if j < sublen then (
4887           if s.[i+j] = sub.[j] then loop2 (j+1)
4888           else -1
4889         ) else
4890           i (* found *)
4891       in
4892       let r = loop2 0 in
4893       if r = -1 then loop (i+1) else r
4894     ) else
4895       -1 (* not found *)
4896   in
4897   loop 0
4898
4899 let rec replace_str s s1 s2 =
4900   let len = String.length s in
4901   let sublen = String.length s1 in
4902   let i = find s s1 in
4903   if i = -1 then s
4904   else (
4905     let s' = String.sub s 0 i in
4906     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4907     s' ^ s2 ^ replace_str s'' s1 s2
4908   )
4909
4910 let rec string_split sep str =
4911   let len = String.length str in
4912   let seplen = String.length sep in
4913   let i = find str sep in
4914   if i = -1 then [str]
4915   else (
4916     let s' = String.sub str 0 i in
4917     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4918     s' :: string_split sep s''
4919   )
4920
4921 let files_equal n1 n2 =
4922   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4923   match Sys.command cmd with
4924   | 0 -> true
4925   | 1 -> false
4926   | i -> failwithf "%s: failed with error code %d" cmd i
4927
4928 let rec filter_map f = function
4929   | [] -> []
4930   | x :: xs ->
4931       match f x with
4932       | Some y -> y :: filter_map f xs
4933       | None -> filter_map f xs
4934
4935 let rec find_map f = function
4936   | [] -> raise Not_found
4937   | x :: xs ->
4938       match f x with
4939       | Some y -> y
4940       | None -> find_map f xs
4941
4942 let iteri f xs =
4943   let rec loop i = function
4944     | [] -> ()
4945     | x :: xs -> f i x; loop (i+1) xs
4946   in
4947   loop 0 xs
4948
4949 let mapi f xs =
4950   let rec loop i = function
4951     | [] -> []
4952     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4953   in
4954   loop 0 xs
4955
4956 let count_chars c str =
4957   let count = ref 0 in
4958   for i = 0 to String.length str - 1 do
4959     if c = String.unsafe_get str i then incr count
4960   done;
4961   !count
4962
4963 let name_of_argt = function
4964   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4965   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4966   | FileIn n | FileOut n -> n
4967
4968 let java_name_of_struct typ =
4969   try List.assoc typ java_structs
4970   with Not_found ->
4971     failwithf
4972       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4973
4974 let cols_of_struct typ =
4975   try List.assoc typ structs
4976   with Not_found ->
4977     failwithf "cols_of_struct: unknown struct %s" typ
4978
4979 let seq_of_test = function
4980   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4981   | TestOutputListOfDevices (s, _)
4982   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4983   | TestOutputTrue s | TestOutputFalse s
4984   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4985   | TestOutputStruct (s, _)
4986   | TestLastFail s -> s
4987
4988 (* Handling for function flags. *)
4989 let protocol_limit_warning =
4990   "Because of the message protocol, there is a transfer limit
4991 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4992
4993 let danger_will_robinson =
4994   "B<This command is dangerous.  Without careful use you
4995 can easily destroy all your data>."
4996
4997 let deprecation_notice flags =
4998   try
4999     let alt =
5000       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5001     let txt =
5002       sprintf "This function is deprecated.
5003 In new code, use the C<%s> call instead.
5004
5005 Deprecated functions will not be removed from the API, but the
5006 fact that they are deprecated indicates that there are problems
5007 with correct use of these functions." alt in
5008     Some txt
5009   with
5010     Not_found -> None
5011
5012 (* Create list of optional groups. *)
5013 let optgroups =
5014   let h = Hashtbl.create 13 in
5015   List.iter (
5016     fun (name, _, _, flags, _, _, _) ->
5017       List.iter (
5018         function
5019         | Optional group ->
5020             let names = try Hashtbl.find h group with Not_found -> [] in
5021             Hashtbl.replace h group (name :: names)
5022         | _ -> ()
5023       ) flags
5024   ) daemon_functions;
5025   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5026   let groups =
5027     List.map (
5028       fun group -> group, List.sort compare (Hashtbl.find h group)
5029     ) groups in
5030   List.sort (fun x y -> compare (fst x) (fst y)) groups
5031
5032 (* Check function names etc. for consistency. *)
5033 let check_functions () =
5034   let contains_uppercase str =
5035     let len = String.length str in
5036     let rec loop i =
5037       if i >= len then false
5038       else (
5039         let c = str.[i] in
5040         if c >= 'A' && c <= 'Z' then true
5041         else loop (i+1)
5042       )
5043     in
5044     loop 0
5045   in
5046
5047   (* Check function names. *)
5048   List.iter (
5049     fun (name, _, _, _, _, _, _) ->
5050       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5051         failwithf "function name %s does not need 'guestfs' prefix" name;
5052       if name = "" then
5053         failwithf "function name is empty";
5054       if name.[0] < 'a' || name.[0] > 'z' then
5055         failwithf "function name %s must start with lowercase a-z" name;
5056       if String.contains name '-' then
5057         failwithf "function name %s should not contain '-', use '_' instead."
5058           name
5059   ) all_functions;
5060
5061   (* Check function parameter/return names. *)
5062   List.iter (
5063     fun (name, style, _, _, _, _, _) ->
5064       let check_arg_ret_name n =
5065         if contains_uppercase n then
5066           failwithf "%s param/ret %s should not contain uppercase chars"
5067             name n;
5068         if String.contains n '-' || String.contains n '_' then
5069           failwithf "%s param/ret %s should not contain '-' or '_'"
5070             name n;
5071         if n = "value" then
5072           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;
5073         if n = "int" || n = "char" || n = "short" || n = "long" then
5074           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5075         if n = "i" || n = "n" then
5076           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5077         if n = "argv" || n = "args" then
5078           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5079
5080         (* List Haskell, OCaml and C keywords here.
5081          * http://www.haskell.org/haskellwiki/Keywords
5082          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5083          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5084          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5085          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5086          * Omitting _-containing words, since they're handled above.
5087          * Omitting the OCaml reserved word, "val", is ok,
5088          * and saves us from renaming several parameters.
5089          *)
5090         let reserved = [
5091           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5092           "char"; "class"; "const"; "constraint"; "continue"; "data";
5093           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5094           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5095           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5096           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5097           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5098           "interface";
5099           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5100           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5101           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5102           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5103           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5104           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5105           "volatile"; "when"; "where"; "while";
5106           ] in
5107         if List.mem n reserved then
5108           failwithf "%s has param/ret using reserved word %s" name n;
5109       in
5110
5111       (match fst style with
5112        | RErr -> ()
5113        | RInt n | RInt64 n | RBool n
5114        | RConstString n | RConstOptString n | RString n
5115        | RStringList n | RStruct (n, _) | RStructList (n, _)
5116        | RHashtable n | RBufferOut n ->
5117            check_arg_ret_name n
5118       );
5119       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5120   ) all_functions;
5121
5122   (* Check short descriptions. *)
5123   List.iter (
5124     fun (name, _, _, _, _, shortdesc, _) ->
5125       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5126         failwithf "short description of %s should begin with lowercase." name;
5127       let c = shortdesc.[String.length shortdesc-1] in
5128       if c = '\n' || c = '.' then
5129         failwithf "short description of %s should not end with . or \\n." name
5130   ) all_functions;
5131
5132   (* Check long descriptions. *)
5133   List.iter (
5134     fun (name, _, _, _, _, _, longdesc) ->
5135       if longdesc.[String.length longdesc-1] = '\n' then
5136         failwithf "long description of %s should not end with \\n." name
5137   ) all_functions;
5138
5139   (* Check proc_nrs. *)
5140   List.iter (
5141     fun (name, _, proc_nr, _, _, _, _) ->
5142       if proc_nr <= 0 then
5143         failwithf "daemon function %s should have proc_nr > 0" name
5144   ) daemon_functions;
5145
5146   List.iter (
5147     fun (name, _, proc_nr, _, _, _, _) ->
5148       if proc_nr <> -1 then
5149         failwithf "non-daemon function %s should have proc_nr -1" name
5150   ) non_daemon_functions;
5151
5152   let proc_nrs =
5153     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5154       daemon_functions in
5155   let proc_nrs =
5156     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5157   let rec loop = function
5158     | [] -> ()
5159     | [_] -> ()
5160     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5161         loop rest
5162     | (name1,nr1) :: (name2,nr2) :: _ ->
5163         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5164           name1 name2 nr1 nr2
5165   in
5166   loop proc_nrs;
5167
5168   (* Check tests. *)
5169   List.iter (
5170     function
5171       (* Ignore functions that have no tests.  We generate a
5172        * warning when the user does 'make check' instead.
5173        *)
5174     | name, _, _, _, [], _, _ -> ()
5175     | name, _, _, _, tests, _, _ ->
5176         let funcs =
5177           List.map (
5178             fun (_, _, test) ->
5179               match seq_of_test test with
5180               | [] ->
5181                   failwithf "%s has a test containing an empty sequence" name
5182               | cmds -> List.map List.hd cmds
5183           ) tests in
5184         let funcs = List.flatten funcs in
5185
5186         let tested = List.mem name funcs in
5187
5188         if not tested then
5189           failwithf "function %s has tests but does not test itself" name
5190   ) all_functions
5191
5192 (* 'pr' prints to the current output file. *)
5193 let chan = ref Pervasives.stdout
5194 let lines = ref 0
5195 let pr fs =
5196   ksprintf
5197     (fun str ->
5198        let i = count_chars '\n' str in
5199        lines := !lines + i;
5200        output_string !chan str
5201     ) fs
5202
5203 let copyright_years =
5204   let this_year = 1900 + (localtime (time ())).tm_year in
5205   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5206
5207 (* Generate a header block in a number of standard styles. *)
5208 type comment_style =
5209     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5210 type license = GPLv2plus | LGPLv2plus
5211
5212 let generate_header ?(extra_inputs = []) comment license =
5213   let inputs = "src/generator.ml" :: extra_inputs in
5214   let c = match comment with
5215     | CStyle ->         pr "/* "; " *"
5216     | CPlusPlusStyle -> pr "// "; "//"
5217     | HashStyle ->      pr "# ";  "#"
5218     | OCamlStyle ->     pr "(* "; " *"
5219     | HaskellStyle ->   pr "{- "; "  " in
5220   pr "libguestfs generated file\n";
5221   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5222   List.iter (pr "%s   %s\n" c) inputs;
5223   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5224   pr "%s\n" c;
5225   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5226   pr "%s\n" c;
5227   (match license with
5228    | GPLv2plus ->
5229        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5230        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5231        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5232        pr "%s (at your option) any later version.\n" c;
5233        pr "%s\n" c;
5234        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5235        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5236        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5237        pr "%s GNU General Public License for more details.\n" c;
5238        pr "%s\n" c;
5239        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5240        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5241        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5242
5243    | LGPLv2plus ->
5244        pr "%s This library is free software; you can redistribute it and/or\n" c;
5245        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5246        pr "%s License as published by the Free Software Foundation; either\n" c;
5247        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5248        pr "%s\n" c;
5249        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5250        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5251        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5252        pr "%s Lesser General Public License for more details.\n" c;
5253        pr "%s\n" c;
5254        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5255        pr "%s License along with this library; if not, write to the Free Software\n" c;
5256        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5257   );
5258   (match comment with
5259    | CStyle -> pr " */\n"
5260    | CPlusPlusStyle
5261    | HashStyle -> ()
5262    | OCamlStyle -> pr " *)\n"
5263    | HaskellStyle -> pr "-}\n"
5264   );
5265   pr "\n"
5266
5267 (* Start of main code generation functions below this line. *)
5268
5269 (* Generate the pod documentation for the C API. *)
5270 let rec generate_actions_pod () =
5271   List.iter (
5272     fun (shortname, style, _, flags, _, _, longdesc) ->
5273       if not (List.mem NotInDocs flags) then (
5274         let name = "guestfs_" ^ shortname in
5275         pr "=head2 %s\n\n" name;
5276         pr " ";
5277         generate_prototype ~extern:false ~handle:"g" name style;
5278         pr "\n\n";
5279         pr "%s\n\n" longdesc;
5280         (match fst style with
5281          | RErr ->
5282              pr "This function returns 0 on success or -1 on error.\n\n"
5283          | RInt _ ->
5284              pr "On error this function returns -1.\n\n"
5285          | RInt64 _ ->
5286              pr "On error this function returns -1.\n\n"
5287          | RBool _ ->
5288              pr "This function returns a C truth value on success or -1 on error.\n\n"
5289          | RConstString _ ->
5290              pr "This function returns a string, or NULL on error.
5291 The string is owned by the guest handle and must I<not> be freed.\n\n"
5292          | RConstOptString _ ->
5293              pr "This function returns a string which may be NULL.
5294 There is way to return an error from this function.
5295 The string is owned by the guest handle and must I<not> be freed.\n\n"
5296          | RString _ ->
5297              pr "This function returns a string, or NULL on error.
5298 I<The caller must free the returned string after use>.\n\n"
5299          | RStringList _ ->
5300              pr "This function returns a NULL-terminated array of strings
5301 (like L<environ(3)>), or NULL if there was an error.
5302 I<The caller must free the strings and the array after use>.\n\n"
5303          | RStruct (_, typ) ->
5304              pr "This function returns a C<struct guestfs_%s *>,
5305 or NULL if there was an error.
5306 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5307          | RStructList (_, typ) ->
5308              pr "This function returns a C<struct guestfs_%s_list *>
5309 (see E<lt>guestfs-structs.hE<gt>),
5310 or NULL if there was an error.
5311 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5312          | RHashtable _ ->
5313              pr "This function returns a NULL-terminated array of
5314 strings, or NULL if there was an error.
5315 The array of strings will always have length C<2n+1>, where
5316 C<n> keys and values alternate, followed by the trailing NULL entry.
5317 I<The caller must free the strings and the array after use>.\n\n"
5318          | RBufferOut _ ->
5319              pr "This function returns a buffer, or NULL on error.
5320 The size of the returned buffer is written to C<*size_r>.
5321 I<The caller must free the returned buffer after use>.\n\n"
5322         );
5323         if List.mem ProtocolLimitWarning flags then
5324           pr "%s\n\n" protocol_limit_warning;
5325         if List.mem DangerWillRobinson flags then
5326           pr "%s\n\n" danger_will_robinson;
5327         match deprecation_notice flags with
5328         | None -> ()
5329         | Some txt -> pr "%s\n\n" txt
5330       )
5331   ) all_functions_sorted
5332
5333 and generate_structs_pod () =
5334   (* Structs documentation. *)
5335   List.iter (
5336     fun (typ, cols) ->
5337       pr "=head2 guestfs_%s\n" typ;
5338       pr "\n";
5339       pr " struct guestfs_%s {\n" typ;
5340       List.iter (
5341         function
5342         | name, FChar -> pr "   char %s;\n" name
5343         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5344         | name, FInt32 -> pr "   int32_t %s;\n" name
5345         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5346         | name, FInt64 -> pr "   int64_t %s;\n" name
5347         | name, FString -> pr "   char *%s;\n" name
5348         | name, FBuffer ->
5349             pr "   /* The next two fields describe a byte array. */\n";
5350             pr "   uint32_t %s_len;\n" name;
5351             pr "   char *%s;\n" name
5352         | name, FUUID ->
5353             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5354             pr "   char %s[32];\n" name
5355         | name, FOptPercent ->
5356             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5357             pr "   float %s;\n" name
5358       ) cols;
5359       pr " };\n";
5360       pr " \n";
5361       pr " struct guestfs_%s_list {\n" typ;
5362       pr "   uint32_t len; /* Number of elements in list. */\n";
5363       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5364       pr " };\n";
5365       pr " \n";
5366       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5367       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5368         typ typ;
5369       pr "\n"
5370   ) structs
5371
5372 and generate_availability_pod () =
5373   (* Availability documentation. *)
5374   pr "=over 4\n";
5375   pr "\n";
5376   List.iter (
5377     fun (group, functions) ->
5378       pr "=item B<%s>\n" group;
5379       pr "\n";
5380       pr "The following functions:\n";
5381       List.iter (pr "L</guestfs_%s>\n") functions;
5382       pr "\n"
5383   ) optgroups;
5384   pr "=back\n";
5385   pr "\n"
5386
5387 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5388  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5389  *
5390  * We have to use an underscore instead of a dash because otherwise
5391  * rpcgen generates incorrect code.
5392  *
5393  * This header is NOT exported to clients, but see also generate_structs_h.
5394  *)
5395 and generate_xdr () =
5396   generate_header CStyle LGPLv2plus;
5397
5398   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5399   pr "typedef string str<>;\n";
5400   pr "\n";
5401
5402   (* Internal structures. *)
5403   List.iter (
5404     function
5405     | typ, cols ->
5406         pr "struct guestfs_int_%s {\n" typ;
5407         List.iter (function
5408                    | name, FChar -> pr "  char %s;\n" name
5409                    | name, FString -> pr "  string %s<>;\n" name
5410                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5411                    | name, FUUID -> pr "  opaque %s[32];\n" name
5412                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5413                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5414                    | name, FOptPercent -> pr "  float %s;\n" name
5415                   ) cols;
5416         pr "};\n";
5417         pr "\n";
5418         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5419         pr "\n";
5420   ) structs;
5421
5422   List.iter (
5423     fun (shortname, style, _, _, _, _, _) ->
5424       let name = "guestfs_" ^ shortname in
5425
5426       (match snd style with
5427        | [] -> ()
5428        | args ->
5429            pr "struct %s_args {\n" name;
5430            List.iter (
5431              function
5432              | Pathname n | Device n | Dev_or_Path n | String n ->
5433                  pr "  string %s<>;\n" n
5434              | OptString n -> pr "  str *%s;\n" n
5435              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5436              | Bool n -> pr "  bool %s;\n" n
5437              | Int n -> pr "  int %s;\n" n
5438              | Int64 n -> pr "  hyper %s;\n" n
5439              | FileIn _ | FileOut _ -> ()
5440            ) args;
5441            pr "};\n\n"
5442       );
5443       (match fst style with
5444        | RErr -> ()
5445        | RInt n ->
5446            pr "struct %s_ret {\n" name;
5447            pr "  int %s;\n" n;
5448            pr "};\n\n"
5449        | RInt64 n ->
5450            pr "struct %s_ret {\n" name;
5451            pr "  hyper %s;\n" n;
5452            pr "};\n\n"
5453        | RBool n ->
5454            pr "struct %s_ret {\n" name;
5455            pr "  bool %s;\n" n;
5456            pr "};\n\n"
5457        | RConstString _ | RConstOptString _ ->
5458            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5459        | RString n ->
5460            pr "struct %s_ret {\n" name;
5461            pr "  string %s<>;\n" n;
5462            pr "};\n\n"
5463        | RStringList n ->
5464            pr "struct %s_ret {\n" name;
5465            pr "  str %s<>;\n" n;
5466            pr "};\n\n"
5467        | RStruct (n, typ) ->
5468            pr "struct %s_ret {\n" name;
5469            pr "  guestfs_int_%s %s;\n" typ n;
5470            pr "};\n\n"
5471        | RStructList (n, typ) ->
5472            pr "struct %s_ret {\n" name;
5473            pr "  guestfs_int_%s_list %s;\n" typ n;
5474            pr "};\n\n"
5475        | RHashtable n ->
5476            pr "struct %s_ret {\n" name;
5477            pr "  str %s<>;\n" n;
5478            pr "};\n\n"
5479        | RBufferOut n ->
5480            pr "struct %s_ret {\n" name;
5481            pr "  opaque %s<>;\n" n;
5482            pr "};\n\n"
5483       );
5484   ) daemon_functions;
5485
5486   (* Table of procedure numbers. *)
5487   pr "enum guestfs_procedure {\n";
5488   List.iter (
5489     fun (shortname, _, proc_nr, _, _, _, _) ->
5490       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5491   ) daemon_functions;
5492   pr "  GUESTFS_PROC_NR_PROCS\n";
5493   pr "};\n";
5494   pr "\n";
5495
5496   (* Having to choose a maximum message size is annoying for several
5497    * reasons (it limits what we can do in the API), but it (a) makes
5498    * the protocol a lot simpler, and (b) provides a bound on the size
5499    * of the daemon which operates in limited memory space.
5500    *)
5501   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5502   pr "\n";
5503
5504   (* Message header, etc. *)
5505   pr "\
5506 /* The communication protocol is now documented in the guestfs(3)
5507  * manpage.
5508  */
5509
5510 const GUESTFS_PROGRAM = 0x2000F5F5;
5511 const GUESTFS_PROTOCOL_VERSION = 1;
5512
5513 /* These constants must be larger than any possible message length. */
5514 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5515 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5516
5517 enum guestfs_message_direction {
5518   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5519   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5520 };
5521
5522 enum guestfs_message_status {
5523   GUESTFS_STATUS_OK = 0,
5524   GUESTFS_STATUS_ERROR = 1
5525 };
5526
5527 const GUESTFS_ERROR_LEN = 256;
5528
5529 struct guestfs_message_error {
5530   string error_message<GUESTFS_ERROR_LEN>;
5531 };
5532
5533 struct guestfs_message_header {
5534   unsigned prog;                     /* GUESTFS_PROGRAM */
5535   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5536   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5537   guestfs_message_direction direction;
5538   unsigned serial;                   /* message serial number */
5539   guestfs_message_status status;
5540 };
5541
5542 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5543
5544 struct guestfs_chunk {
5545   int cancel;                        /* if non-zero, transfer is cancelled */
5546   /* data size is 0 bytes if the transfer has finished successfully */
5547   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5548 };
5549 "
5550
5551 (* Generate the guestfs-structs.h file. *)
5552 and generate_structs_h () =
5553   generate_header CStyle LGPLv2plus;
5554
5555   (* This is a public exported header file containing various
5556    * structures.  The structures are carefully written to have
5557    * exactly the same in-memory format as the XDR structures that
5558    * we use on the wire to the daemon.  The reason for creating
5559    * copies of these structures here is just so we don't have to
5560    * export the whole of guestfs_protocol.h (which includes much
5561    * unrelated and XDR-dependent stuff that we don't want to be
5562    * public, or required by clients).
5563    *
5564    * To reiterate, we will pass these structures to and from the
5565    * client with a simple assignment or memcpy, so the format
5566    * must be identical to what rpcgen / the RFC defines.
5567    *)
5568
5569   (* Public structures. *)
5570   List.iter (
5571     fun (typ, cols) ->
5572       pr "struct guestfs_%s {\n" typ;
5573       List.iter (
5574         function
5575         | name, FChar -> pr "  char %s;\n" name
5576         | name, FString -> pr "  char *%s;\n" name
5577         | name, FBuffer ->
5578             pr "  uint32_t %s_len;\n" name;
5579             pr "  char *%s;\n" name
5580         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5581         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5582         | name, FInt32 -> pr "  int32_t %s;\n" name
5583         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5584         | name, FInt64 -> pr "  int64_t %s;\n" name
5585         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5586       ) cols;
5587       pr "};\n";
5588       pr "\n";
5589       pr "struct guestfs_%s_list {\n" typ;
5590       pr "  uint32_t len;\n";
5591       pr "  struct guestfs_%s *val;\n" typ;
5592       pr "};\n";
5593       pr "\n";
5594       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5595       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5596       pr "\n"
5597   ) structs
5598
5599 (* Generate the guestfs-actions.h file. *)
5600 and generate_actions_h () =
5601   generate_header CStyle LGPLv2plus;
5602   List.iter (
5603     fun (shortname, style, _, _, _, _, _) ->
5604       let name = "guestfs_" ^ shortname in
5605       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5606         name style
5607   ) all_functions
5608
5609 (* Generate the guestfs-internal-actions.h file. *)
5610 and generate_internal_actions_h () =
5611   generate_header CStyle LGPLv2plus;
5612   List.iter (
5613     fun (shortname, style, _, _, _, _, _) ->
5614       let name = "guestfs__" ^ shortname in
5615       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5616         name style
5617   ) non_daemon_functions
5618
5619 (* Generate the client-side dispatch stubs. *)
5620 and generate_client_actions () =
5621   generate_header CStyle LGPLv2plus;
5622
5623   pr "\
5624 #include <stdio.h>
5625 #include <stdlib.h>
5626 #include <stdint.h>
5627 #include <string.h>
5628 #include <inttypes.h>
5629
5630 #include \"guestfs.h\"
5631 #include \"guestfs-internal.h\"
5632 #include \"guestfs-internal-actions.h\"
5633 #include \"guestfs_protocol.h\"
5634
5635 #define error guestfs_error
5636 //#define perrorf guestfs_perrorf
5637 #define safe_malloc guestfs_safe_malloc
5638 #define safe_realloc guestfs_safe_realloc
5639 //#define safe_strdup guestfs_safe_strdup
5640 #define safe_memdup guestfs_safe_memdup
5641
5642 /* Check the return message from a call for validity. */
5643 static int
5644 check_reply_header (guestfs_h *g,
5645                     const struct guestfs_message_header *hdr,
5646                     unsigned int proc_nr, unsigned int serial)
5647 {
5648   if (hdr->prog != GUESTFS_PROGRAM) {
5649     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5650     return -1;
5651   }
5652   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5653     error (g, \"wrong protocol version (%%d/%%d)\",
5654            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5655     return -1;
5656   }
5657   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5658     error (g, \"unexpected message direction (%%d/%%d)\",
5659            hdr->direction, GUESTFS_DIRECTION_REPLY);
5660     return -1;
5661   }
5662   if (hdr->proc != proc_nr) {
5663     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5664     return -1;
5665   }
5666   if (hdr->serial != serial) {
5667     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5668     return -1;
5669   }
5670
5671   return 0;
5672 }
5673
5674 /* Check we are in the right state to run a high-level action. */
5675 static int
5676 check_state (guestfs_h *g, const char *caller)
5677 {
5678   if (!guestfs__is_ready (g)) {
5679     if (guestfs__is_config (g) || guestfs__is_launching (g))
5680       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5681         caller);
5682     else
5683       error (g, \"%%s called from the wrong state, %%d != READY\",
5684         caller, guestfs__get_state (g));
5685     return -1;
5686   }
5687   return 0;
5688 }
5689
5690 ";
5691
5692   (* Generate code to generate guestfish call traces. *)
5693   let trace_call shortname style =
5694     pr "  if (guestfs__get_trace (g)) {\n";
5695
5696     let needs_i =
5697       List.exists (function
5698                    | StringList _ | DeviceList _ -> true
5699                    | _ -> false) (snd style) in
5700     if needs_i then (
5701       pr "    int i;\n";
5702       pr "\n"
5703     );
5704
5705     pr "    printf (\"%s\");\n" shortname;
5706     List.iter (
5707       function
5708       | String n                        (* strings *)
5709       | Device n
5710       | Pathname n
5711       | Dev_or_Path n
5712       | FileIn n
5713       | FileOut n ->
5714           (* guestfish doesn't support string escaping, so neither do we *)
5715           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5716       | OptString n ->                  (* string option *)
5717           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5718           pr "    else printf (\" null\");\n"
5719       | StringList n
5720       | DeviceList n ->                 (* string list *)
5721           pr "    putchar (' ');\n";
5722           pr "    putchar ('\"');\n";
5723           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5724           pr "      if (i > 0) putchar (' ');\n";
5725           pr "      fputs (%s[i], stdout);\n" n;
5726           pr "    }\n";
5727           pr "    putchar ('\"');\n";
5728       | Bool n ->                       (* boolean *)
5729           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5730       | Int n ->                        (* int *)
5731           pr "    printf (\" %%d\", %s);\n" n
5732       | Int64 n ->
5733           pr "    printf (\" %%\" PRIi64, %s);\n" n
5734     ) (snd style);
5735     pr "    putchar ('\\n');\n";
5736     pr "  }\n";
5737     pr "\n";
5738   in
5739
5740   (* For non-daemon functions, generate a wrapper around each function. *)
5741   List.iter (
5742     fun (shortname, style, _, _, _, _, _) ->
5743       let name = "guestfs_" ^ shortname in
5744
5745       generate_prototype ~extern:false ~semicolon:false ~newline:true
5746         ~handle:"g" name style;
5747       pr "{\n";
5748       trace_call shortname style;
5749       pr "  return guestfs__%s " shortname;
5750       generate_c_call_args ~handle:"g" style;
5751       pr ";\n";
5752       pr "}\n";
5753       pr "\n"
5754   ) non_daemon_functions;
5755
5756   (* Client-side stubs for each function. *)
5757   List.iter (
5758     fun (shortname, style, _, _, _, _, _) ->
5759       let name = "guestfs_" ^ shortname in
5760
5761       (* Generate the action stub. *)
5762       generate_prototype ~extern:false ~semicolon:false ~newline:true
5763         ~handle:"g" name style;
5764
5765       let error_code =
5766         match fst style with
5767         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5768         | RConstString _ | RConstOptString _ ->
5769             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5770         | RString _ | RStringList _
5771         | RStruct _ | RStructList _
5772         | RHashtable _ | RBufferOut _ ->
5773             "NULL" in
5774
5775       pr "{\n";
5776
5777       (match snd style with
5778        | [] -> ()
5779        | _ -> pr "  struct %s_args args;\n" name
5780       );
5781
5782       pr "  guestfs_message_header hdr;\n";
5783       pr "  guestfs_message_error err;\n";
5784       let has_ret =
5785         match fst style with
5786         | RErr -> false
5787         | RConstString _ | RConstOptString _ ->
5788             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5789         | RInt _ | RInt64 _
5790         | RBool _ | RString _ | RStringList _
5791         | RStruct _ | RStructList _
5792         | RHashtable _ | RBufferOut _ ->
5793             pr "  struct %s_ret ret;\n" name;
5794             true in
5795
5796       pr "  int serial;\n";
5797       pr "  int r;\n";
5798       pr "\n";
5799       trace_call shortname style;
5800       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5801         shortname error_code;
5802       pr "  guestfs___set_busy (g);\n";
5803       pr "\n";
5804
5805       (* Send the main header and arguments. *)
5806       (match snd style with
5807        | [] ->
5808            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5809              (String.uppercase shortname)
5810        | args ->
5811            List.iter (
5812              function
5813              | Pathname n | Device n | Dev_or_Path n | String n ->
5814                  pr "  args.%s = (char *) %s;\n" n n
5815              | OptString n ->
5816                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5817              | StringList n | DeviceList n ->
5818                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5819                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5820              | Bool n ->
5821                  pr "  args.%s = %s;\n" n n
5822              | Int n ->
5823                  pr "  args.%s = %s;\n" n n
5824              | Int64 n ->
5825                  pr "  args.%s = %s;\n" n n
5826              | FileIn _ | FileOut _ -> ()
5827            ) args;
5828            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5829              (String.uppercase shortname);
5830            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5831              name;
5832       );
5833       pr "  if (serial == -1) {\n";
5834       pr "    guestfs___end_busy (g);\n";
5835       pr "    return %s;\n" error_code;
5836       pr "  }\n";
5837       pr "\n";
5838
5839       (* Send any additional files (FileIn) requested. *)
5840       let need_read_reply_label = ref false in
5841       List.iter (
5842         function
5843         | FileIn n ->
5844             pr "  r = guestfs___send_file (g, %s);\n" n;
5845             pr "  if (r == -1) {\n";
5846             pr "    guestfs___end_busy (g);\n";
5847             pr "    return %s;\n" error_code;
5848             pr "  }\n";
5849             pr "  if (r == -2) /* daemon cancelled */\n";
5850             pr "    goto read_reply;\n";
5851             need_read_reply_label := true;
5852             pr "\n";
5853         | _ -> ()
5854       ) (snd style);
5855
5856       (* Wait for the reply from the remote end. *)
5857       if !need_read_reply_label then pr " read_reply:\n";
5858       pr "  memset (&hdr, 0, sizeof hdr);\n";
5859       pr "  memset (&err, 0, sizeof err);\n";
5860       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5861       pr "\n";
5862       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5863       if not has_ret then
5864         pr "NULL, NULL"
5865       else
5866         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5867       pr ");\n";
5868
5869       pr "  if (r == -1) {\n";
5870       pr "    guestfs___end_busy (g);\n";
5871       pr "    return %s;\n" error_code;
5872       pr "  }\n";
5873       pr "\n";
5874
5875       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5876         (String.uppercase shortname);
5877       pr "    guestfs___end_busy (g);\n";
5878       pr "    return %s;\n" error_code;
5879       pr "  }\n";
5880       pr "\n";
5881
5882       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5883       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5884       pr "    free (err.error_message);\n";
5885       pr "    guestfs___end_busy (g);\n";
5886       pr "    return %s;\n" error_code;
5887       pr "  }\n";
5888       pr "\n";
5889
5890       (* Expecting to receive further files (FileOut)? *)
5891       List.iter (
5892         function
5893         | FileOut n ->
5894             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5895             pr "    guestfs___end_busy (g);\n";
5896             pr "    return %s;\n" error_code;
5897             pr "  }\n";
5898             pr "\n";
5899         | _ -> ()
5900       ) (snd style);
5901
5902       pr "  guestfs___end_busy (g);\n";
5903
5904       (match fst style with
5905        | RErr -> pr "  return 0;\n"
5906        | RInt n | RInt64 n | RBool n ->
5907            pr "  return ret.%s;\n" n
5908        | RConstString _ | RConstOptString _ ->
5909            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5910        | RString n ->
5911            pr "  return ret.%s; /* caller will free */\n" n
5912        | RStringList n | RHashtable n ->
5913            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5914            pr "  ret.%s.%s_val =\n" n n;
5915            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5916            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5917              n n;
5918            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5919            pr "  return ret.%s.%s_val;\n" n n
5920        | RStruct (n, _) ->
5921            pr "  /* caller will free this */\n";
5922            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5923        | RStructList (n, _) ->
5924            pr "  /* caller will free this */\n";
5925            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5926        | RBufferOut n ->
5927            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5928            pr "   * _val might be NULL here.  To make the API saner for\n";
5929            pr "   * callers, we turn this case into a unique pointer (using\n";
5930            pr "   * malloc(1)).\n";
5931            pr "   */\n";
5932            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5933            pr "    *size_r = ret.%s.%s_len;\n" n n;
5934            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5935            pr "  } else {\n";
5936            pr "    free (ret.%s.%s_val);\n" n n;
5937            pr "    char *p = safe_malloc (g, 1);\n";
5938            pr "    *size_r = ret.%s.%s_len;\n" n n;
5939            pr "    return p;\n";
5940            pr "  }\n";
5941       );
5942
5943       pr "}\n\n"
5944   ) daemon_functions;
5945
5946   (* Functions to free structures. *)
5947   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5948   pr " * structure format is identical to the XDR format.  See note in\n";
5949   pr " * generator.ml.\n";
5950   pr " */\n";
5951   pr "\n";
5952
5953   List.iter (
5954     fun (typ, _) ->
5955       pr "void\n";
5956       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5957       pr "{\n";
5958       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5959       pr "  free (x);\n";
5960       pr "}\n";
5961       pr "\n";
5962
5963       pr "void\n";
5964       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5965       pr "{\n";
5966       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5967       pr "  free (x);\n";
5968       pr "}\n";
5969       pr "\n";
5970
5971   ) structs;
5972
5973 (* Generate daemon/actions.h. *)
5974 and generate_daemon_actions_h () =
5975   generate_header CStyle GPLv2plus;
5976
5977   pr "#include \"../src/guestfs_protocol.h\"\n";
5978   pr "\n";
5979
5980   List.iter (
5981     fun (name, style, _, _, _, _, _) ->
5982       generate_prototype
5983         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5984         name style;
5985   ) daemon_functions
5986
5987 (* Generate the linker script which controls the visibility of
5988  * symbols in the public ABI and ensures no other symbols get
5989  * exported accidentally.
5990  *)
5991 and generate_linker_script () =
5992   generate_header HashStyle GPLv2plus;
5993
5994   let globals = [
5995     "guestfs_create";
5996     "guestfs_close";
5997     "guestfs_get_error_handler";
5998     "guestfs_get_out_of_memory_handler";
5999     "guestfs_last_error";
6000     "guestfs_set_error_handler";
6001     "guestfs_set_launch_done_callback";
6002     "guestfs_set_log_message_callback";
6003     "guestfs_set_out_of_memory_handler";
6004     "guestfs_set_subprocess_quit_callback";
6005
6006     (* Unofficial parts of the API: the bindings code use these
6007      * functions, so it is useful to export them.
6008      *)
6009     "guestfs_safe_calloc";
6010     "guestfs_safe_malloc";
6011   ] in
6012   let functions =
6013     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6014       all_functions in
6015   let structs =
6016     List.concat (
6017       List.map (fun (typ, _) ->
6018                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6019         structs
6020     ) in
6021   let globals = List.sort compare (globals @ functions @ structs) in
6022
6023   pr "{\n";
6024   pr "    global:\n";
6025   List.iter (pr "        %s;\n") globals;
6026   pr "\n";
6027
6028   pr "    local:\n";
6029   pr "        *;\n";
6030   pr "};\n"
6031
6032 (* Generate the server-side stubs. *)
6033 and generate_daemon_actions () =
6034   generate_header CStyle GPLv2plus;
6035
6036   pr "#include <config.h>\n";
6037   pr "\n";
6038   pr "#include <stdio.h>\n";
6039   pr "#include <stdlib.h>\n";
6040   pr "#include <string.h>\n";
6041   pr "#include <inttypes.h>\n";
6042   pr "#include <rpc/types.h>\n";
6043   pr "#include <rpc/xdr.h>\n";
6044   pr "\n";
6045   pr "#include \"daemon.h\"\n";
6046   pr "#include \"c-ctype.h\"\n";
6047   pr "#include \"../src/guestfs_protocol.h\"\n";
6048   pr "#include \"actions.h\"\n";
6049   pr "\n";
6050
6051   List.iter (
6052     fun (name, style, _, _, _, _, _) ->
6053       (* Generate server-side stubs. *)
6054       pr "static void %s_stub (XDR *xdr_in)\n" name;
6055       pr "{\n";
6056       let error_code =
6057         match fst style with
6058         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6059         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6060         | RBool _ -> pr "  int r;\n"; "-1"
6061         | RConstString _ | RConstOptString _ ->
6062             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6063         | RString _ -> pr "  char *r;\n"; "NULL"
6064         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6065         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6066         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6067         | RBufferOut _ ->
6068             pr "  size_t size = 1;\n";
6069             pr "  char *r;\n";
6070             "NULL" in
6071
6072       (match snd style with
6073        | [] -> ()
6074        | args ->
6075            pr "  struct guestfs_%s_args args;\n" name;
6076            List.iter (
6077              function
6078              | Device n | Dev_or_Path n
6079              | Pathname n
6080              | String n -> ()
6081              | OptString n -> pr "  char *%s;\n" n
6082              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6083              | Bool n -> pr "  int %s;\n" n
6084              | Int n -> pr "  int %s;\n" n
6085              | Int64 n -> pr "  int64_t %s;\n" n
6086              | FileIn _ | FileOut _ -> ()
6087            ) args
6088       );
6089       pr "\n";
6090
6091       let is_filein =
6092         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6093
6094       (match snd style with
6095        | [] -> ()
6096        | args ->
6097            pr "  memset (&args, 0, sizeof args);\n";
6098            pr "\n";
6099            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6100            if is_filein then
6101              pr "    cancel_receive ();\n";
6102            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6103            pr "    goto done;\n";
6104            pr "  }\n";
6105            let pr_args n =
6106              pr "  char *%s = args.%s;\n" n n
6107            in
6108            let pr_list_handling_code n =
6109              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6110              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6111              pr "  if (%s == NULL) {\n" n;
6112              if is_filein then
6113                pr "    cancel_receive ();\n";
6114              pr "    reply_with_perror (\"realloc\");\n";
6115              pr "    goto done;\n";
6116              pr "  }\n";
6117              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6118              pr "  args.%s.%s_val = %s;\n" n n n;
6119            in
6120            List.iter (
6121              function
6122              | Pathname n ->
6123                  pr_args n;
6124                  pr "  ABS_PATH (%s, %s, goto done);\n"
6125                    n (if is_filein then "cancel_receive ()" else "");
6126              | Device n ->
6127                  pr_args n;
6128                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6129                    n (if is_filein then "cancel_receive ()" else "");
6130              | Dev_or_Path n ->
6131                  pr_args n;
6132                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6133                    n (if is_filein then "cancel_receive ()" else "");
6134              | String n -> pr_args n
6135              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6136              | StringList n ->
6137                  pr_list_handling_code n;
6138              | DeviceList n ->
6139                  pr_list_handling_code n;
6140                  pr "  /* Ensure that each is a device,\n";
6141                  pr "   * and perform device name translation. */\n";
6142                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6143                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6144                    (if is_filein then "cancel_receive ()" else "");
6145                  pr "  }\n";
6146              | Bool n -> pr "  %s = args.%s;\n" n n
6147              | Int n -> pr "  %s = args.%s;\n" n n
6148              | Int64 n -> pr "  %s = args.%s;\n" n n
6149              | FileIn _ | FileOut _ -> ()
6150            ) args;
6151            pr "\n"
6152       );
6153
6154
6155       (* this is used at least for do_equal *)
6156       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6157         (* Emit NEED_ROOT just once, even when there are two or
6158            more Pathname args *)
6159         pr "  NEED_ROOT (%s, goto done);\n"
6160           (if is_filein then "cancel_receive ()" else "");
6161       );
6162
6163       (* Don't want to call the impl with any FileIn or FileOut
6164        * parameters, since these go "outside" the RPC protocol.
6165        *)
6166       let args' =
6167         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6168           (snd style) in
6169       pr "  r = do_%s " name;
6170       generate_c_call_args (fst style, args');
6171       pr ";\n";
6172
6173       (match fst style with
6174        | RErr | RInt _ | RInt64 _ | RBool _
6175        | RConstString _ | RConstOptString _
6176        | RString _ | RStringList _ | RHashtable _
6177        | RStruct (_, _) | RStructList (_, _) ->
6178            pr "  if (r == %s)\n" error_code;
6179            pr "    /* do_%s has already called reply_with_error */\n" name;
6180            pr "    goto done;\n";
6181            pr "\n"
6182        | RBufferOut _ ->
6183            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6184            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6185            pr "   */\n";
6186            pr "  if (size == 1 && r == %s)\n" error_code;
6187            pr "    /* do_%s has already called reply_with_error */\n" name;
6188            pr "    goto done;\n";
6189            pr "\n"
6190       );
6191
6192       (* If there are any FileOut parameters, then the impl must
6193        * send its own reply.
6194        *)
6195       let no_reply =
6196         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6197       if no_reply then
6198         pr "  /* do_%s has already sent a reply */\n" name
6199       else (
6200         match fst style with
6201         | RErr -> pr "  reply (NULL, NULL);\n"
6202         | RInt n | RInt64 n | RBool n ->
6203             pr "  struct guestfs_%s_ret ret;\n" name;
6204             pr "  ret.%s = r;\n" n;
6205             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6206               name
6207         | RConstString _ | RConstOptString _ ->
6208             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6209         | RString n ->
6210             pr "  struct guestfs_%s_ret ret;\n" name;
6211             pr "  ret.%s = r;\n" n;
6212             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6213               name;
6214             pr "  free (r);\n"
6215         | RStringList n | RHashtable n ->
6216             pr "  struct guestfs_%s_ret ret;\n" name;
6217             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6218             pr "  ret.%s.%s_val = r;\n" n n;
6219             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6220               name;
6221             pr "  free_strings (r);\n"
6222         | RStruct (n, _) ->
6223             pr "  struct guestfs_%s_ret ret;\n" name;
6224             pr "  ret.%s = *r;\n" n;
6225             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6226               name;
6227             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6228               name
6229         | RStructList (n, _) ->
6230             pr "  struct guestfs_%s_ret ret;\n" name;
6231             pr "  ret.%s = *r;\n" n;
6232             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6233               name;
6234             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6235               name
6236         | RBufferOut n ->
6237             pr "  struct guestfs_%s_ret ret;\n" name;
6238             pr "  ret.%s.%s_val = r;\n" n n;
6239             pr "  ret.%s.%s_len = size;\n" n n;
6240             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6241               name;
6242             pr "  free (r);\n"
6243       );
6244
6245       (* Free the args. *)
6246       pr "done:\n";
6247       (match snd style with
6248        | [] -> ()
6249        | _ ->
6250            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6251              name
6252       );
6253       pr "  return;\n";
6254       pr "}\n\n";
6255   ) daemon_functions;
6256
6257   (* Dispatch function. *)
6258   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6259   pr "{\n";
6260   pr "  switch (proc_nr) {\n";
6261
6262   List.iter (
6263     fun (name, style, _, _, _, _, _) ->
6264       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6265       pr "      %s_stub (xdr_in);\n" name;
6266       pr "      break;\n"
6267   ) daemon_functions;
6268
6269   pr "    default:\n";
6270   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";
6271   pr "  }\n";
6272   pr "}\n";
6273   pr "\n";
6274
6275   (* LVM columns and tokenization functions. *)
6276   (* XXX This generates crap code.  We should rethink how we
6277    * do this parsing.
6278    *)
6279   List.iter (
6280     function
6281     | typ, cols ->
6282         pr "static const char *lvm_%s_cols = \"%s\";\n"
6283           typ (String.concat "," (List.map fst cols));
6284         pr "\n";
6285
6286         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6287         pr "{\n";
6288         pr "  char *tok, *p, *next;\n";
6289         pr "  int i, j;\n";
6290         pr "\n";
6291         (*
6292           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6293           pr "\n";
6294         *)
6295         pr "  if (!str) {\n";
6296         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6297         pr "    return -1;\n";
6298         pr "  }\n";
6299         pr "  if (!*str || c_isspace (*str)) {\n";
6300         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6301         pr "    return -1;\n";
6302         pr "  }\n";
6303         pr "  tok = str;\n";
6304         List.iter (
6305           fun (name, coltype) ->
6306             pr "  if (!tok) {\n";
6307             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6308             pr "    return -1;\n";
6309             pr "  }\n";
6310             pr "  p = strchrnul (tok, ',');\n";
6311             pr "  if (*p) next = p+1; else next = NULL;\n";
6312             pr "  *p = '\\0';\n";
6313             (match coltype with
6314              | FString ->
6315                  pr "  r->%s = strdup (tok);\n" name;
6316                  pr "  if (r->%s == NULL) {\n" name;
6317                  pr "    perror (\"strdup\");\n";
6318                  pr "    return -1;\n";
6319                  pr "  }\n"
6320              | FUUID ->
6321                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6322                  pr "    if (tok[j] == '\\0') {\n";
6323                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6324                  pr "      return -1;\n";
6325                  pr "    } else if (tok[j] != '-')\n";
6326                  pr "      r->%s[i++] = tok[j];\n" name;
6327                  pr "  }\n";
6328              | FBytes ->
6329                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6330                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6331                  pr "    return -1;\n";
6332                  pr "  }\n";
6333              | FInt64 ->
6334                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6335                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6336                  pr "    return -1;\n";
6337                  pr "  }\n";
6338              | FOptPercent ->
6339                  pr "  if (tok[0] == '\\0')\n";
6340                  pr "    r->%s = -1;\n" name;
6341                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6342                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6343                  pr "    return -1;\n";
6344                  pr "  }\n";
6345              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6346                  assert false (* can never be an LVM column *)
6347             );
6348             pr "  tok = next;\n";
6349         ) cols;
6350
6351         pr "  if (tok != NULL) {\n";
6352         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6353         pr "    return -1;\n";
6354         pr "  }\n";
6355         pr "  return 0;\n";
6356         pr "}\n";
6357         pr "\n";
6358
6359         pr "guestfs_int_lvm_%s_list *\n" typ;
6360         pr "parse_command_line_%ss (void)\n" typ;
6361         pr "{\n";
6362         pr "  char *out, *err;\n";
6363         pr "  char *p, *pend;\n";
6364         pr "  int r, i;\n";
6365         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6366         pr "  void *newp;\n";
6367         pr "\n";
6368         pr "  ret = malloc (sizeof *ret);\n";
6369         pr "  if (!ret) {\n";
6370         pr "    reply_with_perror (\"malloc\");\n";
6371         pr "    return NULL;\n";
6372         pr "  }\n";
6373         pr "\n";
6374         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6375         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6376         pr "\n";
6377         pr "  r = command (&out, &err,\n";
6378         pr "           \"lvm\", \"%ss\",\n" typ;
6379         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6380         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6381         pr "  if (r == -1) {\n";
6382         pr "    reply_with_error (\"%%s\", err);\n";
6383         pr "    free (out);\n";
6384         pr "    free (err);\n";
6385         pr "    free (ret);\n";
6386         pr "    return NULL;\n";
6387         pr "  }\n";
6388         pr "\n";
6389         pr "  free (err);\n";
6390         pr "\n";
6391         pr "  /* Tokenize each line of the output. */\n";
6392         pr "  p = out;\n";
6393         pr "  i = 0;\n";
6394         pr "  while (p) {\n";
6395         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6396         pr "    if (pend) {\n";
6397         pr "      *pend = '\\0';\n";
6398         pr "      pend++;\n";
6399         pr "    }\n";
6400         pr "\n";
6401         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6402         pr "      p++;\n";
6403         pr "\n";
6404         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6405         pr "      p = pend;\n";
6406         pr "      continue;\n";
6407         pr "    }\n";
6408         pr "\n";
6409         pr "    /* Allocate some space to store this next entry. */\n";
6410         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6411         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6412         pr "    if (newp == NULL) {\n";
6413         pr "      reply_with_perror (\"realloc\");\n";
6414         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6415         pr "      free (ret);\n";
6416         pr "      free (out);\n";
6417         pr "      return NULL;\n";
6418         pr "    }\n";
6419         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6420         pr "\n";
6421         pr "    /* Tokenize the next entry. */\n";
6422         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6423         pr "    if (r == -1) {\n";
6424         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6425         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6426         pr "      free (ret);\n";
6427         pr "      free (out);\n";
6428         pr "      return NULL;\n";
6429         pr "    }\n";
6430         pr "\n";
6431         pr "    ++i;\n";
6432         pr "    p = pend;\n";
6433         pr "  }\n";
6434         pr "\n";
6435         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6436         pr "\n";
6437         pr "  free (out);\n";
6438         pr "  return ret;\n";
6439         pr "}\n"
6440
6441   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6442
6443 (* Generate a list of function names, for debugging in the daemon.. *)
6444 and generate_daemon_names () =
6445   generate_header CStyle GPLv2plus;
6446
6447   pr "#include <config.h>\n";
6448   pr "\n";
6449   pr "#include \"daemon.h\"\n";
6450   pr "\n";
6451
6452   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6453   pr "const char *function_names[] = {\n";
6454   List.iter (
6455     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6456   ) daemon_functions;
6457   pr "};\n";
6458
6459 (* Generate the optional groups for the daemon to implement
6460  * guestfs_available.
6461  *)
6462 and generate_daemon_optgroups_c () =
6463   generate_header CStyle GPLv2plus;
6464
6465   pr "#include <config.h>\n";
6466   pr "\n";
6467   pr "#include \"daemon.h\"\n";
6468   pr "#include \"optgroups.h\"\n";
6469   pr "\n";
6470
6471   pr "struct optgroup optgroups[] = {\n";
6472   List.iter (
6473     fun (group, _) ->
6474       pr "  { \"%s\", optgroup_%s_available },\n" group group
6475   ) optgroups;
6476   pr "  { NULL, NULL }\n";
6477   pr "};\n"
6478
6479 and generate_daemon_optgroups_h () =
6480   generate_header CStyle GPLv2plus;
6481
6482   List.iter (
6483     fun (group, _) ->
6484       pr "extern int optgroup_%s_available (void);\n" group
6485   ) optgroups
6486
6487 (* Generate the tests. *)
6488 and generate_tests () =
6489   generate_header CStyle GPLv2plus;
6490
6491   pr "\
6492 #include <stdio.h>
6493 #include <stdlib.h>
6494 #include <string.h>
6495 #include <unistd.h>
6496 #include <sys/types.h>
6497 #include <fcntl.h>
6498
6499 #include \"guestfs.h\"
6500 #include \"guestfs-internal.h\"
6501
6502 static guestfs_h *g;
6503 static int suppress_error = 0;
6504
6505 static void print_error (guestfs_h *g, void *data, const char *msg)
6506 {
6507   if (!suppress_error)
6508     fprintf (stderr, \"%%s\\n\", msg);
6509 }
6510
6511 /* FIXME: nearly identical code appears in fish.c */
6512 static void print_strings (char *const *argv)
6513 {
6514   int argc;
6515
6516   for (argc = 0; argv[argc] != NULL; ++argc)
6517     printf (\"\\t%%s\\n\", argv[argc]);
6518 }
6519
6520 /*
6521 static void print_table (char const *const *argv)
6522 {
6523   int i;
6524
6525   for (i = 0; argv[i] != NULL; i += 2)
6526     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6527 }
6528 */
6529
6530 ";
6531
6532   (* Generate a list of commands which are not tested anywhere. *)
6533   pr "static void no_test_warnings (void)\n";
6534   pr "{\n";
6535
6536   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6537   List.iter (
6538     fun (_, _, _, _, tests, _, _) ->
6539       let tests = filter_map (
6540         function
6541         | (_, (Always|If _|Unless _), test) -> Some test
6542         | (_, Disabled, _) -> None
6543       ) tests in
6544       let seq = List.concat (List.map seq_of_test tests) in
6545       let cmds_tested = List.map List.hd seq in
6546       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6547   ) all_functions;
6548
6549   List.iter (
6550     fun (name, _, _, _, _, _, _) ->
6551       if not (Hashtbl.mem hash name) then
6552         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6553   ) all_functions;
6554
6555   pr "}\n";
6556   pr "\n";
6557
6558   (* Generate the actual tests.  Note that we generate the tests
6559    * in reverse order, deliberately, so that (in general) the
6560    * newest tests run first.  This makes it quicker and easier to
6561    * debug them.
6562    *)
6563   let test_names =
6564     List.map (
6565       fun (name, _, _, flags, tests, _, _) ->
6566         mapi (generate_one_test name flags) tests
6567     ) (List.rev all_functions) in
6568   let test_names = List.concat test_names in
6569   let nr_tests = List.length test_names in
6570
6571   pr "\
6572 int main (int argc, char *argv[])
6573 {
6574   char c = 0;
6575   unsigned long int n_failed = 0;
6576   const char *filename;
6577   int fd;
6578   int nr_tests, test_num = 0;
6579
6580   setbuf (stdout, NULL);
6581
6582   no_test_warnings ();
6583
6584   g = guestfs_create ();
6585   if (g == NULL) {
6586     printf (\"guestfs_create FAILED\\n\");
6587     exit (EXIT_FAILURE);
6588   }
6589
6590   guestfs_set_error_handler (g, print_error, NULL);
6591
6592   guestfs_set_path (g, \"../appliance\");
6593
6594   filename = \"test1.img\";
6595   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6596   if (fd == -1) {
6597     perror (filename);
6598     exit (EXIT_FAILURE);
6599   }
6600   if (lseek (fd, %d, SEEK_SET) == -1) {
6601     perror (\"lseek\");
6602     close (fd);
6603     unlink (filename);
6604     exit (EXIT_FAILURE);
6605   }
6606   if (write (fd, &c, 1) == -1) {
6607     perror (\"write\");
6608     close (fd);
6609     unlink (filename);
6610     exit (EXIT_FAILURE);
6611   }
6612   if (close (fd) == -1) {
6613     perror (filename);
6614     unlink (filename);
6615     exit (EXIT_FAILURE);
6616   }
6617   if (guestfs_add_drive (g, filename) == -1) {
6618     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6619     exit (EXIT_FAILURE);
6620   }
6621
6622   filename = \"test2.img\";
6623   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6624   if (fd == -1) {
6625     perror (filename);
6626     exit (EXIT_FAILURE);
6627   }
6628   if (lseek (fd, %d, SEEK_SET) == -1) {
6629     perror (\"lseek\");
6630     close (fd);
6631     unlink (filename);
6632     exit (EXIT_FAILURE);
6633   }
6634   if (write (fd, &c, 1) == -1) {
6635     perror (\"write\");
6636     close (fd);
6637     unlink (filename);
6638     exit (EXIT_FAILURE);
6639   }
6640   if (close (fd) == -1) {
6641     perror (filename);
6642     unlink (filename);
6643     exit (EXIT_FAILURE);
6644   }
6645   if (guestfs_add_drive (g, filename) == -1) {
6646     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6647     exit (EXIT_FAILURE);
6648   }
6649
6650   filename = \"test3.img\";
6651   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6652   if (fd == -1) {
6653     perror (filename);
6654     exit (EXIT_FAILURE);
6655   }
6656   if (lseek (fd, %d, SEEK_SET) == -1) {
6657     perror (\"lseek\");
6658     close (fd);
6659     unlink (filename);
6660     exit (EXIT_FAILURE);
6661   }
6662   if (write (fd, &c, 1) == -1) {
6663     perror (\"write\");
6664     close (fd);
6665     unlink (filename);
6666     exit (EXIT_FAILURE);
6667   }
6668   if (close (fd) == -1) {
6669     perror (filename);
6670     unlink (filename);
6671     exit (EXIT_FAILURE);
6672   }
6673   if (guestfs_add_drive (g, filename) == -1) {
6674     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6675     exit (EXIT_FAILURE);
6676   }
6677
6678   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6679     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6680     exit (EXIT_FAILURE);
6681   }
6682
6683   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6684   alarm (600);
6685
6686   if (guestfs_launch (g) == -1) {
6687     printf (\"guestfs_launch FAILED\\n\");
6688     exit (EXIT_FAILURE);
6689   }
6690
6691   /* Cancel previous alarm. */
6692   alarm (0);
6693
6694   nr_tests = %d;
6695
6696 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6697
6698   iteri (
6699     fun i test_name ->
6700       pr "  test_num++;\n";
6701       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6702       pr "  if (%s () == -1) {\n" test_name;
6703       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6704       pr "    n_failed++;\n";
6705       pr "  }\n";
6706   ) test_names;
6707   pr "\n";
6708
6709   pr "  guestfs_close (g);\n";
6710   pr "  unlink (\"test1.img\");\n";
6711   pr "  unlink (\"test2.img\");\n";
6712   pr "  unlink (\"test3.img\");\n";
6713   pr "\n";
6714
6715   pr "  if (n_failed > 0) {\n";
6716   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6717   pr "    exit (EXIT_FAILURE);\n";
6718   pr "  }\n";
6719   pr "\n";
6720
6721   pr "  exit (EXIT_SUCCESS);\n";
6722   pr "}\n"
6723
6724 and generate_one_test name flags i (init, prereq, test) =
6725   let test_name = sprintf "test_%s_%d" name i in
6726
6727   pr "\
6728 static int %s_skip (void)
6729 {
6730   const char *str;
6731
6732   str = getenv (\"TEST_ONLY\");
6733   if (str)
6734     return strstr (str, \"%s\") == NULL;
6735   str = getenv (\"SKIP_%s\");
6736   if (str && STREQ (str, \"1\")) return 1;
6737   str = getenv (\"SKIP_TEST_%s\");
6738   if (str && STREQ (str, \"1\")) return 1;
6739   return 0;
6740 }
6741
6742 " test_name name (String.uppercase test_name) (String.uppercase name);
6743
6744   (match prereq with
6745    | Disabled | Always -> ()
6746    | If code | Unless code ->
6747        pr "static int %s_prereq (void)\n" test_name;
6748        pr "{\n";
6749        pr "  %s\n" code;
6750        pr "}\n";
6751        pr "\n";
6752   );
6753
6754   pr "\
6755 static int %s (void)
6756 {
6757   if (%s_skip ()) {
6758     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6759     return 0;
6760   }
6761
6762 " test_name test_name test_name;
6763
6764   (* Optional functions should only be tested if the relevant
6765    * support is available in the daemon.
6766    *)
6767   List.iter (
6768     function
6769     | Optional group ->
6770         pr "  {\n";
6771         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6772         pr "    int r;\n";
6773         pr "    suppress_error = 1;\n";
6774         pr "    r = guestfs_available (g, (char **) groups);\n";
6775         pr "    suppress_error = 0;\n";
6776         pr "    if (r == -1) {\n";
6777         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6778         pr "      return 0;\n";
6779         pr "    }\n";
6780         pr "  }\n";
6781     | _ -> ()
6782   ) flags;
6783
6784   (match prereq with
6785    | Disabled ->
6786        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6787    | If _ ->
6788        pr "  if (! %s_prereq ()) {\n" test_name;
6789        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6790        pr "    return 0;\n";
6791        pr "  }\n";
6792        pr "\n";
6793        generate_one_test_body name i test_name init test;
6794    | Unless _ ->
6795        pr "  if (%s_prereq ()) {\n" test_name;
6796        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6797        pr "    return 0;\n";
6798        pr "  }\n";
6799        pr "\n";
6800        generate_one_test_body name i test_name init test;
6801    | Always ->
6802        generate_one_test_body name i test_name init test
6803   );
6804
6805   pr "  return 0;\n";
6806   pr "}\n";
6807   pr "\n";
6808   test_name
6809
6810 and generate_one_test_body name i test_name init test =
6811   (match init with
6812    | InitNone (* XXX at some point, InitNone and InitEmpty became
6813                * folded together as the same thing.  Really we should
6814                * make InitNone do nothing at all, but the tests may
6815                * need to be checked to make sure this is OK.
6816                *)
6817    | InitEmpty ->
6818        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6819        List.iter (generate_test_command_call test_name)
6820          [["blockdev_setrw"; "/dev/sda"];
6821           ["umount_all"];
6822           ["lvm_remove_all"]]
6823    | InitPartition ->
6824        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6825        List.iter (generate_test_command_call test_name)
6826          [["blockdev_setrw"; "/dev/sda"];
6827           ["umount_all"];
6828           ["lvm_remove_all"];
6829           ["part_disk"; "/dev/sda"; "mbr"]]
6830    | InitBasicFS ->
6831        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6832        List.iter (generate_test_command_call test_name)
6833          [["blockdev_setrw"; "/dev/sda"];
6834           ["umount_all"];
6835           ["lvm_remove_all"];
6836           ["part_disk"; "/dev/sda"; "mbr"];
6837           ["mkfs"; "ext2"; "/dev/sda1"];
6838           ["mount_options"; ""; "/dev/sda1"; "/"]]
6839    | InitBasicFSonLVM ->
6840        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6841          test_name;
6842        List.iter (generate_test_command_call test_name)
6843          [["blockdev_setrw"; "/dev/sda"];
6844           ["umount_all"];
6845           ["lvm_remove_all"];
6846           ["part_disk"; "/dev/sda"; "mbr"];
6847           ["pvcreate"; "/dev/sda1"];
6848           ["vgcreate"; "VG"; "/dev/sda1"];
6849           ["lvcreate"; "LV"; "VG"; "8"];
6850           ["mkfs"; "ext2"; "/dev/VG/LV"];
6851           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6852    | InitISOFS ->
6853        pr "  /* InitISOFS for %s */\n" test_name;
6854        List.iter (generate_test_command_call test_name)
6855          [["blockdev_setrw"; "/dev/sda"];
6856           ["umount_all"];
6857           ["lvm_remove_all"];
6858           ["mount_ro"; "/dev/sdd"; "/"]]
6859   );
6860
6861   let get_seq_last = function
6862     | [] ->
6863         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6864           test_name
6865     | seq ->
6866         let seq = List.rev seq in
6867         List.rev (List.tl seq), List.hd seq
6868   in
6869
6870   match test with
6871   | TestRun seq ->
6872       pr "  /* TestRun for %s (%d) */\n" name i;
6873       List.iter (generate_test_command_call test_name) seq
6874   | TestOutput (seq, expected) ->
6875       pr "  /* TestOutput for %s (%d) */\n" name i;
6876       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6877       let seq, last = get_seq_last seq in
6878       let test () =
6879         pr "    if (STRNEQ (r, expected)) {\n";
6880         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6881         pr "      return -1;\n";
6882         pr "    }\n"
6883       in
6884       List.iter (generate_test_command_call test_name) seq;
6885       generate_test_command_call ~test test_name last
6886   | TestOutputList (seq, expected) ->
6887       pr "  /* TestOutputList for %s (%d) */\n" name i;
6888       let seq, last = get_seq_last seq in
6889       let test () =
6890         iteri (
6891           fun i str ->
6892             pr "    if (!r[%d]) {\n" i;
6893             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6894             pr "      print_strings (r);\n";
6895             pr "      return -1;\n";
6896             pr "    }\n";
6897             pr "    {\n";
6898             pr "      const char *expected = \"%s\";\n" (c_quote str);
6899             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6900             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6901             pr "        return -1;\n";
6902             pr "      }\n";
6903             pr "    }\n"
6904         ) expected;
6905         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6906         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6907           test_name;
6908         pr "      print_strings (r);\n";
6909         pr "      return -1;\n";
6910         pr "    }\n"
6911       in
6912       List.iter (generate_test_command_call test_name) seq;
6913       generate_test_command_call ~test test_name last
6914   | TestOutputListOfDevices (seq, expected) ->
6915       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6916       let seq, last = get_seq_last seq in
6917       let test () =
6918         iteri (
6919           fun i str ->
6920             pr "    if (!r[%d]) {\n" i;
6921             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6922             pr "      print_strings (r);\n";
6923             pr "      return -1;\n";
6924             pr "    }\n";
6925             pr "    {\n";
6926             pr "      const char *expected = \"%s\";\n" (c_quote str);
6927             pr "      r[%d][5] = 's';\n" i;
6928             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6929             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6930             pr "        return -1;\n";
6931             pr "      }\n";
6932             pr "    }\n"
6933         ) expected;
6934         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6935         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6936           test_name;
6937         pr "      print_strings (r);\n";
6938         pr "      return -1;\n";
6939         pr "    }\n"
6940       in
6941       List.iter (generate_test_command_call test_name) seq;
6942       generate_test_command_call ~test test_name last
6943   | TestOutputInt (seq, expected) ->
6944       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6945       let seq, last = get_seq_last seq in
6946       let test () =
6947         pr "    if (r != %d) {\n" expected;
6948         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6949           test_name expected;
6950         pr "               (int) r);\n";
6951         pr "      return -1;\n";
6952         pr "    }\n"
6953       in
6954       List.iter (generate_test_command_call test_name) seq;
6955       generate_test_command_call ~test test_name last
6956   | TestOutputIntOp (seq, op, expected) ->
6957       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6958       let seq, last = get_seq_last seq in
6959       let test () =
6960         pr "    if (! (r %s %d)) {\n" op expected;
6961         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6962           test_name op expected;
6963         pr "               (int) r);\n";
6964         pr "      return -1;\n";
6965         pr "    }\n"
6966       in
6967       List.iter (generate_test_command_call test_name) seq;
6968       generate_test_command_call ~test test_name last
6969   | TestOutputTrue seq ->
6970       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6971       let seq, last = get_seq_last seq in
6972       let test () =
6973         pr "    if (!r) {\n";
6974         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6975           test_name;
6976         pr "      return -1;\n";
6977         pr "    }\n"
6978       in
6979       List.iter (generate_test_command_call test_name) seq;
6980       generate_test_command_call ~test test_name last
6981   | TestOutputFalse seq ->
6982       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6983       let seq, last = get_seq_last seq in
6984       let test () =
6985         pr "    if (r) {\n";
6986         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6987           test_name;
6988         pr "      return -1;\n";
6989         pr "    }\n"
6990       in
6991       List.iter (generate_test_command_call test_name) seq;
6992       generate_test_command_call ~test test_name last
6993   | TestOutputLength (seq, expected) ->
6994       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6995       let seq, last = get_seq_last seq in
6996       let test () =
6997         pr "    int j;\n";
6998         pr "    for (j = 0; j < %d; ++j)\n" expected;
6999         pr "      if (r[j] == NULL) {\n";
7000         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7001           test_name;
7002         pr "        print_strings (r);\n";
7003         pr "        return -1;\n";
7004         pr "      }\n";
7005         pr "    if (r[j] != NULL) {\n";
7006         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7007           test_name;
7008         pr "      print_strings (r);\n";
7009         pr "      return -1;\n";
7010         pr "    }\n"
7011       in
7012       List.iter (generate_test_command_call test_name) seq;
7013       generate_test_command_call ~test test_name last
7014   | TestOutputBuffer (seq, expected) ->
7015       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7016       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7017       let seq, last = get_seq_last seq in
7018       let len = String.length expected in
7019       let test () =
7020         pr "    if (size != %d) {\n" len;
7021         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7022         pr "      return -1;\n";
7023         pr "    }\n";
7024         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7025         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7026         pr "      return -1;\n";
7027         pr "    }\n"
7028       in
7029       List.iter (generate_test_command_call test_name) seq;
7030       generate_test_command_call ~test test_name last
7031   | TestOutputStruct (seq, checks) ->
7032       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7033       let seq, last = get_seq_last seq in
7034       let test () =
7035         List.iter (
7036           function
7037           | CompareWithInt (field, expected) ->
7038               pr "    if (r->%s != %d) {\n" field expected;
7039               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7040                 test_name field expected;
7041               pr "               (int) r->%s);\n" field;
7042               pr "      return -1;\n";
7043               pr "    }\n"
7044           | CompareWithIntOp (field, op, expected) ->
7045               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7046               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7047                 test_name field op expected;
7048               pr "               (int) r->%s);\n" field;
7049               pr "      return -1;\n";
7050               pr "    }\n"
7051           | CompareWithString (field, expected) ->
7052               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7053               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7054                 test_name field expected;
7055               pr "               r->%s);\n" field;
7056               pr "      return -1;\n";
7057               pr "    }\n"
7058           | CompareFieldsIntEq (field1, field2) ->
7059               pr "    if (r->%s != r->%s) {\n" field1 field2;
7060               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7061                 test_name field1 field2;
7062               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7063               pr "      return -1;\n";
7064               pr "    }\n"
7065           | CompareFieldsStrEq (field1, field2) ->
7066               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7067               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7068                 test_name field1 field2;
7069               pr "               r->%s, r->%s);\n" field1 field2;
7070               pr "      return -1;\n";
7071               pr "    }\n"
7072         ) checks
7073       in
7074       List.iter (generate_test_command_call test_name) seq;
7075       generate_test_command_call ~test test_name last
7076   | TestLastFail seq ->
7077       pr "  /* TestLastFail for %s (%d) */\n" name i;
7078       let seq, last = get_seq_last seq in
7079       List.iter (generate_test_command_call test_name) seq;
7080       generate_test_command_call test_name ~expect_error:true last
7081
7082 (* Generate the code to run a command, leaving the result in 'r'.
7083  * If you expect to get an error then you should set expect_error:true.
7084  *)
7085 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7086   match cmd with
7087   | [] -> assert false
7088   | name :: args ->
7089       (* Look up the command to find out what args/ret it has. *)
7090       let style =
7091         try
7092           let _, style, _, _, _, _, _ =
7093             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7094           style
7095         with Not_found ->
7096           failwithf "%s: in test, command %s was not found" test_name name in
7097
7098       if List.length (snd style) <> List.length args then
7099         failwithf "%s: in test, wrong number of args given to %s"
7100           test_name name;
7101
7102       pr "  {\n";
7103
7104       List.iter (
7105         function
7106         | OptString n, "NULL" -> ()
7107         | Pathname n, arg
7108         | Device n, arg
7109         | Dev_or_Path n, arg
7110         | String n, arg
7111         | OptString n, arg ->
7112             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7113         | Int _, _
7114         | Int64 _, _
7115         | Bool _, _
7116         | FileIn _, _ | FileOut _, _ -> ()
7117         | StringList n, "" | DeviceList n, "" ->
7118             pr "    const char *const %s[1] = { NULL };\n" n
7119         | StringList n, arg | DeviceList n, arg ->
7120             let strs = string_split " " arg in
7121             iteri (
7122               fun i str ->
7123                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7124             ) strs;
7125             pr "    const char *const %s[] = {\n" n;
7126             iteri (
7127               fun i _ -> pr "      %s_%d,\n" n i
7128             ) strs;
7129             pr "      NULL\n";
7130             pr "    };\n";
7131       ) (List.combine (snd style) args);
7132
7133       let error_code =
7134         match fst style with
7135         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7136         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7137         | RConstString _ | RConstOptString _ ->
7138             pr "    const char *r;\n"; "NULL"
7139         | RString _ -> pr "    char *r;\n"; "NULL"
7140         | RStringList _ | RHashtable _ ->
7141             pr "    char **r;\n";
7142             pr "    int i;\n";
7143             "NULL"
7144         | RStruct (_, typ) ->
7145             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7146         | RStructList (_, typ) ->
7147             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7148         | RBufferOut _ ->
7149             pr "    char *r;\n";
7150             pr "    size_t size;\n";
7151             "NULL" in
7152
7153       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7154       pr "    r = guestfs_%s (g" name;
7155
7156       (* Generate the parameters. *)
7157       List.iter (
7158         function
7159         | OptString _, "NULL" -> pr ", NULL"
7160         | Pathname n, _
7161         | Device n, _ | Dev_or_Path n, _
7162         | String n, _
7163         | OptString n, _ ->
7164             pr ", %s" n
7165         | FileIn _, arg | FileOut _, arg ->
7166             pr ", \"%s\"" (c_quote arg)
7167         | StringList n, _ | DeviceList n, _ ->
7168             pr ", (char **) %s" n
7169         | Int _, arg ->
7170             let i =
7171               try int_of_string arg
7172               with Failure "int_of_string" ->
7173                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7174             pr ", %d" i
7175         | Int64 _, arg ->
7176             let i =
7177               try Int64.of_string arg
7178               with Failure "int_of_string" ->
7179                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7180             pr ", %Ld" i
7181         | Bool _, arg ->
7182             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7183       ) (List.combine (snd style) args);
7184
7185       (match fst style with
7186        | RBufferOut _ -> pr ", &size"
7187        | _ -> ()
7188       );
7189
7190       pr ");\n";
7191
7192       if not expect_error then
7193         pr "    if (r == %s)\n" error_code
7194       else
7195         pr "    if (r != %s)\n" error_code;
7196       pr "      return -1;\n";
7197
7198       (* Insert the test code. *)
7199       (match test with
7200        | None -> ()
7201        | Some f -> f ()
7202       );
7203
7204       (match fst style with
7205        | RErr | RInt _ | RInt64 _ | RBool _
7206        | RConstString _ | RConstOptString _ -> ()
7207        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7208        | RStringList _ | RHashtable _ ->
7209            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7210            pr "      free (r[i]);\n";
7211            pr "    free (r);\n"
7212        | RStruct (_, typ) ->
7213            pr "    guestfs_free_%s (r);\n" typ
7214        | RStructList (_, typ) ->
7215            pr "    guestfs_free_%s_list (r);\n" typ
7216       );
7217
7218       pr "  }\n"
7219
7220 and c_quote str =
7221   let str = replace_str str "\r" "\\r" in
7222   let str = replace_str str "\n" "\\n" in
7223   let str = replace_str str "\t" "\\t" in
7224   let str = replace_str str "\000" "\\0" in
7225   str
7226
7227 (* Generate a lot of different functions for guestfish. *)
7228 and generate_fish_cmds () =
7229   generate_header CStyle GPLv2plus;
7230
7231   let all_functions =
7232     List.filter (
7233       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7234     ) all_functions in
7235   let all_functions_sorted =
7236     List.filter (
7237       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7238     ) all_functions_sorted in
7239
7240   pr "#include <config.h>\n";
7241   pr "\n";
7242   pr "#include <stdio.h>\n";
7243   pr "#include <stdlib.h>\n";
7244   pr "#include <string.h>\n";
7245   pr "#include <inttypes.h>\n";
7246   pr "\n";
7247   pr "#include <guestfs.h>\n";
7248   pr "#include \"c-ctype.h\"\n";
7249   pr "#include \"full-write.h\"\n";
7250   pr "#include \"xstrtol.h\"\n";
7251   pr "#include \"fish.h\"\n";
7252   pr "\n";
7253
7254   (* list_commands function, which implements guestfish -h *)
7255   pr "void list_commands (void)\n";
7256   pr "{\n";
7257   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7258   pr "  list_builtin_commands ();\n";
7259   List.iter (
7260     fun (name, _, _, flags, _, shortdesc, _) ->
7261       let name = replace_char name '_' '-' in
7262       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7263         name shortdesc
7264   ) all_functions_sorted;
7265   pr "  printf (\"    %%s\\n\",";
7266   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7267   pr "}\n";
7268   pr "\n";
7269
7270   (* display_command function, which implements guestfish -h cmd *)
7271   pr "void display_command (const char *cmd)\n";
7272   pr "{\n";
7273   List.iter (
7274     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7275       let name2 = replace_char name '_' '-' in
7276       let alias =
7277         try find_map (function FishAlias n -> Some n | _ -> None) flags
7278         with Not_found -> name in
7279       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7280       let synopsis =
7281         match snd style with
7282         | [] -> name2
7283         | args ->
7284             sprintf "%s %s"
7285               name2 (String.concat " " (List.map name_of_argt args)) in
7286
7287       let warnings =
7288         if List.mem ProtocolLimitWarning flags then
7289           ("\n\n" ^ protocol_limit_warning)
7290         else "" in
7291
7292       (* For DangerWillRobinson commands, we should probably have
7293        * guestfish prompt before allowing you to use them (especially
7294        * in interactive mode). XXX
7295        *)
7296       let warnings =
7297         warnings ^
7298           if List.mem DangerWillRobinson flags then
7299             ("\n\n" ^ danger_will_robinson)
7300           else "" in
7301
7302       let warnings =
7303         warnings ^
7304           match deprecation_notice flags with
7305           | None -> ""
7306           | Some txt -> "\n\n" ^ txt in
7307
7308       let describe_alias =
7309         if name <> alias then
7310           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7311         else "" in
7312
7313       pr "  if (";
7314       pr "STRCASEEQ (cmd, \"%s\")" name;
7315       if name <> name2 then
7316         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7317       if name <> alias then
7318         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7319       pr ")\n";
7320       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7321         name2 shortdesc
7322         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7323          "=head1 DESCRIPTION\n\n" ^
7324          longdesc ^ warnings ^ describe_alias);
7325       pr "  else\n"
7326   ) all_functions;
7327   pr "    display_builtin_command (cmd);\n";
7328   pr "}\n";
7329   pr "\n";
7330
7331   let emit_print_list_function typ =
7332     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7333       typ typ typ;
7334     pr "{\n";
7335     pr "  unsigned int i;\n";
7336     pr "\n";
7337     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7338     pr "    printf (\"[%%d] = {\\n\", i);\n";
7339     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7340     pr "    printf (\"}\\n\");\n";
7341     pr "  }\n";
7342     pr "}\n";
7343     pr "\n";
7344   in
7345
7346   (* print_* functions *)
7347   List.iter (
7348     fun (typ, cols) ->
7349       let needs_i =
7350         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7351
7352       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7353       pr "{\n";
7354       if needs_i then (
7355         pr "  unsigned int i;\n";
7356         pr "\n"
7357       );
7358       List.iter (
7359         function
7360         | name, FString ->
7361             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7362         | name, FUUID ->
7363             pr "  printf (\"%%s%s: \", indent);\n" name;
7364             pr "  for (i = 0; i < 32; ++i)\n";
7365             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7366             pr "  printf (\"\\n\");\n"
7367         | name, FBuffer ->
7368             pr "  printf (\"%%s%s: \", indent);\n" name;
7369             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7370             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7371             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7372             pr "    else\n";
7373             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7374             pr "  printf (\"\\n\");\n"
7375         | name, (FUInt64|FBytes) ->
7376             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7377               name typ name
7378         | name, FInt64 ->
7379             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7380               name typ name
7381         | name, FUInt32 ->
7382             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7383               name typ name
7384         | name, FInt32 ->
7385             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7386               name typ name
7387         | name, FChar ->
7388             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7389               name typ name
7390         | name, FOptPercent ->
7391             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7392               typ name name typ name;
7393             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7394       ) cols;
7395       pr "}\n";
7396       pr "\n";
7397   ) structs;
7398
7399   (* Emit a print_TYPE_list function definition only if that function is used. *)
7400   List.iter (
7401     function
7402     | typ, (RStructListOnly | RStructAndList) ->
7403         (* generate the function for typ *)
7404         emit_print_list_function typ
7405     | typ, _ -> () (* empty *)
7406   ) (rstructs_used_by all_functions);
7407
7408   (* Emit a print_TYPE function definition only if that function is used. *)
7409   List.iter (
7410     function
7411     | typ, (RStructOnly | RStructAndList) ->
7412         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7413         pr "{\n";
7414         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7415         pr "}\n";
7416         pr "\n";
7417     | typ, _ -> () (* empty *)
7418   ) (rstructs_used_by all_functions);
7419
7420   (* run_<action> actions *)
7421   List.iter (
7422     fun (name, style, _, flags, _, _, _) ->
7423       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7424       pr "{\n";
7425       (match fst style with
7426        | RErr
7427        | RInt _
7428        | RBool _ -> pr "  int r;\n"
7429        | RInt64 _ -> pr "  int64_t r;\n"
7430        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7431        | RString _ -> pr "  char *r;\n"
7432        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7433        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7434        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7435        | RBufferOut _ ->
7436            pr "  char *r;\n";
7437            pr "  size_t size;\n";
7438       );
7439       List.iter (
7440         function
7441         | Device n
7442         | String n
7443         | OptString n -> pr "  const char *%s;\n" n
7444         | Pathname n
7445         | Dev_or_Path n
7446         | FileIn n
7447         | FileOut n -> pr "  char *%s;\n" n
7448         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7449         | Bool n -> pr "  int %s;\n" n
7450         | Int n -> pr "  int %s;\n" n
7451         | Int64 n -> pr "  int64_t %s;\n" n
7452       ) (snd style);
7453
7454       (* Check and convert parameters. *)
7455       let argc_expected = List.length (snd style) in
7456       pr "  if (argc != %d) {\n" argc_expected;
7457       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7458         argc_expected;
7459       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7460       pr "    return -1;\n";
7461       pr "  }\n";
7462
7463       let parse_integer fn fntyp rtyp range name i =
7464         pr "  {\n";
7465         pr "    strtol_error xerr;\n";
7466         pr "    %s r;\n" fntyp;
7467         pr "\n";
7468         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7469         pr "    if (xerr != LONGINT_OK) {\n";
7470         pr "      fprintf (stderr,\n";
7471         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7472         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7473         pr "      return -1;\n";
7474         pr "    }\n";
7475         (match range with
7476          | None -> ()
7477          | Some (min, max, comment) ->
7478              pr "    /* %s */\n" comment;
7479              pr "    if (r < %s || r > %s) {\n" min max;
7480              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7481                name;
7482              pr "      return -1;\n";
7483              pr "    }\n";
7484              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7485         );
7486         pr "    %s = r;\n" name;
7487         pr "  }\n";
7488       in
7489
7490       iteri (
7491         fun i ->
7492           function
7493           | Device name
7494           | String name ->
7495               pr "  %s = argv[%d];\n" name i
7496           | Pathname name
7497           | Dev_or_Path name ->
7498               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7499               pr "  if (%s == NULL) return -1;\n" name
7500           | OptString name ->
7501               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7502                 name i i
7503           | FileIn name ->
7504               pr "  %s = file_in (argv[%d]);\n" name i;
7505               pr "  if (%s == NULL) return -1;\n" name
7506           | FileOut name ->
7507               pr "  %s = file_out (argv[%d]);\n" name i;
7508               pr "  if (%s == NULL) return -1;\n" name
7509           | StringList name | DeviceList name ->
7510               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7511               pr "  if (%s == NULL) return -1;\n" name;
7512           | Bool name ->
7513               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7514           | Int name ->
7515               let range =
7516                 let min = "(-(2LL<<30))"
7517                 and max = "((2LL<<30)-1)"
7518                 and comment =
7519                   "The Int type in the generator is a signed 31 bit int." in
7520                 Some (min, max, comment) in
7521               parse_integer "xstrtoll" "long long" "int" range name i
7522           | Int64 name ->
7523               parse_integer "xstrtoll" "long long" "int64_t" None name i
7524       ) (snd style);
7525
7526       (* Call C API function. *)
7527       let fn =
7528         try find_map (function FishAction n -> Some n | _ -> None) flags
7529         with Not_found -> sprintf "guestfs_%s" name in
7530       pr "  r = %s " fn;
7531       generate_c_call_args ~handle:"g" style;
7532       pr ";\n";
7533
7534       List.iter (
7535         function
7536         | Device name | String name
7537         | OptString name | Bool name
7538         | Int name | Int64 name -> ()
7539         | Pathname name | Dev_or_Path name | FileOut name ->
7540             pr "  free (%s);\n" name
7541         | FileIn name ->
7542             pr "  free_file_in (%s);\n" name
7543         | StringList name | DeviceList name ->
7544             pr "  free_strings (%s);\n" name
7545       ) (snd style);
7546
7547       (* Any output flags? *)
7548       let fish_output =
7549         let flags = filter_map (
7550           function FishOutput flag -> Some flag | _ -> None
7551         ) flags in
7552         match flags with
7553         | [] -> None
7554         | [f] -> Some f
7555         | _ ->
7556             failwithf "%s: more than one FishOutput flag is not allowed" name in
7557
7558       (* Check return value for errors and display command results. *)
7559       (match fst style with
7560        | RErr -> pr "  return r;\n"
7561        | RInt _ ->
7562            pr "  if (r == -1) return -1;\n";
7563            (match fish_output with
7564             | None ->
7565                 pr "  printf (\"%%d\\n\", r);\n";
7566             | Some FishOutputOctal ->
7567                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7568             | Some FishOutputHexadecimal ->
7569                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7570            pr "  return 0;\n"
7571        | RInt64 _ ->
7572            pr "  if (r == -1) return -1;\n";
7573            (match fish_output with
7574             | None ->
7575                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7576             | Some FishOutputOctal ->
7577                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7578             | Some FishOutputHexadecimal ->
7579                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7580            pr "  return 0;\n"
7581        | RBool _ ->
7582            pr "  if (r == -1) return -1;\n";
7583            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7584            pr "  return 0;\n"
7585        | RConstString _ ->
7586            pr "  if (r == NULL) return -1;\n";
7587            pr "  printf (\"%%s\\n\", r);\n";
7588            pr "  return 0;\n"
7589        | RConstOptString _ ->
7590            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7591            pr "  return 0;\n"
7592        | RString _ ->
7593            pr "  if (r == NULL) return -1;\n";
7594            pr "  printf (\"%%s\\n\", r);\n";
7595            pr "  free (r);\n";
7596            pr "  return 0;\n"
7597        | RStringList _ ->
7598            pr "  if (r == NULL) return -1;\n";
7599            pr "  print_strings (r);\n";
7600            pr "  free_strings (r);\n";
7601            pr "  return 0;\n"
7602        | RStruct (_, typ) ->
7603            pr "  if (r == NULL) return -1;\n";
7604            pr "  print_%s (r);\n" typ;
7605            pr "  guestfs_free_%s (r);\n" typ;
7606            pr "  return 0;\n"
7607        | RStructList (_, typ) ->
7608            pr "  if (r == NULL) return -1;\n";
7609            pr "  print_%s_list (r);\n" typ;
7610            pr "  guestfs_free_%s_list (r);\n" typ;
7611            pr "  return 0;\n"
7612        | RHashtable _ ->
7613            pr "  if (r == NULL) return -1;\n";
7614            pr "  print_table (r);\n";
7615            pr "  free_strings (r);\n";
7616            pr "  return 0;\n"
7617        | RBufferOut _ ->
7618            pr "  if (r == NULL) return -1;\n";
7619            pr "  if (full_write (1, r, size) != size) {\n";
7620            pr "    perror (\"write\");\n";
7621            pr "    free (r);\n";
7622            pr "    return -1;\n";
7623            pr "  }\n";
7624            pr "  free (r);\n";
7625            pr "  return 0;\n"
7626       );
7627       pr "}\n";
7628       pr "\n"
7629   ) all_functions;
7630
7631   (* run_action function *)
7632   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7633   pr "{\n";
7634   List.iter (
7635     fun (name, _, _, flags, _, _, _) ->
7636       let name2 = replace_char name '_' '-' in
7637       let alias =
7638         try find_map (function FishAlias n -> Some n | _ -> None) flags
7639         with Not_found -> name in
7640       pr "  if (";
7641       pr "STRCASEEQ (cmd, \"%s\")" name;
7642       if name <> name2 then
7643         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7644       if name <> alias then
7645         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7646       pr ")\n";
7647       pr "    return run_%s (cmd, argc, argv);\n" name;
7648       pr "  else\n";
7649   ) all_functions;
7650   pr "    {\n";
7651   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7652   pr "      if (command_num == 1)\n";
7653   pr "        extended_help_message ();\n";
7654   pr "      return -1;\n";
7655   pr "    }\n";
7656   pr "  return 0;\n";
7657   pr "}\n";
7658   pr "\n"
7659
7660 (* Readline completion for guestfish. *)
7661 and generate_fish_completion () =
7662   generate_header CStyle GPLv2plus;
7663
7664   let all_functions =
7665     List.filter (
7666       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7667     ) all_functions in
7668
7669   pr "\
7670 #include <config.h>
7671
7672 #include <stdio.h>
7673 #include <stdlib.h>
7674 #include <string.h>
7675
7676 #ifdef HAVE_LIBREADLINE
7677 #include <readline/readline.h>
7678 #endif
7679
7680 #include \"fish.h\"
7681
7682 #ifdef HAVE_LIBREADLINE
7683
7684 static const char *const commands[] = {
7685   BUILTIN_COMMANDS_FOR_COMPLETION,
7686 ";
7687
7688   (* Get the commands, including the aliases.  They don't need to be
7689    * sorted - the generator() function just does a dumb linear search.
7690    *)
7691   let commands =
7692     List.map (
7693       fun (name, _, _, flags, _, _, _) ->
7694         let name2 = replace_char name '_' '-' in
7695         let alias =
7696           try find_map (function FishAlias n -> Some n | _ -> None) flags
7697           with Not_found -> name in
7698
7699         if name <> alias then [name2; alias] else [name2]
7700     ) all_functions in
7701   let commands = List.flatten commands in
7702
7703   List.iter (pr "  \"%s\",\n") commands;
7704
7705   pr "  NULL
7706 };
7707
7708 static char *
7709 generator (const char *text, int state)
7710 {
7711   static int index, len;
7712   const char *name;
7713
7714   if (!state) {
7715     index = 0;
7716     len = strlen (text);
7717   }
7718
7719   rl_attempted_completion_over = 1;
7720
7721   while ((name = commands[index]) != NULL) {
7722     index++;
7723     if (STRCASEEQLEN (name, text, len))
7724       return strdup (name);
7725   }
7726
7727   return NULL;
7728 }
7729
7730 #endif /* HAVE_LIBREADLINE */
7731
7732 #ifdef HAVE_RL_COMPLETION_MATCHES
7733 #define RL_COMPLETION_MATCHES rl_completion_matches
7734 #else
7735 #ifdef HAVE_COMPLETION_MATCHES
7736 #define RL_COMPLETION_MATCHES completion_matches
7737 #endif
7738 #endif /* else just fail if we don't have either symbol */
7739
7740 char **
7741 do_completion (const char *text, int start, int end)
7742 {
7743   char **matches = NULL;
7744
7745 #ifdef HAVE_LIBREADLINE
7746   rl_completion_append_character = ' ';
7747
7748   if (start == 0)
7749     matches = RL_COMPLETION_MATCHES (text, generator);
7750   else if (complete_dest_paths)
7751     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7752 #endif
7753
7754   return matches;
7755 }
7756 ";
7757
7758 (* Generate the POD documentation for guestfish. *)
7759 and generate_fish_actions_pod () =
7760   let all_functions_sorted =
7761     List.filter (
7762       fun (_, _, _, flags, _, _, _) ->
7763         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7764     ) all_functions_sorted in
7765
7766   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7767
7768   List.iter (
7769     fun (name, style, _, flags, _, _, longdesc) ->
7770       let longdesc =
7771         Str.global_substitute rex (
7772           fun s ->
7773             let sub =
7774               try Str.matched_group 1 s
7775               with Not_found ->
7776                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7777             "C<" ^ replace_char sub '_' '-' ^ ">"
7778         ) longdesc in
7779       let name = replace_char name '_' '-' in
7780       let alias =
7781         try find_map (function FishAlias n -> Some n | _ -> None) flags
7782         with Not_found -> name in
7783
7784       pr "=head2 %s" name;
7785       if name <> alias then
7786         pr " | %s" alias;
7787       pr "\n";
7788       pr "\n";
7789       pr " %s" name;
7790       List.iter (
7791         function
7792         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7793         | OptString n -> pr " %s" n
7794         | StringList n | DeviceList n -> pr " '%s ...'" n
7795         | Bool _ -> pr " true|false"
7796         | Int n -> pr " %s" n
7797         | Int64 n -> pr " %s" n
7798         | FileIn n | FileOut n -> pr " (%s|-)" n
7799       ) (snd style);
7800       pr "\n";
7801       pr "\n";
7802       pr "%s\n\n" longdesc;
7803
7804       if List.exists (function FileIn _ | FileOut _ -> true
7805                       | _ -> false) (snd style) then
7806         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7807
7808       if List.mem ProtocolLimitWarning flags then
7809         pr "%s\n\n" protocol_limit_warning;
7810
7811       if List.mem DangerWillRobinson flags then
7812         pr "%s\n\n" danger_will_robinson;
7813
7814       match deprecation_notice flags with
7815       | None -> ()
7816       | Some txt -> pr "%s\n\n" txt
7817   ) all_functions_sorted
7818
7819 (* Generate a C function prototype. *)
7820 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7821     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7822     ?(prefix = "")
7823     ?handle name style =
7824   if extern then pr "extern ";
7825   if static then pr "static ";
7826   (match fst style with
7827    | RErr -> pr "int "
7828    | RInt _ -> pr "int "
7829    | RInt64 _ -> pr "int64_t "
7830    | RBool _ -> pr "int "
7831    | RConstString _ | RConstOptString _ -> pr "const char *"
7832    | RString _ | RBufferOut _ -> pr "char *"
7833    | RStringList _ | RHashtable _ -> pr "char **"
7834    | RStruct (_, typ) ->
7835        if not in_daemon then pr "struct guestfs_%s *" typ
7836        else pr "guestfs_int_%s *" typ
7837    | RStructList (_, typ) ->
7838        if not in_daemon then pr "struct guestfs_%s_list *" typ
7839        else pr "guestfs_int_%s_list *" typ
7840   );
7841   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7842   pr "%s%s (" prefix name;
7843   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7844     pr "void"
7845   else (
7846     let comma = ref false in
7847     (match handle with
7848      | None -> ()
7849      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7850     );
7851     let next () =
7852       if !comma then (
7853         if single_line then pr ", " else pr ",\n\t\t"
7854       );
7855       comma := true
7856     in
7857     List.iter (
7858       function
7859       | Pathname n
7860       | Device n | Dev_or_Path n
7861       | String n
7862       | OptString n ->
7863           next ();
7864           pr "const char *%s" n
7865       | StringList n | DeviceList n ->
7866           next ();
7867           pr "char *const *%s" n
7868       | Bool n -> next (); pr "int %s" n
7869       | Int n -> next (); pr "int %s" n
7870       | Int64 n -> next (); pr "int64_t %s" n
7871       | FileIn n
7872       | FileOut n ->
7873           if not in_daemon then (next (); pr "const char *%s" n)
7874     ) (snd style);
7875     if is_RBufferOut then (next (); pr "size_t *size_r");
7876   );
7877   pr ")";
7878   if semicolon then pr ";";
7879   if newline then pr "\n"
7880
7881 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7882 and generate_c_call_args ?handle ?(decl = false) style =
7883   pr "(";
7884   let comma = ref false in
7885   let next () =
7886     if !comma then pr ", ";
7887     comma := true
7888   in
7889   (match handle with
7890    | None -> ()
7891    | Some handle -> pr "%s" handle; comma := true
7892   );
7893   List.iter (
7894     fun arg ->
7895       next ();
7896       pr "%s" (name_of_argt arg)
7897   ) (snd style);
7898   (* For RBufferOut calls, add implicit &size parameter. *)
7899   if not decl then (
7900     match fst style with
7901     | RBufferOut _ ->
7902         next ();
7903         pr "&size"
7904     | _ -> ()
7905   );
7906   pr ")"
7907
7908 (* Generate the OCaml bindings interface. *)
7909 and generate_ocaml_mli () =
7910   generate_header OCamlStyle LGPLv2plus;
7911
7912   pr "\
7913 (** For API documentation you should refer to the C API
7914     in the guestfs(3) manual page.  The OCaml API uses almost
7915     exactly the same calls. *)
7916
7917 type t
7918 (** A [guestfs_h] handle. *)
7919
7920 exception Error of string
7921 (** This exception is raised when there is an error. *)
7922
7923 exception Handle_closed of string
7924 (** This exception is raised if you use a {!Guestfs.t} handle
7925     after calling {!close} on it.  The string is the name of
7926     the function. *)
7927
7928 val create : unit -> t
7929 (** Create a {!Guestfs.t} handle. *)
7930
7931 val close : t -> unit
7932 (** Close the {!Guestfs.t} handle and free up all resources used
7933     by it immediately.
7934
7935     Handles are closed by the garbage collector when they become
7936     unreferenced, but callers can call this in order to provide
7937     predictable cleanup. *)
7938
7939 ";
7940   generate_ocaml_structure_decls ();
7941
7942   (* The actions. *)
7943   List.iter (
7944     fun (name, style, _, _, _, shortdesc, _) ->
7945       generate_ocaml_prototype name style;
7946       pr "(** %s *)\n" shortdesc;
7947       pr "\n"
7948   ) all_functions_sorted
7949
7950 (* Generate the OCaml bindings implementation. *)
7951 and generate_ocaml_ml () =
7952   generate_header OCamlStyle LGPLv2plus;
7953
7954   pr "\
7955 type t
7956
7957 exception Error of string
7958 exception Handle_closed of string
7959
7960 external create : unit -> t = \"ocaml_guestfs_create\"
7961 external close : t -> unit = \"ocaml_guestfs_close\"
7962
7963 (* Give the exceptions names, so they can be raised from the C code. *)
7964 let () =
7965   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7966   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7967
7968 ";
7969
7970   generate_ocaml_structure_decls ();
7971
7972   (* The actions. *)
7973   List.iter (
7974     fun (name, style, _, _, _, shortdesc, _) ->
7975       generate_ocaml_prototype ~is_external:true name style;
7976   ) all_functions_sorted
7977
7978 (* Generate the OCaml bindings C implementation. *)
7979 and generate_ocaml_c () =
7980   generate_header CStyle LGPLv2plus;
7981
7982   pr "\
7983 #include <stdio.h>
7984 #include <stdlib.h>
7985 #include <string.h>
7986
7987 #include <caml/config.h>
7988 #include <caml/alloc.h>
7989 #include <caml/callback.h>
7990 #include <caml/fail.h>
7991 #include <caml/memory.h>
7992 #include <caml/mlvalues.h>
7993 #include <caml/signals.h>
7994
7995 #include <guestfs.h>
7996
7997 #include \"guestfs_c.h\"
7998
7999 /* Copy a hashtable of string pairs into an assoc-list.  We return
8000  * the list in reverse order, but hashtables aren't supposed to be
8001  * ordered anyway.
8002  */
8003 static CAMLprim value
8004 copy_table (char * const * argv)
8005 {
8006   CAMLparam0 ();
8007   CAMLlocal5 (rv, pairv, kv, vv, cons);
8008   int i;
8009
8010   rv = Val_int (0);
8011   for (i = 0; argv[i] != NULL; i += 2) {
8012     kv = caml_copy_string (argv[i]);
8013     vv = caml_copy_string (argv[i+1]);
8014     pairv = caml_alloc (2, 0);
8015     Store_field (pairv, 0, kv);
8016     Store_field (pairv, 1, vv);
8017     cons = caml_alloc (2, 0);
8018     Store_field (cons, 1, rv);
8019     rv = cons;
8020     Store_field (cons, 0, pairv);
8021   }
8022
8023   CAMLreturn (rv);
8024 }
8025
8026 ";
8027
8028   (* Struct copy functions. *)
8029
8030   let emit_ocaml_copy_list_function typ =
8031     pr "static CAMLprim value\n";
8032     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8033     pr "{\n";
8034     pr "  CAMLparam0 ();\n";
8035     pr "  CAMLlocal2 (rv, v);\n";
8036     pr "  unsigned int i;\n";
8037     pr "\n";
8038     pr "  if (%ss->len == 0)\n" typ;
8039     pr "    CAMLreturn (Atom (0));\n";
8040     pr "  else {\n";
8041     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8042     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8043     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8044     pr "      caml_modify (&Field (rv, i), v);\n";
8045     pr "    }\n";
8046     pr "    CAMLreturn (rv);\n";
8047     pr "  }\n";
8048     pr "}\n";
8049     pr "\n";
8050   in
8051
8052   List.iter (
8053     fun (typ, cols) ->
8054       let has_optpercent_col =
8055         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8056
8057       pr "static CAMLprim value\n";
8058       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8059       pr "{\n";
8060       pr "  CAMLparam0 ();\n";
8061       if has_optpercent_col then
8062         pr "  CAMLlocal3 (rv, v, v2);\n"
8063       else
8064         pr "  CAMLlocal2 (rv, v);\n";
8065       pr "\n";
8066       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8067       iteri (
8068         fun i col ->
8069           (match col with
8070            | name, FString ->
8071                pr "  v = caml_copy_string (%s->%s);\n" typ name
8072            | name, FBuffer ->
8073                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8074                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8075                  typ name typ name
8076            | name, FUUID ->
8077                pr "  v = caml_alloc_string (32);\n";
8078                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8079            | name, (FBytes|FInt64|FUInt64) ->
8080                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8081            | name, (FInt32|FUInt32) ->
8082                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8083            | name, FOptPercent ->
8084                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8085                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8086                pr "    v = caml_alloc (1, 0);\n";
8087                pr "    Store_field (v, 0, v2);\n";
8088                pr "  } else /* None */\n";
8089                pr "    v = Val_int (0);\n";
8090            | name, FChar ->
8091                pr "  v = Val_int (%s->%s);\n" typ name
8092           );
8093           pr "  Store_field (rv, %d, v);\n" i
8094       ) cols;
8095       pr "  CAMLreturn (rv);\n";
8096       pr "}\n";
8097       pr "\n";
8098   ) structs;
8099
8100   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8101   List.iter (
8102     function
8103     | typ, (RStructListOnly | RStructAndList) ->
8104         (* generate the function for typ *)
8105         emit_ocaml_copy_list_function typ
8106     | typ, _ -> () (* empty *)
8107   ) (rstructs_used_by all_functions);
8108
8109   (* The wrappers. *)
8110   List.iter (
8111     fun (name, style, _, _, _, _, _) ->
8112       pr "/* Automatically generated wrapper for function\n";
8113       pr " * ";
8114       generate_ocaml_prototype name style;
8115       pr " */\n";
8116       pr "\n";
8117
8118       let params =
8119         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8120
8121       let needs_extra_vs =
8122         match fst style with RConstOptString _ -> true | _ -> false in
8123
8124       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8125       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8126       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8127       pr "\n";
8128
8129       pr "CAMLprim value\n";
8130       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8131       List.iter (pr ", value %s") (List.tl params);
8132       pr ")\n";
8133       pr "{\n";
8134
8135       (match params with
8136        | [p1; p2; p3; p4; p5] ->
8137            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8138        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8139            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8140            pr "  CAMLxparam%d (%s);\n"
8141              (List.length rest) (String.concat ", " rest)
8142        | ps ->
8143            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8144       );
8145       if not needs_extra_vs then
8146         pr "  CAMLlocal1 (rv);\n"
8147       else
8148         pr "  CAMLlocal3 (rv, v, v2);\n";
8149       pr "\n";
8150
8151       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8152       pr "  if (g == NULL)\n";
8153       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8154       pr "\n";
8155
8156       List.iter (
8157         function
8158         | Pathname n
8159         | Device n | Dev_or_Path n
8160         | String n
8161         | FileIn n
8162         | FileOut n ->
8163             pr "  const char *%s = String_val (%sv);\n" n n
8164         | OptString n ->
8165             pr "  const char *%s =\n" n;
8166             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8167               n n
8168         | StringList n | DeviceList n ->
8169             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8170         | Bool n ->
8171             pr "  int %s = Bool_val (%sv);\n" n n
8172         | Int n ->
8173             pr "  int %s = Int_val (%sv);\n" n n
8174         | Int64 n ->
8175             pr "  int64_t %s = Int64_val (%sv);\n" n n
8176       ) (snd style);
8177       let error_code =
8178         match fst style with
8179         | RErr -> pr "  int r;\n"; "-1"
8180         | RInt _ -> pr "  int r;\n"; "-1"
8181         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8182         | RBool _ -> pr "  int r;\n"; "-1"
8183         | RConstString _ | RConstOptString _ ->
8184             pr "  const char *r;\n"; "NULL"
8185         | RString _ -> pr "  char *r;\n"; "NULL"
8186         | RStringList _ ->
8187             pr "  int i;\n";
8188             pr "  char **r;\n";
8189             "NULL"
8190         | RStruct (_, typ) ->
8191             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8192         | RStructList (_, typ) ->
8193             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8194         | RHashtable _ ->
8195             pr "  int i;\n";
8196             pr "  char **r;\n";
8197             "NULL"
8198         | RBufferOut _ ->
8199             pr "  char *r;\n";
8200             pr "  size_t size;\n";
8201             "NULL" in
8202       pr "\n";
8203
8204       pr "  caml_enter_blocking_section ();\n";
8205       pr "  r = guestfs_%s " name;
8206       generate_c_call_args ~handle:"g" style;
8207       pr ";\n";
8208       pr "  caml_leave_blocking_section ();\n";
8209
8210       List.iter (
8211         function
8212         | StringList n | DeviceList n ->
8213             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8214         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8215         | Bool _ | Int _ | Int64 _
8216         | FileIn _ | FileOut _ -> ()
8217       ) (snd style);
8218
8219       pr "  if (r == %s)\n" error_code;
8220       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8221       pr "\n";
8222
8223       (match fst style with
8224        | RErr -> pr "  rv = Val_unit;\n"
8225        | RInt _ -> pr "  rv = Val_int (r);\n"
8226        | RInt64 _ ->
8227            pr "  rv = caml_copy_int64 (r);\n"
8228        | RBool _ -> pr "  rv = Val_bool (r);\n"
8229        | RConstString _ ->
8230            pr "  rv = caml_copy_string (r);\n"
8231        | RConstOptString _ ->
8232            pr "  if (r) { /* Some string */\n";
8233            pr "    v = caml_alloc (1, 0);\n";
8234            pr "    v2 = caml_copy_string (r);\n";
8235            pr "    Store_field (v, 0, v2);\n";
8236            pr "  } else /* None */\n";
8237            pr "    v = Val_int (0);\n";
8238        | RString _ ->
8239            pr "  rv = caml_copy_string (r);\n";
8240            pr "  free (r);\n"
8241        | RStringList _ ->
8242            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8243            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8244            pr "  free (r);\n"
8245        | RStruct (_, typ) ->
8246            pr "  rv = copy_%s (r);\n" typ;
8247            pr "  guestfs_free_%s (r);\n" typ;
8248        | RStructList (_, typ) ->
8249            pr "  rv = copy_%s_list (r);\n" typ;
8250            pr "  guestfs_free_%s_list (r);\n" typ;
8251        | RHashtable _ ->
8252            pr "  rv = copy_table (r);\n";
8253            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8254            pr "  free (r);\n";
8255        | RBufferOut _ ->
8256            pr "  rv = caml_alloc_string (size);\n";
8257            pr "  memcpy (String_val (rv), r, size);\n";
8258       );
8259
8260       pr "  CAMLreturn (rv);\n";
8261       pr "}\n";
8262       pr "\n";
8263
8264       if List.length params > 5 then (
8265         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8266         pr "CAMLprim value ";
8267         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8268         pr "CAMLprim value\n";
8269         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8270         pr "{\n";
8271         pr "  return ocaml_guestfs_%s (argv[0]" name;
8272         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8273         pr ");\n";
8274         pr "}\n";
8275         pr "\n"
8276       )
8277   ) all_functions_sorted
8278
8279 and generate_ocaml_structure_decls () =
8280   List.iter (
8281     fun (typ, cols) ->
8282       pr "type %s = {\n" typ;
8283       List.iter (
8284         function
8285         | name, FString -> pr "  %s : string;\n" name
8286         | name, FBuffer -> pr "  %s : string;\n" name
8287         | name, FUUID -> pr "  %s : string;\n" name
8288         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8289         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8290         | name, FChar -> pr "  %s : char;\n" name
8291         | name, FOptPercent -> pr "  %s : float option;\n" name
8292       ) cols;
8293       pr "}\n";
8294       pr "\n"
8295   ) structs
8296
8297 and generate_ocaml_prototype ?(is_external = false) name style =
8298   if is_external then pr "external " else pr "val ";
8299   pr "%s : t -> " name;
8300   List.iter (
8301     function
8302     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8303     | OptString _ -> pr "string option -> "
8304     | StringList _ | DeviceList _ -> pr "string array -> "
8305     | Bool _ -> pr "bool -> "
8306     | Int _ -> pr "int -> "
8307     | Int64 _ -> pr "int64 -> "
8308   ) (snd style);
8309   (match fst style with
8310    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8311    | RInt _ -> pr "int"
8312    | RInt64 _ -> pr "int64"
8313    | RBool _ -> pr "bool"
8314    | RConstString _ -> pr "string"
8315    | RConstOptString _ -> pr "string option"
8316    | RString _ | RBufferOut _ -> pr "string"
8317    | RStringList _ -> pr "string array"
8318    | RStruct (_, typ) -> pr "%s" typ
8319    | RStructList (_, typ) -> pr "%s array" typ
8320    | RHashtable _ -> pr "(string * string) list"
8321   );
8322   if is_external then (
8323     pr " = ";
8324     if List.length (snd style) + 1 > 5 then
8325       pr "\"ocaml_guestfs_%s_byte\" " name;
8326     pr "\"ocaml_guestfs_%s\"" name
8327   );
8328   pr "\n"
8329
8330 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8331 and generate_perl_xs () =
8332   generate_header CStyle LGPLv2plus;
8333
8334   pr "\
8335 #include \"EXTERN.h\"
8336 #include \"perl.h\"
8337 #include \"XSUB.h\"
8338
8339 #include <guestfs.h>
8340
8341 #ifndef PRId64
8342 #define PRId64 \"lld\"
8343 #endif
8344
8345 static SV *
8346 my_newSVll(long long val) {
8347 #ifdef USE_64_BIT_ALL
8348   return newSViv(val);
8349 #else
8350   char buf[100];
8351   int len;
8352   len = snprintf(buf, 100, \"%%\" PRId64, val);
8353   return newSVpv(buf, len);
8354 #endif
8355 }
8356
8357 #ifndef PRIu64
8358 #define PRIu64 \"llu\"
8359 #endif
8360
8361 static SV *
8362 my_newSVull(unsigned long long val) {
8363 #ifdef USE_64_BIT_ALL
8364   return newSVuv(val);
8365 #else
8366   char buf[100];
8367   int len;
8368   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8369   return newSVpv(buf, len);
8370 #endif
8371 }
8372
8373 /* http://www.perlmonks.org/?node_id=680842 */
8374 static char **
8375 XS_unpack_charPtrPtr (SV *arg) {
8376   char **ret;
8377   AV *av;
8378   I32 i;
8379
8380   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8381     croak (\"array reference expected\");
8382
8383   av = (AV *)SvRV (arg);
8384   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8385   if (!ret)
8386     croak (\"malloc failed\");
8387
8388   for (i = 0; i <= av_len (av); i++) {
8389     SV **elem = av_fetch (av, i, 0);
8390
8391     if (!elem || !*elem)
8392       croak (\"missing element in list\");
8393
8394     ret[i] = SvPV_nolen (*elem);
8395   }
8396
8397   ret[i] = NULL;
8398
8399   return ret;
8400 }
8401
8402 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8403
8404 PROTOTYPES: ENABLE
8405
8406 guestfs_h *
8407 _create ()
8408    CODE:
8409       RETVAL = guestfs_create ();
8410       if (!RETVAL)
8411         croak (\"could not create guestfs handle\");
8412       guestfs_set_error_handler (RETVAL, NULL, NULL);
8413  OUTPUT:
8414       RETVAL
8415
8416 void
8417 DESTROY (g)
8418       guestfs_h *g;
8419  PPCODE:
8420       guestfs_close (g);
8421
8422 ";
8423
8424   List.iter (
8425     fun (name, style, _, _, _, _, _) ->
8426       (match fst style with
8427        | RErr -> pr "void\n"
8428        | RInt _ -> pr "SV *\n"
8429        | RInt64 _ -> pr "SV *\n"
8430        | RBool _ -> pr "SV *\n"
8431        | RConstString _ -> pr "SV *\n"
8432        | RConstOptString _ -> pr "SV *\n"
8433        | RString _ -> pr "SV *\n"
8434        | RBufferOut _ -> pr "SV *\n"
8435        | RStringList _
8436        | RStruct _ | RStructList _
8437        | RHashtable _ ->
8438            pr "void\n" (* all lists returned implictly on the stack *)
8439       );
8440       (* Call and arguments. *)
8441       pr "%s " name;
8442       generate_c_call_args ~handle:"g" ~decl:true style;
8443       pr "\n";
8444       pr "      guestfs_h *g;\n";
8445       iteri (
8446         fun i ->
8447           function
8448           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8449               pr "      char *%s;\n" n
8450           | OptString n ->
8451               (* http://www.perlmonks.org/?node_id=554277
8452                * Note that the implicit handle argument means we have
8453                * to add 1 to the ST(x) operator.
8454                *)
8455               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8456           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8457           | Bool n -> pr "      int %s;\n" n
8458           | Int n -> pr "      int %s;\n" n
8459           | Int64 n -> pr "      int64_t %s;\n" n
8460       ) (snd style);
8461
8462       let do_cleanups () =
8463         List.iter (
8464           function
8465           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8466           | Bool _ | Int _ | Int64 _
8467           | FileIn _ | FileOut _ -> ()
8468           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8469         ) (snd style)
8470       in
8471
8472       (* Code. *)
8473       (match fst style with
8474        | RErr ->
8475            pr "PREINIT:\n";
8476            pr "      int r;\n";
8477            pr " PPCODE:\n";
8478            pr "      r = guestfs_%s " name;
8479            generate_c_call_args ~handle:"g" style;
8480            pr ";\n";
8481            do_cleanups ();
8482            pr "      if (r == -1)\n";
8483            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8484        | RInt n
8485        | RBool n ->
8486            pr "PREINIT:\n";
8487            pr "      int %s;\n" n;
8488            pr "   CODE:\n";
8489            pr "      %s = guestfs_%s " n name;
8490            generate_c_call_args ~handle:"g" style;
8491            pr ";\n";
8492            do_cleanups ();
8493            pr "      if (%s == -1)\n" n;
8494            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8495            pr "      RETVAL = newSViv (%s);\n" n;
8496            pr " OUTPUT:\n";
8497            pr "      RETVAL\n"
8498        | RInt64 n ->
8499            pr "PREINIT:\n";
8500            pr "      int64_t %s;\n" n;
8501            pr "   CODE:\n";
8502            pr "      %s = guestfs_%s " n name;
8503            generate_c_call_args ~handle:"g" style;
8504            pr ";\n";
8505            do_cleanups ();
8506            pr "      if (%s == -1)\n" n;
8507            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8508            pr "      RETVAL = my_newSVll (%s);\n" n;
8509            pr " OUTPUT:\n";
8510            pr "      RETVAL\n"
8511        | RConstString n ->
8512            pr "PREINIT:\n";
8513            pr "      const char *%s;\n" n;
8514            pr "   CODE:\n";
8515            pr "      %s = guestfs_%s " n name;
8516            generate_c_call_args ~handle:"g" style;
8517            pr ";\n";
8518            do_cleanups ();
8519            pr "      if (%s == NULL)\n" n;
8520            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8521            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8522            pr " OUTPUT:\n";
8523            pr "      RETVAL\n"
8524        | RConstOptString n ->
8525            pr "PREINIT:\n";
8526            pr "      const char *%s;\n" n;
8527            pr "   CODE:\n";
8528            pr "      %s = guestfs_%s " n name;
8529            generate_c_call_args ~handle:"g" style;
8530            pr ";\n";
8531            do_cleanups ();
8532            pr "      if (%s == NULL)\n" n;
8533            pr "        RETVAL = &PL_sv_undef;\n";
8534            pr "      else\n";
8535            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8536            pr " OUTPUT:\n";
8537            pr "      RETVAL\n"
8538        | RString n ->
8539            pr "PREINIT:\n";
8540            pr "      char *%s;\n" n;
8541            pr "   CODE:\n";
8542            pr "      %s = guestfs_%s " n name;
8543            generate_c_call_args ~handle:"g" style;
8544            pr ";\n";
8545            do_cleanups ();
8546            pr "      if (%s == NULL)\n" n;
8547            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8548            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8549            pr "      free (%s);\n" n;
8550            pr " OUTPUT:\n";
8551            pr "      RETVAL\n"
8552        | RStringList n | RHashtable n ->
8553            pr "PREINIT:\n";
8554            pr "      char **%s;\n" n;
8555            pr "      int i, n;\n";
8556            pr " PPCODE:\n";
8557            pr "      %s = guestfs_%s " n name;
8558            generate_c_call_args ~handle:"g" style;
8559            pr ";\n";
8560            do_cleanups ();
8561            pr "      if (%s == NULL)\n" n;
8562            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8563            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8564            pr "      EXTEND (SP, n);\n";
8565            pr "      for (i = 0; i < n; ++i) {\n";
8566            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8567            pr "        free (%s[i]);\n" n;
8568            pr "      }\n";
8569            pr "      free (%s);\n" n;
8570        | RStruct (n, typ) ->
8571            let cols = cols_of_struct typ in
8572            generate_perl_struct_code typ cols name style n do_cleanups
8573        | RStructList (n, typ) ->
8574            let cols = cols_of_struct typ in
8575            generate_perl_struct_list_code typ cols name style n do_cleanups
8576        | RBufferOut n ->
8577            pr "PREINIT:\n";
8578            pr "      char *%s;\n" n;
8579            pr "      size_t size;\n";
8580            pr "   CODE:\n";
8581            pr "      %s = guestfs_%s " n name;
8582            generate_c_call_args ~handle:"g" style;
8583            pr ";\n";
8584            do_cleanups ();
8585            pr "      if (%s == NULL)\n" n;
8586            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8587            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8588            pr "      free (%s);\n" n;
8589            pr " OUTPUT:\n";
8590            pr "      RETVAL\n"
8591       );
8592
8593       pr "\n"
8594   ) all_functions
8595
8596 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8597   pr "PREINIT:\n";
8598   pr "      struct guestfs_%s_list *%s;\n" typ n;
8599   pr "      int i;\n";
8600   pr "      HV *hv;\n";
8601   pr " PPCODE:\n";
8602   pr "      %s = guestfs_%s " n name;
8603   generate_c_call_args ~handle:"g" style;
8604   pr ";\n";
8605   do_cleanups ();
8606   pr "      if (%s == NULL)\n" n;
8607   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8608   pr "      EXTEND (SP, %s->len);\n" n;
8609   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8610   pr "        hv = newHV ();\n";
8611   List.iter (
8612     function
8613     | name, FString ->
8614         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8615           name (String.length name) n name
8616     | name, FUUID ->
8617         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8618           name (String.length name) n name
8619     | name, FBuffer ->
8620         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8621           name (String.length name) n name n name
8622     | name, (FBytes|FUInt64) ->
8623         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8624           name (String.length name) n name
8625     | name, FInt64 ->
8626         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8627           name (String.length name) n name
8628     | name, (FInt32|FUInt32) ->
8629         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8630           name (String.length name) n name
8631     | name, FChar ->
8632         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8633           name (String.length name) n name
8634     | name, FOptPercent ->
8635         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8636           name (String.length name) n name
8637   ) cols;
8638   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8639   pr "      }\n";
8640   pr "      guestfs_free_%s_list (%s);\n" typ n
8641
8642 and generate_perl_struct_code typ cols name style n do_cleanups =
8643   pr "PREINIT:\n";
8644   pr "      struct guestfs_%s *%s;\n" typ n;
8645   pr " PPCODE:\n";
8646   pr "      %s = guestfs_%s " n name;
8647   generate_c_call_args ~handle:"g" style;
8648   pr ";\n";
8649   do_cleanups ();
8650   pr "      if (%s == NULL)\n" n;
8651   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8652   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8653   List.iter (
8654     fun ((name, _) as col) ->
8655       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8656
8657       match col with
8658       | name, FString ->
8659           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8660             n name
8661       | name, FBuffer ->
8662           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8663             n name n name
8664       | name, FUUID ->
8665           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8666             n name
8667       | name, (FBytes|FUInt64) ->
8668           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8669             n name
8670       | name, FInt64 ->
8671           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8672             n name
8673       | name, (FInt32|FUInt32) ->
8674           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8675             n name
8676       | name, FChar ->
8677           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8678             n name
8679       | name, FOptPercent ->
8680           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8681             n name
8682   ) cols;
8683   pr "      free (%s);\n" n
8684
8685 (* Generate Sys/Guestfs.pm. *)
8686 and generate_perl_pm () =
8687   generate_header HashStyle LGPLv2plus;
8688
8689   pr "\
8690 =pod
8691
8692 =head1 NAME
8693
8694 Sys::Guestfs - Perl bindings for libguestfs
8695
8696 =head1 SYNOPSIS
8697
8698  use Sys::Guestfs;
8699
8700  my $h = Sys::Guestfs->new ();
8701  $h->add_drive ('guest.img');
8702  $h->launch ();
8703  $h->mount ('/dev/sda1', '/');
8704  $h->touch ('/hello');
8705  $h->sync ();
8706
8707 =head1 DESCRIPTION
8708
8709 The C<Sys::Guestfs> module provides a Perl XS binding to the
8710 libguestfs API for examining and modifying virtual machine
8711 disk images.
8712
8713 Amongst the things this is good for: making batch configuration
8714 changes to guests, getting disk used/free statistics (see also:
8715 virt-df), migrating between virtualization systems (see also:
8716 virt-p2v), performing partial backups, performing partial guest
8717 clones, cloning guests and changing registry/UUID/hostname info, and
8718 much else besides.
8719
8720 Libguestfs uses Linux kernel and qemu code, and can access any type of
8721 guest filesystem that Linux and qemu can, including but not limited
8722 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8723 schemes, qcow, qcow2, vmdk.
8724
8725 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8726 LVs, what filesystem is in each LV, etc.).  It can also run commands
8727 in the context of the guest.  Also you can access filesystems over
8728 FUSE.
8729
8730 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8731 functions for using libguestfs from Perl, including integration
8732 with libvirt.
8733
8734 =head1 ERRORS
8735
8736 All errors turn into calls to C<croak> (see L<Carp(3)>).
8737
8738 =head1 METHODS
8739
8740 =over 4
8741
8742 =cut
8743
8744 package Sys::Guestfs;
8745
8746 use strict;
8747 use warnings;
8748
8749 require XSLoader;
8750 XSLoader::load ('Sys::Guestfs');
8751
8752 =item $h = Sys::Guestfs->new ();
8753
8754 Create a new guestfs handle.
8755
8756 =cut
8757
8758 sub new {
8759   my $proto = shift;
8760   my $class = ref ($proto) || $proto;
8761
8762   my $self = Sys::Guestfs::_create ();
8763   bless $self, $class;
8764   return $self;
8765 }
8766
8767 ";
8768
8769   (* Actions.  We only need to print documentation for these as
8770    * they are pulled in from the XS code automatically.
8771    *)
8772   List.iter (
8773     fun (name, style, _, flags, _, _, longdesc) ->
8774       if not (List.mem NotInDocs flags) then (
8775         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8776         pr "=item ";
8777         generate_perl_prototype name style;
8778         pr "\n\n";
8779         pr "%s\n\n" longdesc;
8780         if List.mem ProtocolLimitWarning flags then
8781           pr "%s\n\n" protocol_limit_warning;
8782         if List.mem DangerWillRobinson flags then
8783           pr "%s\n\n" danger_will_robinson;
8784         match deprecation_notice flags with
8785         | None -> ()
8786         | Some txt -> pr "%s\n\n" txt
8787       )
8788   ) all_functions_sorted;
8789
8790   (* End of file. *)
8791   pr "\
8792 =cut
8793
8794 1;
8795
8796 =back
8797
8798 =head1 COPYRIGHT
8799
8800 Copyright (C) %s Red Hat Inc.
8801
8802 =head1 LICENSE
8803
8804 Please see the file COPYING.LIB for the full license.
8805
8806 =head1 SEE ALSO
8807
8808 L<guestfs(3)>,
8809 L<guestfish(1)>,
8810 L<http://libguestfs.org>,
8811 L<Sys::Guestfs::Lib(3)>.
8812
8813 =cut
8814 " copyright_years
8815
8816 and generate_perl_prototype name style =
8817   (match fst style with
8818    | RErr -> ()
8819    | RBool n
8820    | RInt n
8821    | RInt64 n
8822    | RConstString n
8823    | RConstOptString n
8824    | RString n
8825    | RBufferOut n -> pr "$%s = " n
8826    | RStruct (n,_)
8827    | RHashtable n -> pr "%%%s = " n
8828    | RStringList n
8829    | RStructList (n,_) -> pr "@%s = " n
8830   );
8831   pr "$h->%s (" name;
8832   let comma = ref false in
8833   List.iter (
8834     fun arg ->
8835       if !comma then pr ", ";
8836       comma := true;
8837       match arg with
8838       | Pathname n | Device n | Dev_or_Path n | String n
8839       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8840           pr "$%s" n
8841       | StringList n | DeviceList n ->
8842           pr "\\@%s" n
8843   ) (snd style);
8844   pr ");"
8845
8846 (* Generate Python C module. *)
8847 and generate_python_c () =
8848   generate_header CStyle LGPLv2plus;
8849
8850   pr "\
8851 #include <Python.h>
8852
8853 #include <stdio.h>
8854 #include <stdlib.h>
8855 #include <assert.h>
8856
8857 #include \"guestfs.h\"
8858
8859 typedef struct {
8860   PyObject_HEAD
8861   guestfs_h *g;
8862 } Pyguestfs_Object;
8863
8864 static guestfs_h *
8865 get_handle (PyObject *obj)
8866 {
8867   assert (obj);
8868   assert (obj != Py_None);
8869   return ((Pyguestfs_Object *) obj)->g;
8870 }
8871
8872 static PyObject *
8873 put_handle (guestfs_h *g)
8874 {
8875   assert (g);
8876   return
8877     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8878 }
8879
8880 /* This list should be freed (but not the strings) after use. */
8881 static char **
8882 get_string_list (PyObject *obj)
8883 {
8884   int i, len;
8885   char **r;
8886
8887   assert (obj);
8888
8889   if (!PyList_Check (obj)) {
8890     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8891     return NULL;
8892   }
8893
8894   len = PyList_Size (obj);
8895   r = malloc (sizeof (char *) * (len+1));
8896   if (r == NULL) {
8897     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8898     return NULL;
8899   }
8900
8901   for (i = 0; i < len; ++i)
8902     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8903   r[len] = NULL;
8904
8905   return r;
8906 }
8907
8908 static PyObject *
8909 put_string_list (char * const * const argv)
8910 {
8911   PyObject *list;
8912   int argc, i;
8913
8914   for (argc = 0; argv[argc] != NULL; ++argc)
8915     ;
8916
8917   list = PyList_New (argc);
8918   for (i = 0; i < argc; ++i)
8919     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8920
8921   return list;
8922 }
8923
8924 static PyObject *
8925 put_table (char * const * const argv)
8926 {
8927   PyObject *list, *item;
8928   int argc, i;
8929
8930   for (argc = 0; argv[argc] != NULL; ++argc)
8931     ;
8932
8933   list = PyList_New (argc >> 1);
8934   for (i = 0; i < argc; i += 2) {
8935     item = PyTuple_New (2);
8936     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8937     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8938     PyList_SetItem (list, i >> 1, item);
8939   }
8940
8941   return list;
8942 }
8943
8944 static void
8945 free_strings (char **argv)
8946 {
8947   int argc;
8948
8949   for (argc = 0; argv[argc] != NULL; ++argc)
8950     free (argv[argc]);
8951   free (argv);
8952 }
8953
8954 static PyObject *
8955 py_guestfs_create (PyObject *self, PyObject *args)
8956 {
8957   guestfs_h *g;
8958
8959   g = guestfs_create ();
8960   if (g == NULL) {
8961     PyErr_SetString (PyExc_RuntimeError,
8962                      \"guestfs.create: failed to allocate handle\");
8963     return NULL;
8964   }
8965   guestfs_set_error_handler (g, NULL, NULL);
8966   return put_handle (g);
8967 }
8968
8969 static PyObject *
8970 py_guestfs_close (PyObject *self, PyObject *args)
8971 {
8972   PyObject *py_g;
8973   guestfs_h *g;
8974
8975   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8976     return NULL;
8977   g = get_handle (py_g);
8978
8979   guestfs_close (g);
8980
8981   Py_INCREF (Py_None);
8982   return Py_None;
8983 }
8984
8985 ";
8986
8987   let emit_put_list_function typ =
8988     pr "static PyObject *\n";
8989     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8990     pr "{\n";
8991     pr "  PyObject *list;\n";
8992     pr "  int i;\n";
8993     pr "\n";
8994     pr "  list = PyList_New (%ss->len);\n" typ;
8995     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8996     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8997     pr "  return list;\n";
8998     pr "};\n";
8999     pr "\n"
9000   in
9001
9002   (* Structures, turned into Python dictionaries. *)
9003   List.iter (
9004     fun (typ, cols) ->
9005       pr "static PyObject *\n";
9006       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9007       pr "{\n";
9008       pr "  PyObject *dict;\n";
9009       pr "\n";
9010       pr "  dict = PyDict_New ();\n";
9011       List.iter (
9012         function
9013         | name, FString ->
9014             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9015             pr "                        PyString_FromString (%s->%s));\n"
9016               typ name
9017         | name, FBuffer ->
9018             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9019             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9020               typ name typ name
9021         | name, FUUID ->
9022             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9023             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9024               typ name
9025         | name, (FBytes|FUInt64) ->
9026             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9027             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9028               typ name
9029         | name, FInt64 ->
9030             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9031             pr "                        PyLong_FromLongLong (%s->%s));\n"
9032               typ name
9033         | name, FUInt32 ->
9034             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9035             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9036               typ name
9037         | name, FInt32 ->
9038             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9039             pr "                        PyLong_FromLong (%s->%s));\n"
9040               typ name
9041         | name, FOptPercent ->
9042             pr "  if (%s->%s >= 0)\n" typ name;
9043             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9044             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9045               typ name;
9046             pr "  else {\n";
9047             pr "    Py_INCREF (Py_None);\n";
9048             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9049             pr "  }\n"
9050         | name, FChar ->
9051             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9052             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9053       ) cols;
9054       pr "  return dict;\n";
9055       pr "};\n";
9056       pr "\n";
9057
9058   ) structs;
9059
9060   (* Emit a put_TYPE_list function definition only if that function is used. *)
9061   List.iter (
9062     function
9063     | typ, (RStructListOnly | RStructAndList) ->
9064         (* generate the function for typ *)
9065         emit_put_list_function typ
9066     | typ, _ -> () (* empty *)
9067   ) (rstructs_used_by all_functions);
9068
9069   (* Python wrapper functions. *)
9070   List.iter (
9071     fun (name, style, _, _, _, _, _) ->
9072       pr "static PyObject *\n";
9073       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9074       pr "{\n";
9075
9076       pr "  PyObject *py_g;\n";
9077       pr "  guestfs_h *g;\n";
9078       pr "  PyObject *py_r;\n";
9079
9080       let error_code =
9081         match fst style with
9082         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9083         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9084         | RConstString _ | RConstOptString _ ->
9085             pr "  const char *r;\n"; "NULL"
9086         | RString _ -> pr "  char *r;\n"; "NULL"
9087         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9088         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9089         | RStructList (_, typ) ->
9090             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9091         | RBufferOut _ ->
9092             pr "  char *r;\n";
9093             pr "  size_t size;\n";
9094             "NULL" in
9095
9096       List.iter (
9097         function
9098         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9099             pr "  const char *%s;\n" n
9100         | OptString n -> pr "  const char *%s;\n" n
9101         | StringList n | DeviceList n ->
9102             pr "  PyObject *py_%s;\n" n;
9103             pr "  char **%s;\n" n
9104         | Bool n -> pr "  int %s;\n" n
9105         | Int n -> pr "  int %s;\n" n
9106         | Int64 n -> pr "  long long %s;\n" n
9107       ) (snd style);
9108
9109       pr "\n";
9110
9111       (* Convert the parameters. *)
9112       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9113       List.iter (
9114         function
9115         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9116         | OptString _ -> pr "z"
9117         | StringList _ | DeviceList _ -> pr "O"
9118         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9119         | Int _ -> pr "i"
9120         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9121                              * emulate C's int/long/long long in Python?
9122                              *)
9123       ) (snd style);
9124       pr ":guestfs_%s\",\n" name;
9125       pr "                         &py_g";
9126       List.iter (
9127         function
9128         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9129         | OptString n -> pr ", &%s" n
9130         | StringList n | DeviceList n -> pr ", &py_%s" n
9131         | Bool n -> pr ", &%s" n
9132         | Int n -> pr ", &%s" n
9133         | Int64 n -> pr ", &%s" n
9134       ) (snd style);
9135
9136       pr "))\n";
9137       pr "    return NULL;\n";
9138
9139       pr "  g = get_handle (py_g);\n";
9140       List.iter (
9141         function
9142         | Pathname _ | Device _ | Dev_or_Path _ | String _
9143         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9144         | StringList n | DeviceList n ->
9145             pr "  %s = get_string_list (py_%s);\n" n n;
9146             pr "  if (!%s) return NULL;\n" n
9147       ) (snd style);
9148
9149       pr "\n";
9150
9151       pr "  r = guestfs_%s " name;
9152       generate_c_call_args ~handle:"g" style;
9153       pr ";\n";
9154
9155       List.iter (
9156         function
9157         | Pathname _ | Device _ | Dev_or_Path _ | String _
9158         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9159         | StringList n | DeviceList n ->
9160             pr "  free (%s);\n" n
9161       ) (snd style);
9162
9163       pr "  if (r == %s) {\n" error_code;
9164       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9165       pr "    return NULL;\n";
9166       pr "  }\n";
9167       pr "\n";
9168
9169       (match fst style with
9170        | RErr ->
9171            pr "  Py_INCREF (Py_None);\n";
9172            pr "  py_r = Py_None;\n"
9173        | RInt _
9174        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9175        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9176        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9177        | RConstOptString _ ->
9178            pr "  if (r)\n";
9179            pr "    py_r = PyString_FromString (r);\n";
9180            pr "  else {\n";
9181            pr "    Py_INCREF (Py_None);\n";
9182            pr "    py_r = Py_None;\n";
9183            pr "  }\n"
9184        | RString _ ->
9185            pr "  py_r = PyString_FromString (r);\n";
9186            pr "  free (r);\n"
9187        | RStringList _ ->
9188            pr "  py_r = put_string_list (r);\n";
9189            pr "  free_strings (r);\n"
9190        | RStruct (_, typ) ->
9191            pr "  py_r = put_%s (r);\n" typ;
9192            pr "  guestfs_free_%s (r);\n" typ
9193        | RStructList (_, typ) ->
9194            pr "  py_r = put_%s_list (r);\n" typ;
9195            pr "  guestfs_free_%s_list (r);\n" typ
9196        | RHashtable n ->
9197            pr "  py_r = put_table (r);\n";
9198            pr "  free_strings (r);\n"
9199        | RBufferOut _ ->
9200            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9201            pr "  free (r);\n"
9202       );
9203
9204       pr "  return py_r;\n";
9205       pr "}\n";
9206       pr "\n"
9207   ) all_functions;
9208
9209   (* Table of functions. *)
9210   pr "static PyMethodDef methods[] = {\n";
9211   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9212   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9213   List.iter (
9214     fun (name, _, _, _, _, _, _) ->
9215       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9216         name name
9217   ) all_functions;
9218   pr "  { NULL, NULL, 0, NULL }\n";
9219   pr "};\n";
9220   pr "\n";
9221
9222   (* Init function. *)
9223   pr "\
9224 void
9225 initlibguestfsmod (void)
9226 {
9227   static int initialized = 0;
9228
9229   if (initialized) return;
9230   Py_InitModule ((char *) \"libguestfsmod\", methods);
9231   initialized = 1;
9232 }
9233 "
9234
9235 (* Generate Python module. *)
9236 and generate_python_py () =
9237   generate_header HashStyle LGPLv2plus;
9238
9239   pr "\
9240 u\"\"\"Python bindings for libguestfs
9241
9242 import guestfs
9243 g = guestfs.GuestFS ()
9244 g.add_drive (\"guest.img\")
9245 g.launch ()
9246 parts = g.list_partitions ()
9247
9248 The guestfs module provides a Python binding to the libguestfs API
9249 for examining and modifying virtual machine disk images.
9250
9251 Amongst the things this is good for: making batch configuration
9252 changes to guests, getting disk used/free statistics (see also:
9253 virt-df), migrating between virtualization systems (see also:
9254 virt-p2v), performing partial backups, performing partial guest
9255 clones, cloning guests and changing registry/UUID/hostname info, and
9256 much else besides.
9257
9258 Libguestfs uses Linux kernel and qemu code, and can access any type of
9259 guest filesystem that Linux and qemu can, including but not limited
9260 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9261 schemes, qcow, qcow2, vmdk.
9262
9263 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9264 LVs, what filesystem is in each LV, etc.).  It can also run commands
9265 in the context of the guest.  Also you can access filesystems over
9266 FUSE.
9267
9268 Errors which happen while using the API are turned into Python
9269 RuntimeError exceptions.
9270
9271 To create a guestfs handle you usually have to perform the following
9272 sequence of calls:
9273
9274 # Create the handle, call add_drive at least once, and possibly
9275 # several times if the guest has multiple block devices:
9276 g = guestfs.GuestFS ()
9277 g.add_drive (\"guest.img\")
9278
9279 # Launch the qemu subprocess and wait for it to become ready:
9280 g.launch ()
9281
9282 # Now you can issue commands, for example:
9283 logvols = g.lvs ()
9284
9285 \"\"\"
9286
9287 import libguestfsmod
9288
9289 class GuestFS:
9290     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9291
9292     def __init__ (self):
9293         \"\"\"Create a new libguestfs handle.\"\"\"
9294         self._o = libguestfsmod.create ()
9295
9296     def __del__ (self):
9297         libguestfsmod.close (self._o)
9298
9299 ";
9300
9301   List.iter (
9302     fun (name, style, _, flags, _, _, longdesc) ->
9303       pr "    def %s " name;
9304       generate_py_call_args ~handle:"self" (snd style);
9305       pr ":\n";
9306
9307       if not (List.mem NotInDocs flags) then (
9308         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9309         let doc =
9310           match fst style with
9311           | RErr | RInt _ | RInt64 _ | RBool _
9312           | RConstOptString _ | RConstString _
9313           | RString _ | RBufferOut _ -> doc
9314           | RStringList _ ->
9315               doc ^ "\n\nThis function returns a list of strings."
9316           | RStruct (_, typ) ->
9317               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9318           | RStructList (_, typ) ->
9319               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9320           | RHashtable _ ->
9321               doc ^ "\n\nThis function returns a dictionary." in
9322         let doc =
9323           if List.mem ProtocolLimitWarning flags then
9324             doc ^ "\n\n" ^ protocol_limit_warning
9325           else doc in
9326         let doc =
9327           if List.mem DangerWillRobinson flags then
9328             doc ^ "\n\n" ^ danger_will_robinson
9329           else doc in
9330         let doc =
9331           match deprecation_notice flags with
9332           | None -> doc
9333           | Some txt -> doc ^ "\n\n" ^ txt in
9334         let doc = pod2text ~width:60 name doc in
9335         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9336         let doc = String.concat "\n        " doc in
9337         pr "        u\"\"\"%s\"\"\"\n" doc;
9338       );
9339       pr "        return libguestfsmod.%s " name;
9340       generate_py_call_args ~handle:"self._o" (snd style);
9341       pr "\n";
9342       pr "\n";
9343   ) all_functions
9344
9345 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9346 and generate_py_call_args ~handle args =
9347   pr "(%s" handle;
9348   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9349   pr ")"
9350
9351 (* Useful if you need the longdesc POD text as plain text.  Returns a
9352  * list of lines.
9353  *
9354  * Because this is very slow (the slowest part of autogeneration),
9355  * we memoize the results.
9356  *)
9357 and pod2text ~width name longdesc =
9358   let key = width, name, longdesc in
9359   try Hashtbl.find pod2text_memo key
9360   with Not_found ->
9361     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9362     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9363     close_out chan;
9364     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9365     let chan = open_process_in cmd in
9366     let lines = ref [] in
9367     let rec loop i =
9368       let line = input_line chan in
9369       if i = 1 then             (* discard the first line of output *)
9370         loop (i+1)
9371       else (
9372         let line = triml line in
9373         lines := line :: !lines;
9374         loop (i+1)
9375       ) in
9376     let lines = try loop 1 with End_of_file -> List.rev !lines in
9377     unlink filename;
9378     (match close_process_in chan with
9379      | WEXITED 0 -> ()
9380      | WEXITED i ->
9381          failwithf "pod2text: process exited with non-zero status (%d)" i
9382      | WSIGNALED i | WSTOPPED i ->
9383          failwithf "pod2text: process signalled or stopped by signal %d" i
9384     );
9385     Hashtbl.add pod2text_memo key lines;
9386     pod2text_memo_updated ();
9387     lines
9388
9389 (* Generate ruby bindings. *)
9390 and generate_ruby_c () =
9391   generate_header CStyle LGPLv2plus;
9392
9393   pr "\
9394 #include <stdio.h>
9395 #include <stdlib.h>
9396
9397 #include <ruby.h>
9398
9399 #include \"guestfs.h\"
9400
9401 #include \"extconf.h\"
9402
9403 /* For Ruby < 1.9 */
9404 #ifndef RARRAY_LEN
9405 #define RARRAY_LEN(r) (RARRAY((r))->len)
9406 #endif
9407
9408 static VALUE m_guestfs;                 /* guestfs module */
9409 static VALUE c_guestfs;                 /* guestfs_h handle */
9410 static VALUE e_Error;                   /* used for all errors */
9411
9412 static void ruby_guestfs_free (void *p)
9413 {
9414   if (!p) return;
9415   guestfs_close ((guestfs_h *) p);
9416 }
9417
9418 static VALUE ruby_guestfs_create (VALUE m)
9419 {
9420   guestfs_h *g;
9421
9422   g = guestfs_create ();
9423   if (!g)
9424     rb_raise (e_Error, \"failed to create guestfs handle\");
9425
9426   /* Don't print error messages to stderr by default. */
9427   guestfs_set_error_handler (g, NULL, NULL);
9428
9429   /* Wrap it, and make sure the close function is called when the
9430    * handle goes away.
9431    */
9432   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9433 }
9434
9435 static VALUE ruby_guestfs_close (VALUE gv)
9436 {
9437   guestfs_h *g;
9438   Data_Get_Struct (gv, guestfs_h, g);
9439
9440   ruby_guestfs_free (g);
9441   DATA_PTR (gv) = NULL;
9442
9443   return Qnil;
9444 }
9445
9446 ";
9447
9448   List.iter (
9449     fun (name, style, _, _, _, _, _) ->
9450       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9451       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9452       pr ")\n";
9453       pr "{\n";
9454       pr "  guestfs_h *g;\n";
9455       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9456       pr "  if (!g)\n";
9457       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9458         name;
9459       pr "\n";
9460
9461       List.iter (
9462         function
9463         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9464             pr "  Check_Type (%sv, T_STRING);\n" n;
9465             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9466             pr "  if (!%s)\n" n;
9467             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9468             pr "              \"%s\", \"%s\");\n" n name
9469         | OptString n ->
9470             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9471         | StringList n | DeviceList n ->
9472             pr "  char **%s;\n" n;
9473             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9474             pr "  {\n";
9475             pr "    int i, len;\n";
9476             pr "    len = RARRAY_LEN (%sv);\n" n;
9477             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9478               n;
9479             pr "    for (i = 0; i < len; ++i) {\n";
9480             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9481             pr "      %s[i] = StringValueCStr (v);\n" n;
9482             pr "    }\n";
9483             pr "    %s[len] = NULL;\n" n;
9484             pr "  }\n";
9485         | Bool n ->
9486             pr "  int %s = RTEST (%sv);\n" n n
9487         | Int n ->
9488             pr "  int %s = NUM2INT (%sv);\n" n n
9489         | Int64 n ->
9490             pr "  long long %s = NUM2LL (%sv);\n" n n
9491       ) (snd style);
9492       pr "\n";
9493
9494       let error_code =
9495         match fst style with
9496         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9497         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9498         | RConstString _ | RConstOptString _ ->
9499             pr "  const char *r;\n"; "NULL"
9500         | RString _ -> pr "  char *r;\n"; "NULL"
9501         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9502         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9503         | RStructList (_, typ) ->
9504             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9505         | RBufferOut _ ->
9506             pr "  char *r;\n";
9507             pr "  size_t size;\n";
9508             "NULL" in
9509       pr "\n";
9510
9511       pr "  r = guestfs_%s " name;
9512       generate_c_call_args ~handle:"g" style;
9513       pr ";\n";
9514
9515       List.iter (
9516         function
9517         | Pathname _ | Device _ | Dev_or_Path _ | String _
9518         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9519         | StringList n | DeviceList n ->
9520             pr "  free (%s);\n" n
9521       ) (snd style);
9522
9523       pr "  if (r == %s)\n" error_code;
9524       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9525       pr "\n";
9526
9527       (match fst style with
9528        | RErr ->
9529            pr "  return Qnil;\n"
9530        | RInt _ | RBool _ ->
9531            pr "  return INT2NUM (r);\n"
9532        | RInt64 _ ->
9533            pr "  return ULL2NUM (r);\n"
9534        | RConstString _ ->
9535            pr "  return rb_str_new2 (r);\n";
9536        | RConstOptString _ ->
9537            pr "  if (r)\n";
9538            pr "    return rb_str_new2 (r);\n";
9539            pr "  else\n";
9540            pr "    return Qnil;\n";
9541        | RString _ ->
9542            pr "  VALUE rv = rb_str_new2 (r);\n";
9543            pr "  free (r);\n";
9544            pr "  return rv;\n";
9545        | RStringList _ ->
9546            pr "  int i, len = 0;\n";
9547            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9548            pr "  VALUE rv = rb_ary_new2 (len);\n";
9549            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9550            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9551            pr "    free (r[i]);\n";
9552            pr "  }\n";
9553            pr "  free (r);\n";
9554            pr "  return rv;\n"
9555        | RStruct (_, typ) ->
9556            let cols = cols_of_struct typ in
9557            generate_ruby_struct_code typ cols
9558        | RStructList (_, typ) ->
9559            let cols = cols_of_struct typ in
9560            generate_ruby_struct_list_code typ cols
9561        | RHashtable _ ->
9562            pr "  VALUE rv = rb_hash_new ();\n";
9563            pr "  int i;\n";
9564            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9565            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9566            pr "    free (r[i]);\n";
9567            pr "    free (r[i+1]);\n";
9568            pr "  }\n";
9569            pr "  free (r);\n";
9570            pr "  return rv;\n"
9571        | RBufferOut _ ->
9572            pr "  VALUE rv = rb_str_new (r, size);\n";
9573            pr "  free (r);\n";
9574            pr "  return rv;\n";
9575       );
9576
9577       pr "}\n";
9578       pr "\n"
9579   ) all_functions;
9580
9581   pr "\
9582 /* Initialize the module. */
9583 void Init__guestfs ()
9584 {
9585   m_guestfs = rb_define_module (\"Guestfs\");
9586   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9587   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9588
9589   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9590   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9591
9592 ";
9593   (* Define the rest of the methods. *)
9594   List.iter (
9595     fun (name, style, _, _, _, _, _) ->
9596       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9597       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9598   ) all_functions;
9599
9600   pr "}\n"
9601
9602 (* Ruby code to return a struct. *)
9603 and generate_ruby_struct_code typ cols =
9604   pr "  VALUE rv = rb_hash_new ();\n";
9605   List.iter (
9606     function
9607     | name, FString ->
9608         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9609     | name, FBuffer ->
9610         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9611     | name, FUUID ->
9612         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9613     | name, (FBytes|FUInt64) ->
9614         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9615     | name, FInt64 ->
9616         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9617     | name, FUInt32 ->
9618         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9619     | name, FInt32 ->
9620         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9621     | name, FOptPercent ->
9622         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9623     | name, FChar -> (* XXX wrong? *)
9624         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9625   ) cols;
9626   pr "  guestfs_free_%s (r);\n" typ;
9627   pr "  return rv;\n"
9628
9629 (* Ruby code to return a struct list. *)
9630 and generate_ruby_struct_list_code typ cols =
9631   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9632   pr "  int i;\n";
9633   pr "  for (i = 0; i < r->len; ++i) {\n";
9634   pr "    VALUE hv = rb_hash_new ();\n";
9635   List.iter (
9636     function
9637     | name, FString ->
9638         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9639     | name, FBuffer ->
9640         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
9641     | name, FUUID ->
9642         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9643     | name, (FBytes|FUInt64) ->
9644         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9645     | name, FInt64 ->
9646         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9647     | name, FUInt32 ->
9648         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9649     | name, FInt32 ->
9650         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9651     | name, FOptPercent ->
9652         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9653     | name, FChar -> (* XXX wrong? *)
9654         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9655   ) cols;
9656   pr "    rb_ary_push (rv, hv);\n";
9657   pr "  }\n";
9658   pr "  guestfs_free_%s_list (r);\n" typ;
9659   pr "  return rv;\n"
9660
9661 (* Generate Java bindings GuestFS.java file. *)
9662 and generate_java_java () =
9663   generate_header CStyle LGPLv2plus;
9664
9665   pr "\
9666 package com.redhat.et.libguestfs;
9667
9668 import java.util.HashMap;
9669 import com.redhat.et.libguestfs.LibGuestFSException;
9670 import com.redhat.et.libguestfs.PV;
9671 import com.redhat.et.libguestfs.VG;
9672 import com.redhat.et.libguestfs.LV;
9673 import com.redhat.et.libguestfs.Stat;
9674 import com.redhat.et.libguestfs.StatVFS;
9675 import com.redhat.et.libguestfs.IntBool;
9676 import com.redhat.et.libguestfs.Dirent;
9677
9678 /**
9679  * The GuestFS object is a libguestfs handle.
9680  *
9681  * @author rjones
9682  */
9683 public class GuestFS {
9684   // Load the native code.
9685   static {
9686     System.loadLibrary (\"guestfs_jni\");
9687   }
9688
9689   /**
9690    * The native guestfs_h pointer.
9691    */
9692   long g;
9693
9694   /**
9695    * Create a libguestfs handle.
9696    *
9697    * @throws LibGuestFSException
9698    */
9699   public GuestFS () throws LibGuestFSException
9700   {
9701     g = _create ();
9702   }
9703   private native long _create () throws LibGuestFSException;
9704
9705   /**
9706    * Close a libguestfs handle.
9707    *
9708    * You can also leave handles to be collected by the garbage
9709    * collector, but this method ensures that the resources used
9710    * by the handle are freed up immediately.  If you call any
9711    * other methods after closing the handle, you will get an
9712    * exception.
9713    *
9714    * @throws LibGuestFSException
9715    */
9716   public void close () throws LibGuestFSException
9717   {
9718     if (g != 0)
9719       _close (g);
9720     g = 0;
9721   }
9722   private native void _close (long g) throws LibGuestFSException;
9723
9724   public void finalize () throws LibGuestFSException
9725   {
9726     close ();
9727   }
9728
9729 ";
9730
9731   List.iter (
9732     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9733       if not (List.mem NotInDocs flags); then (
9734         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9735         let doc =
9736           if List.mem ProtocolLimitWarning flags then
9737             doc ^ "\n\n" ^ protocol_limit_warning
9738           else doc in
9739         let doc =
9740           if List.mem DangerWillRobinson flags then
9741             doc ^ "\n\n" ^ danger_will_robinson
9742           else doc in
9743         let doc =
9744           match deprecation_notice flags with
9745           | None -> doc
9746           | Some txt -> doc ^ "\n\n" ^ txt in
9747         let doc = pod2text ~width:60 name doc in
9748         let doc = List.map (            (* RHBZ#501883 *)
9749           function
9750           | "" -> "<p>"
9751           | nonempty -> nonempty
9752         ) doc in
9753         let doc = String.concat "\n   * " doc in
9754
9755         pr "  /**\n";
9756         pr "   * %s\n" shortdesc;
9757         pr "   * <p>\n";
9758         pr "   * %s\n" doc;
9759         pr "   * @throws LibGuestFSException\n";
9760         pr "   */\n";
9761         pr "  ";
9762       );
9763       generate_java_prototype ~public:true ~semicolon:false name style;
9764       pr "\n";
9765       pr "  {\n";
9766       pr "    if (g == 0)\n";
9767       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9768         name;
9769       pr "    ";
9770       if fst style <> RErr then pr "return ";
9771       pr "_%s " name;
9772       generate_java_call_args ~handle:"g" (snd style);
9773       pr ";\n";
9774       pr "  }\n";
9775       pr "  ";
9776       generate_java_prototype ~privat:true ~native:true name style;
9777       pr "\n";
9778       pr "\n";
9779   ) all_functions;
9780
9781   pr "}\n"
9782
9783 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9784 and generate_java_call_args ~handle args =
9785   pr "(%s" handle;
9786   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9787   pr ")"
9788
9789 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9790     ?(semicolon=true) name style =
9791   if privat then pr "private ";
9792   if public then pr "public ";
9793   if native then pr "native ";
9794
9795   (* return type *)
9796   (match fst style with
9797    | RErr -> pr "void ";
9798    | RInt _ -> pr "int ";
9799    | RInt64 _ -> pr "long ";
9800    | RBool _ -> pr "boolean ";
9801    | RConstString _ | RConstOptString _ | RString _
9802    | RBufferOut _ -> pr "String ";
9803    | RStringList _ -> pr "String[] ";
9804    | RStruct (_, typ) ->
9805        let name = java_name_of_struct typ in
9806        pr "%s " name;
9807    | RStructList (_, typ) ->
9808        let name = java_name_of_struct typ in
9809        pr "%s[] " name;
9810    | RHashtable _ -> pr "HashMap<String,String> ";
9811   );
9812
9813   if native then pr "_%s " name else pr "%s " name;
9814   pr "(";
9815   let needs_comma = ref false in
9816   if native then (
9817     pr "long g";
9818     needs_comma := true
9819   );
9820
9821   (* args *)
9822   List.iter (
9823     fun arg ->
9824       if !needs_comma then pr ", ";
9825       needs_comma := true;
9826
9827       match arg with
9828       | Pathname n
9829       | Device n | Dev_or_Path n
9830       | String n
9831       | OptString n
9832       | FileIn n
9833       | FileOut n ->
9834           pr "String %s" n
9835       | StringList n | DeviceList n ->
9836           pr "String[] %s" n
9837       | Bool n ->
9838           pr "boolean %s" n
9839       | Int n ->
9840           pr "int %s" n
9841       | Int64 n ->
9842           pr "long %s" n
9843   ) (snd style);
9844
9845   pr ")\n";
9846   pr "    throws LibGuestFSException";
9847   if semicolon then pr ";"
9848
9849 and generate_java_struct jtyp cols () =
9850   generate_header CStyle LGPLv2plus;
9851
9852   pr "\
9853 package com.redhat.et.libguestfs;
9854
9855 /**
9856  * Libguestfs %s structure.
9857  *
9858  * @author rjones
9859  * @see GuestFS
9860  */
9861 public class %s {
9862 " jtyp jtyp;
9863
9864   List.iter (
9865     function
9866     | name, FString
9867     | name, FUUID
9868     | name, FBuffer -> pr "  public String %s;\n" name
9869     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9870     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9871     | name, FChar -> pr "  public char %s;\n" name
9872     | name, FOptPercent ->
9873         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9874         pr "  public float %s;\n" name
9875   ) cols;
9876
9877   pr "}\n"
9878
9879 and generate_java_c () =
9880   generate_header CStyle LGPLv2plus;
9881
9882   pr "\
9883 #include <stdio.h>
9884 #include <stdlib.h>
9885 #include <string.h>
9886
9887 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9888 #include \"guestfs.h\"
9889
9890 /* Note that this function returns.  The exception is not thrown
9891  * until after the wrapper function returns.
9892  */
9893 static void
9894 throw_exception (JNIEnv *env, const char *msg)
9895 {
9896   jclass cl;
9897   cl = (*env)->FindClass (env,
9898                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9899   (*env)->ThrowNew (env, cl, msg);
9900 }
9901
9902 JNIEXPORT jlong JNICALL
9903 Java_com_redhat_et_libguestfs_GuestFS__1create
9904   (JNIEnv *env, jobject obj)
9905 {
9906   guestfs_h *g;
9907
9908   g = guestfs_create ();
9909   if (g == NULL) {
9910     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9911     return 0;
9912   }
9913   guestfs_set_error_handler (g, NULL, NULL);
9914   return (jlong) (long) g;
9915 }
9916
9917 JNIEXPORT void JNICALL
9918 Java_com_redhat_et_libguestfs_GuestFS__1close
9919   (JNIEnv *env, jobject obj, jlong jg)
9920 {
9921   guestfs_h *g = (guestfs_h *) (long) jg;
9922   guestfs_close (g);
9923 }
9924
9925 ";
9926
9927   List.iter (
9928     fun (name, style, _, _, _, _, _) ->
9929       pr "JNIEXPORT ";
9930       (match fst style with
9931        | RErr -> pr "void ";
9932        | RInt _ -> pr "jint ";
9933        | RInt64 _ -> pr "jlong ";
9934        | RBool _ -> pr "jboolean ";
9935        | RConstString _ | RConstOptString _ | RString _
9936        | RBufferOut _ -> pr "jstring ";
9937        | RStruct _ | RHashtable _ ->
9938            pr "jobject ";
9939        | RStringList _ | RStructList _ ->
9940            pr "jobjectArray ";
9941       );
9942       pr "JNICALL\n";
9943       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9944       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9945       pr "\n";
9946       pr "  (JNIEnv *env, jobject obj, jlong jg";
9947       List.iter (
9948         function
9949         | Pathname n
9950         | Device n | Dev_or_Path n
9951         | String n
9952         | OptString n
9953         | FileIn n
9954         | FileOut n ->
9955             pr ", jstring j%s" n
9956         | StringList n | DeviceList n ->
9957             pr ", jobjectArray j%s" n
9958         | Bool n ->
9959             pr ", jboolean j%s" n
9960         | Int n ->
9961             pr ", jint j%s" n
9962         | Int64 n ->
9963             pr ", jlong j%s" n
9964       ) (snd style);
9965       pr ")\n";
9966       pr "{\n";
9967       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9968       let error_code, no_ret =
9969         match fst style with
9970         | RErr -> pr "  int r;\n"; "-1", ""
9971         | RBool _
9972         | RInt _ -> pr "  int r;\n"; "-1", "0"
9973         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9974         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9975         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9976         | RString _ ->
9977             pr "  jstring jr;\n";
9978             pr "  char *r;\n"; "NULL", "NULL"
9979         | RStringList _ ->
9980             pr "  jobjectArray jr;\n";
9981             pr "  int r_len;\n";
9982             pr "  jclass cl;\n";
9983             pr "  jstring jstr;\n";
9984             pr "  char **r;\n"; "NULL", "NULL"
9985         | RStruct (_, typ) ->
9986             pr "  jobject jr;\n";
9987             pr "  jclass cl;\n";
9988             pr "  jfieldID fl;\n";
9989             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9990         | RStructList (_, typ) ->
9991             pr "  jobjectArray jr;\n";
9992             pr "  jclass cl;\n";
9993             pr "  jfieldID fl;\n";
9994             pr "  jobject jfl;\n";
9995             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9996         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9997         | RBufferOut _ ->
9998             pr "  jstring jr;\n";
9999             pr "  char *r;\n";
10000             pr "  size_t size;\n";
10001             "NULL", "NULL" in
10002       List.iter (
10003         function
10004         | Pathname n
10005         | Device n | Dev_or_Path n
10006         | String n
10007         | OptString n
10008         | FileIn n
10009         | FileOut n ->
10010             pr "  const char *%s;\n" n
10011         | StringList n | DeviceList n ->
10012             pr "  int %s_len;\n" n;
10013             pr "  const char **%s;\n" n
10014         | Bool n
10015         | Int n ->
10016             pr "  int %s;\n" n
10017         | Int64 n ->
10018             pr "  int64_t %s;\n" n
10019       ) (snd style);
10020
10021       let needs_i =
10022         (match fst style with
10023          | RStringList _ | RStructList _ -> true
10024          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10025          | RConstOptString _
10026          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10027           List.exists (function
10028                        | StringList _ -> true
10029                        | DeviceList _ -> true
10030                        | _ -> false) (snd style) in
10031       if needs_i then
10032         pr "  int i;\n";
10033
10034       pr "\n";
10035
10036       (* Get the parameters. *)
10037       List.iter (
10038         function
10039         | Pathname n
10040         | Device n | Dev_or_Path n
10041         | String n
10042         | FileIn n
10043         | FileOut n ->
10044             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10045         | OptString n ->
10046             (* This is completely undocumented, but Java null becomes
10047              * a NULL parameter.
10048              *)
10049             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10050         | StringList n | DeviceList n ->
10051             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10052             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10053             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10054             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10055               n;
10056             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10057             pr "  }\n";
10058             pr "  %s[%s_len] = NULL;\n" n n;
10059         | Bool n
10060         | Int n
10061         | Int64 n ->
10062             pr "  %s = j%s;\n" n n
10063       ) (snd style);
10064
10065       (* Make the call. *)
10066       pr "  r = guestfs_%s " name;
10067       generate_c_call_args ~handle:"g" style;
10068       pr ";\n";
10069
10070       (* Release the parameters. *)
10071       List.iter (
10072         function
10073         | Pathname n
10074         | Device n | Dev_or_Path n
10075         | String n
10076         | FileIn n
10077         | FileOut n ->
10078             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10079         | OptString n ->
10080             pr "  if (j%s)\n" n;
10081             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10082         | StringList n | DeviceList n ->
10083             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10084             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10085               n;
10086             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10087             pr "  }\n";
10088             pr "  free (%s);\n" n
10089         | Bool n
10090         | Int n
10091         | Int64 n -> ()
10092       ) (snd style);
10093
10094       (* Check for errors. *)
10095       pr "  if (r == %s) {\n" error_code;
10096       pr "    throw_exception (env, guestfs_last_error (g));\n";
10097       pr "    return %s;\n" no_ret;
10098       pr "  }\n";
10099
10100       (* Return value. *)
10101       (match fst style with
10102        | RErr -> ()
10103        | RInt _ -> pr "  return (jint) r;\n"
10104        | RBool _ -> pr "  return (jboolean) r;\n"
10105        | RInt64 _ -> pr "  return (jlong) r;\n"
10106        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10107        | RConstOptString _ ->
10108            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10109        | RString _ ->
10110            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10111            pr "  free (r);\n";
10112            pr "  return jr;\n"
10113        | RStringList _ ->
10114            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10115            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10116            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10117            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10118            pr "  for (i = 0; i < r_len; ++i) {\n";
10119            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10120            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10121            pr "    free (r[i]);\n";
10122            pr "  }\n";
10123            pr "  free (r);\n";
10124            pr "  return jr;\n"
10125        | RStruct (_, typ) ->
10126            let jtyp = java_name_of_struct typ in
10127            let cols = cols_of_struct typ in
10128            generate_java_struct_return typ jtyp cols
10129        | RStructList (_, typ) ->
10130            let jtyp = java_name_of_struct typ in
10131            let cols = cols_of_struct typ in
10132            generate_java_struct_list_return typ jtyp cols
10133        | RHashtable _ ->
10134            (* XXX *)
10135            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10136            pr "  return NULL;\n"
10137        | RBufferOut _ ->
10138            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10139            pr "  free (r);\n";
10140            pr "  return jr;\n"
10141       );
10142
10143       pr "}\n";
10144       pr "\n"
10145   ) all_functions
10146
10147 and generate_java_struct_return typ jtyp cols =
10148   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10149   pr "  jr = (*env)->AllocObject (env, cl);\n";
10150   List.iter (
10151     function
10152     | name, FString ->
10153         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10154         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10155     | name, FUUID ->
10156         pr "  {\n";
10157         pr "    char s[33];\n";
10158         pr "    memcpy (s, r->%s, 32);\n" name;
10159         pr "    s[32] = 0;\n";
10160         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10161         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10162         pr "  }\n";
10163     | name, FBuffer ->
10164         pr "  {\n";
10165         pr "    int len = r->%s_len;\n" name;
10166         pr "    char s[len+1];\n";
10167         pr "    memcpy (s, r->%s, len);\n" name;
10168         pr "    s[len] = 0;\n";
10169         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10170         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10171         pr "  }\n";
10172     | name, (FBytes|FUInt64|FInt64) ->
10173         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10174         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10175     | name, (FUInt32|FInt32) ->
10176         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10177         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10178     | name, FOptPercent ->
10179         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10180         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10181     | name, FChar ->
10182         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10183         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10184   ) cols;
10185   pr "  free (r);\n";
10186   pr "  return jr;\n"
10187
10188 and generate_java_struct_list_return typ jtyp cols =
10189   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10190   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10191   pr "  for (i = 0; i < r->len; ++i) {\n";
10192   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10193   List.iter (
10194     function
10195     | name, FString ->
10196         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10197         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10198     | name, FUUID ->
10199         pr "    {\n";
10200         pr "      char s[33];\n";
10201         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10202         pr "      s[32] = 0;\n";
10203         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10204         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10205         pr "    }\n";
10206     | name, FBuffer ->
10207         pr "    {\n";
10208         pr "      int len = r->val[i].%s_len;\n" name;
10209         pr "      char s[len+1];\n";
10210         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10211         pr "      s[len] = 0;\n";
10212         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10213         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10214         pr "    }\n";
10215     | name, (FBytes|FUInt64|FInt64) ->
10216         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10217         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10218     | name, (FUInt32|FInt32) ->
10219         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10220         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10221     | name, FOptPercent ->
10222         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10223         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10224     | name, FChar ->
10225         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10226         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10227   ) cols;
10228   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10229   pr "  }\n";
10230   pr "  guestfs_free_%s_list (r);\n" typ;
10231   pr "  return jr;\n"
10232
10233 and generate_java_makefile_inc () =
10234   generate_header HashStyle GPLv2plus;
10235
10236   pr "java_built_sources = \\\n";
10237   List.iter (
10238     fun (typ, jtyp) ->
10239         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10240   ) java_structs;
10241   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10242
10243 and generate_haskell_hs () =
10244   generate_header HaskellStyle LGPLv2plus;
10245
10246   (* XXX We only know how to generate partial FFI for Haskell
10247    * at the moment.  Please help out!
10248    *)
10249   let can_generate style =
10250     match style with
10251     | RErr, _
10252     | RInt _, _
10253     | RInt64 _, _ -> true
10254     | RBool _, _
10255     | RConstString _, _
10256     | RConstOptString _, _
10257     | RString _, _
10258     | RStringList _, _
10259     | RStruct _, _
10260     | RStructList _, _
10261     | RHashtable _, _
10262     | RBufferOut _, _ -> false in
10263
10264   pr "\
10265 {-# INCLUDE <guestfs.h> #-}
10266 {-# LANGUAGE ForeignFunctionInterface #-}
10267
10268 module Guestfs (
10269   create";
10270
10271   (* List out the names of the actions we want to export. *)
10272   List.iter (
10273     fun (name, style, _, _, _, _, _) ->
10274       if can_generate style then pr ",\n  %s" name
10275   ) all_functions;
10276
10277   pr "
10278   ) where
10279
10280 -- Unfortunately some symbols duplicate ones already present
10281 -- in Prelude.  We don't know which, so we hard-code a list
10282 -- here.
10283 import Prelude hiding (truncate)
10284
10285 import Foreign
10286 import Foreign.C
10287 import Foreign.C.Types
10288 import IO
10289 import Control.Exception
10290 import Data.Typeable
10291
10292 data GuestfsS = GuestfsS            -- represents the opaque C struct
10293 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10294 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10295
10296 -- XXX define properly later XXX
10297 data PV = PV
10298 data VG = VG
10299 data LV = LV
10300 data IntBool = IntBool
10301 data Stat = Stat
10302 data StatVFS = StatVFS
10303 data Hashtable = Hashtable
10304
10305 foreign import ccall unsafe \"guestfs_create\" c_create
10306   :: IO GuestfsP
10307 foreign import ccall unsafe \"&guestfs_close\" c_close
10308   :: FunPtr (GuestfsP -> IO ())
10309 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10310   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10311
10312 create :: IO GuestfsH
10313 create = do
10314   p <- c_create
10315   c_set_error_handler p nullPtr nullPtr
10316   h <- newForeignPtr c_close p
10317   return h
10318
10319 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10320   :: GuestfsP -> IO CString
10321
10322 -- last_error :: GuestfsH -> IO (Maybe String)
10323 -- last_error h = do
10324 --   str <- withForeignPtr h (\\p -> c_last_error p)
10325 --   maybePeek peekCString str
10326
10327 last_error :: GuestfsH -> IO (String)
10328 last_error h = do
10329   str <- withForeignPtr h (\\p -> c_last_error p)
10330   if (str == nullPtr)
10331     then return \"no error\"
10332     else peekCString str
10333
10334 ";
10335
10336   (* Generate wrappers for each foreign function. *)
10337   List.iter (
10338     fun (name, style, _, _, _, _, _) ->
10339       if can_generate style then (
10340         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10341         pr "  :: ";
10342         generate_haskell_prototype ~handle:"GuestfsP" style;
10343         pr "\n";
10344         pr "\n";
10345         pr "%s :: " name;
10346         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10347         pr "\n";
10348         pr "%s %s = do\n" name
10349           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10350         pr "  r <- ";
10351         (* Convert pointer arguments using with* functions. *)
10352         List.iter (
10353           function
10354           | FileIn n
10355           | FileOut n
10356           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10357           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10358           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10359           | Bool _ | Int _ | Int64 _ -> ()
10360         ) (snd style);
10361         (* Convert integer arguments. *)
10362         let args =
10363           List.map (
10364             function
10365             | Bool n -> sprintf "(fromBool %s)" n
10366             | Int n -> sprintf "(fromIntegral %s)" n
10367             | Int64 n -> sprintf "(fromIntegral %s)" n
10368             | FileIn n | FileOut n
10369             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10370           ) (snd style) in
10371         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10372           (String.concat " " ("p" :: args));
10373         (match fst style with
10374          | RErr | RInt _ | RInt64 _ | RBool _ ->
10375              pr "  if (r == -1)\n";
10376              pr "    then do\n";
10377              pr "      err <- last_error h\n";
10378              pr "      fail err\n";
10379          | RConstString _ | RConstOptString _ | RString _
10380          | RStringList _ | RStruct _
10381          | RStructList _ | RHashtable _ | RBufferOut _ ->
10382              pr "  if (r == nullPtr)\n";
10383              pr "    then do\n";
10384              pr "      err <- last_error h\n";
10385              pr "      fail err\n";
10386         );
10387         (match fst style with
10388          | RErr ->
10389              pr "    else return ()\n"
10390          | RInt _ ->
10391              pr "    else return (fromIntegral r)\n"
10392          | RInt64 _ ->
10393              pr "    else return (fromIntegral r)\n"
10394          | RBool _ ->
10395              pr "    else return (toBool r)\n"
10396          | RConstString _
10397          | RConstOptString _
10398          | RString _
10399          | RStringList _
10400          | RStruct _
10401          | RStructList _
10402          | RHashtable _
10403          | RBufferOut _ ->
10404              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10405         );
10406         pr "\n";
10407       )
10408   ) all_functions
10409
10410 and generate_haskell_prototype ~handle ?(hs = false) style =
10411   pr "%s -> " handle;
10412   let string = if hs then "String" else "CString" in
10413   let int = if hs then "Int" else "CInt" in
10414   let bool = if hs then "Bool" else "CInt" in
10415   let int64 = if hs then "Integer" else "Int64" in
10416   List.iter (
10417     fun arg ->
10418       (match arg with
10419        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10420        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10421        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10422        | Bool _ -> pr "%s" bool
10423        | Int _ -> pr "%s" int
10424        | Int64 _ -> pr "%s" int
10425        | FileIn _ -> pr "%s" string
10426        | FileOut _ -> pr "%s" string
10427       );
10428       pr " -> ";
10429   ) (snd style);
10430   pr "IO (";
10431   (match fst style with
10432    | RErr -> if not hs then pr "CInt"
10433    | RInt _ -> pr "%s" int
10434    | RInt64 _ -> pr "%s" int64
10435    | RBool _ -> pr "%s" bool
10436    | RConstString _ -> pr "%s" string
10437    | RConstOptString _ -> pr "Maybe %s" string
10438    | RString _ -> pr "%s" string
10439    | RStringList _ -> pr "[%s]" string
10440    | RStruct (_, typ) ->
10441        let name = java_name_of_struct typ in
10442        pr "%s" name
10443    | RStructList (_, typ) ->
10444        let name = java_name_of_struct typ in
10445        pr "[%s]" name
10446    | RHashtable _ -> pr "Hashtable"
10447    | RBufferOut _ -> pr "%s" string
10448   );
10449   pr ")"
10450
10451 and generate_csharp () =
10452   generate_header CPlusPlusStyle LGPLv2plus;
10453
10454   (* XXX Make this configurable by the C# assembly users. *)
10455   let library = "libguestfs.so.0" in
10456
10457   pr "\
10458 // These C# bindings are highly experimental at present.
10459 //
10460 // Firstly they only work on Linux (ie. Mono).  In order to get them
10461 // to work on Windows (ie. .Net) you would need to port the library
10462 // itself to Windows first.
10463 //
10464 // The second issue is that some calls are known to be incorrect and
10465 // can cause Mono to segfault.  Particularly: calls which pass or
10466 // return string[], or return any structure value.  This is because
10467 // we haven't worked out the correct way to do this from C#.
10468 //
10469 // The third issue is that when compiling you get a lot of warnings.
10470 // We are not sure whether the warnings are important or not.
10471 //
10472 // Fourthly we do not routinely build or test these bindings as part
10473 // of the make && make check cycle, which means that regressions might
10474 // go unnoticed.
10475 //
10476 // Suggestions and patches are welcome.
10477
10478 // To compile:
10479 //
10480 // gmcs Libguestfs.cs
10481 // mono Libguestfs.exe
10482 //
10483 // (You'll probably want to add a Test class / static main function
10484 // otherwise this won't do anything useful).
10485
10486 using System;
10487 using System.IO;
10488 using System.Runtime.InteropServices;
10489 using System.Runtime.Serialization;
10490 using System.Collections;
10491
10492 namespace Guestfs
10493 {
10494   class Error : System.ApplicationException
10495   {
10496     public Error (string message) : base (message) {}
10497     protected Error (SerializationInfo info, StreamingContext context) {}
10498   }
10499
10500   class Guestfs
10501   {
10502     IntPtr _handle;
10503
10504     [DllImport (\"%s\")]
10505     static extern IntPtr guestfs_create ();
10506
10507     public Guestfs ()
10508     {
10509       _handle = guestfs_create ();
10510       if (_handle == IntPtr.Zero)
10511         throw new Error (\"could not create guestfs handle\");
10512     }
10513
10514     [DllImport (\"%s\")]
10515     static extern void guestfs_close (IntPtr h);
10516
10517     ~Guestfs ()
10518     {
10519       guestfs_close (_handle);
10520     }
10521
10522     [DllImport (\"%s\")]
10523     static extern string guestfs_last_error (IntPtr h);
10524
10525 " library library library;
10526
10527   (* Generate C# structure bindings.  We prefix struct names with
10528    * underscore because C# cannot have conflicting struct names and
10529    * method names (eg. "class stat" and "stat").
10530    *)
10531   List.iter (
10532     fun (typ, cols) ->
10533       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10534       pr "    public class _%s {\n" typ;
10535       List.iter (
10536         function
10537         | name, FChar -> pr "      char %s;\n" name
10538         | name, FString -> pr "      string %s;\n" name
10539         | name, FBuffer ->
10540             pr "      uint %s_len;\n" name;
10541             pr "      string %s;\n" name
10542         | name, FUUID ->
10543             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10544             pr "      string %s;\n" name
10545         | name, FUInt32 -> pr "      uint %s;\n" name
10546         | name, FInt32 -> pr "      int %s;\n" name
10547         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10548         | name, FInt64 -> pr "      long %s;\n" name
10549         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10550       ) cols;
10551       pr "    }\n";
10552       pr "\n"
10553   ) structs;
10554
10555   (* Generate C# function bindings. *)
10556   List.iter (
10557     fun (name, style, _, _, _, shortdesc, _) ->
10558       let rec csharp_return_type () =
10559         match fst style with
10560         | RErr -> "void"
10561         | RBool n -> "bool"
10562         | RInt n -> "int"
10563         | RInt64 n -> "long"
10564         | RConstString n
10565         | RConstOptString n
10566         | RString n
10567         | RBufferOut n -> "string"
10568         | RStruct (_,n) -> "_" ^ n
10569         | RHashtable n -> "Hashtable"
10570         | RStringList n -> "string[]"
10571         | RStructList (_,n) -> sprintf "_%s[]" n
10572
10573       and c_return_type () =
10574         match fst style with
10575         | RErr
10576         | RBool _
10577         | RInt _ -> "int"
10578         | RInt64 _ -> "long"
10579         | RConstString _
10580         | RConstOptString _
10581         | RString _
10582         | RBufferOut _ -> "string"
10583         | RStruct (_,n) -> "_" ^ n
10584         | RHashtable _
10585         | RStringList _ -> "string[]"
10586         | RStructList (_,n) -> sprintf "_%s[]" n
10587
10588       and c_error_comparison () =
10589         match fst style with
10590         | RErr
10591         | RBool _
10592         | RInt _
10593         | RInt64 _ -> "== -1"
10594         | RConstString _
10595         | RConstOptString _
10596         | RString _
10597         | RBufferOut _
10598         | RStruct (_,_)
10599         | RHashtable _
10600         | RStringList _
10601         | RStructList (_,_) -> "== null"
10602
10603       and generate_extern_prototype () =
10604         pr "    static extern %s guestfs_%s (IntPtr h"
10605           (c_return_type ()) name;
10606         List.iter (
10607           function
10608           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10609           | FileIn n | FileOut n ->
10610               pr ", [In] string %s" n
10611           | StringList n | DeviceList n ->
10612               pr ", [In] string[] %s" n
10613           | Bool n ->
10614               pr ", bool %s" n
10615           | Int n ->
10616               pr ", int %s" n
10617           | Int64 n ->
10618               pr ", long %s" n
10619         ) (snd style);
10620         pr ");\n"
10621
10622       and generate_public_prototype () =
10623         pr "    public %s %s (" (csharp_return_type ()) name;
10624         let comma = ref false in
10625         let next () =
10626           if !comma then pr ", ";
10627           comma := true
10628         in
10629         List.iter (
10630           function
10631           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10632           | FileIn n | FileOut n ->
10633               next (); pr "string %s" n
10634           | StringList n | DeviceList n ->
10635               next (); pr "string[] %s" n
10636           | Bool n ->
10637               next (); pr "bool %s" n
10638           | Int n ->
10639               next (); pr "int %s" n
10640           | Int64 n ->
10641               next (); pr "long %s" n
10642         ) (snd style);
10643         pr ")\n"
10644
10645       and generate_call () =
10646         pr "guestfs_%s (_handle" name;
10647         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10648         pr ");\n";
10649       in
10650
10651       pr "    [DllImport (\"%s\")]\n" library;
10652       generate_extern_prototype ();
10653       pr "\n";
10654       pr "    /// <summary>\n";
10655       pr "    /// %s\n" shortdesc;
10656       pr "    /// </summary>\n";
10657       generate_public_prototype ();
10658       pr "    {\n";
10659       pr "      %s r;\n" (c_return_type ());
10660       pr "      r = ";
10661       generate_call ();
10662       pr "      if (r %s)\n" (c_error_comparison ());
10663       pr "        throw new Error (guestfs_last_error (_handle));\n";
10664       (match fst style with
10665        | RErr -> ()
10666        | RBool _ ->
10667            pr "      return r != 0 ? true : false;\n"
10668        | RHashtable _ ->
10669            pr "      Hashtable rr = new Hashtable ();\n";
10670            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10671            pr "        rr.Add (r[i], r[i+1]);\n";
10672            pr "      return rr;\n"
10673        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10674        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10675        | RStructList _ ->
10676            pr "      return r;\n"
10677       );
10678       pr "    }\n";
10679       pr "\n";
10680   ) all_functions_sorted;
10681
10682   pr "  }
10683 }
10684 "
10685
10686 and generate_bindtests () =
10687   generate_header CStyle LGPLv2plus;
10688
10689   pr "\
10690 #include <stdio.h>
10691 #include <stdlib.h>
10692 #include <inttypes.h>
10693 #include <string.h>
10694
10695 #include \"guestfs.h\"
10696 #include \"guestfs-internal.h\"
10697 #include \"guestfs-internal-actions.h\"
10698 #include \"guestfs_protocol.h\"
10699
10700 #define error guestfs_error
10701 #define safe_calloc guestfs_safe_calloc
10702 #define safe_malloc guestfs_safe_malloc
10703
10704 static void
10705 print_strings (char *const *argv)
10706 {
10707   int argc;
10708
10709   printf (\"[\");
10710   for (argc = 0; argv[argc] != NULL; ++argc) {
10711     if (argc > 0) printf (\", \");
10712     printf (\"\\\"%%s\\\"\", argv[argc]);
10713   }
10714   printf (\"]\\n\");
10715 }
10716
10717 /* The test0 function prints its parameters to stdout. */
10718 ";
10719
10720   let test0, tests =
10721     match test_functions with
10722     | [] -> assert false
10723     | test0 :: tests -> test0, tests in
10724
10725   let () =
10726     let (name, style, _, _, _, _, _) = test0 in
10727     generate_prototype ~extern:false ~semicolon:false ~newline:true
10728       ~handle:"g" ~prefix:"guestfs__" name style;
10729     pr "{\n";
10730     List.iter (
10731       function
10732       | Pathname n
10733       | Device n | Dev_or_Path n
10734       | String n
10735       | FileIn n
10736       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10737       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10738       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10739       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10740       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10741       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10742     ) (snd style);
10743     pr "  /* Java changes stdout line buffering so we need this: */\n";
10744     pr "  fflush (stdout);\n";
10745     pr "  return 0;\n";
10746     pr "}\n";
10747     pr "\n" in
10748
10749   List.iter (
10750     fun (name, style, _, _, _, _, _) ->
10751       if String.sub name (String.length name - 3) 3 <> "err" then (
10752         pr "/* Test normal return. */\n";
10753         generate_prototype ~extern:false ~semicolon:false ~newline:true
10754           ~handle:"g" ~prefix:"guestfs__" name style;
10755         pr "{\n";
10756         (match fst style with
10757          | RErr ->
10758              pr "  return 0;\n"
10759          | RInt _ ->
10760              pr "  int r;\n";
10761              pr "  sscanf (val, \"%%d\", &r);\n";
10762              pr "  return r;\n"
10763          | RInt64 _ ->
10764              pr "  int64_t r;\n";
10765              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10766              pr "  return r;\n"
10767          | RBool _ ->
10768              pr "  return STREQ (val, \"true\");\n"
10769          | RConstString _
10770          | RConstOptString _ ->
10771              (* Can't return the input string here.  Return a static
10772               * string so we ensure we get a segfault if the caller
10773               * tries to free it.
10774               *)
10775              pr "  return \"static string\";\n"
10776          | RString _ ->
10777              pr "  return strdup (val);\n"
10778          | RStringList _ ->
10779              pr "  char **strs;\n";
10780              pr "  int n, i;\n";
10781              pr "  sscanf (val, \"%%d\", &n);\n";
10782              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10783              pr "  for (i = 0; i < n; ++i) {\n";
10784              pr "    strs[i] = safe_malloc (g, 16);\n";
10785              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10786              pr "  }\n";
10787              pr "  strs[n] = NULL;\n";
10788              pr "  return strs;\n"
10789          | RStruct (_, typ) ->
10790              pr "  struct guestfs_%s *r;\n" typ;
10791              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10792              pr "  return r;\n"
10793          | RStructList (_, typ) ->
10794              pr "  struct guestfs_%s_list *r;\n" typ;
10795              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10796              pr "  sscanf (val, \"%%d\", &r->len);\n";
10797              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10798              pr "  return r;\n"
10799          | RHashtable _ ->
10800              pr "  char **strs;\n";
10801              pr "  int n, i;\n";
10802              pr "  sscanf (val, \"%%d\", &n);\n";
10803              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10804              pr "  for (i = 0; i < n; ++i) {\n";
10805              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10806              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10807              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10808              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10809              pr "  }\n";
10810              pr "  strs[n*2] = NULL;\n";
10811              pr "  return strs;\n"
10812          | RBufferOut _ ->
10813              pr "  return strdup (val);\n"
10814         );
10815         pr "}\n";
10816         pr "\n"
10817       ) else (
10818         pr "/* Test error return. */\n";
10819         generate_prototype ~extern:false ~semicolon:false ~newline:true
10820           ~handle:"g" ~prefix:"guestfs__" name style;
10821         pr "{\n";
10822         pr "  error (g, \"error\");\n";
10823         (match fst style with
10824          | RErr | RInt _ | RInt64 _ | RBool _ ->
10825              pr "  return -1;\n"
10826          | RConstString _ | RConstOptString _
10827          | RString _ | RStringList _ | RStruct _
10828          | RStructList _
10829          | RHashtable _
10830          | RBufferOut _ ->
10831              pr "  return NULL;\n"
10832         );
10833         pr "}\n";
10834         pr "\n"
10835       )
10836   ) tests
10837
10838 and generate_ocaml_bindtests () =
10839   generate_header OCamlStyle GPLv2plus;
10840
10841   pr "\
10842 let () =
10843   let g = Guestfs.create () in
10844 ";
10845
10846   let mkargs args =
10847     String.concat " " (
10848       List.map (
10849         function
10850         | CallString s -> "\"" ^ s ^ "\""
10851         | CallOptString None -> "None"
10852         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10853         | CallStringList xs ->
10854             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10855         | CallInt i when i >= 0 -> string_of_int i
10856         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10857         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10858         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10859         | CallBool b -> string_of_bool b
10860       ) args
10861     )
10862   in
10863
10864   generate_lang_bindtests (
10865     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10866   );
10867
10868   pr "print_endline \"EOF\"\n"
10869
10870 and generate_perl_bindtests () =
10871   pr "#!/usr/bin/perl -w\n";
10872   generate_header HashStyle GPLv2plus;
10873
10874   pr "\
10875 use strict;
10876
10877 use Sys::Guestfs;
10878
10879 my $g = Sys::Guestfs->new ();
10880 ";
10881
10882   let mkargs args =
10883     String.concat ", " (
10884       List.map (
10885         function
10886         | CallString s -> "\"" ^ s ^ "\""
10887         | CallOptString None -> "undef"
10888         | CallOptString (Some s) -> sprintf "\"%s\"" s
10889         | CallStringList xs ->
10890             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10891         | CallInt i -> string_of_int i
10892         | CallInt64 i -> Int64.to_string i
10893         | CallBool b -> if b then "1" else "0"
10894       ) args
10895     )
10896   in
10897
10898   generate_lang_bindtests (
10899     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10900   );
10901
10902   pr "print \"EOF\\n\"\n"
10903
10904 and generate_python_bindtests () =
10905   generate_header HashStyle GPLv2plus;
10906
10907   pr "\
10908 import guestfs
10909
10910 g = guestfs.GuestFS ()
10911 ";
10912
10913   let mkargs args =
10914     String.concat ", " (
10915       List.map (
10916         function
10917         | CallString s -> "\"" ^ s ^ "\""
10918         | CallOptString None -> "None"
10919         | CallOptString (Some s) -> sprintf "\"%s\"" s
10920         | CallStringList xs ->
10921             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10922         | CallInt i -> string_of_int i
10923         | CallInt64 i -> Int64.to_string i
10924         | CallBool b -> if b then "1" else "0"
10925       ) args
10926     )
10927   in
10928
10929   generate_lang_bindtests (
10930     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10931   );
10932
10933   pr "print \"EOF\"\n"
10934
10935 and generate_ruby_bindtests () =
10936   generate_header HashStyle GPLv2plus;
10937
10938   pr "\
10939 require 'guestfs'
10940
10941 g = Guestfs::create()
10942 ";
10943
10944   let mkargs args =
10945     String.concat ", " (
10946       List.map (
10947         function
10948         | CallString s -> "\"" ^ s ^ "\""
10949         | CallOptString None -> "nil"
10950         | CallOptString (Some s) -> sprintf "\"%s\"" s
10951         | CallStringList xs ->
10952             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10953         | CallInt i -> string_of_int i
10954         | CallInt64 i -> Int64.to_string i
10955         | CallBool b -> string_of_bool b
10956       ) args
10957     )
10958   in
10959
10960   generate_lang_bindtests (
10961     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10962   );
10963
10964   pr "print \"EOF\\n\"\n"
10965
10966 and generate_java_bindtests () =
10967   generate_header CStyle GPLv2plus;
10968
10969   pr "\
10970 import com.redhat.et.libguestfs.*;
10971
10972 public class Bindtests {
10973     public static void main (String[] argv)
10974     {
10975         try {
10976             GuestFS g = new GuestFS ();
10977 ";
10978
10979   let mkargs args =
10980     String.concat ", " (
10981       List.map (
10982         function
10983         | CallString s -> "\"" ^ s ^ "\""
10984         | CallOptString None -> "null"
10985         | CallOptString (Some s) -> sprintf "\"%s\"" s
10986         | CallStringList xs ->
10987             "new String[]{" ^
10988               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10989         | CallInt i -> string_of_int i
10990         | CallInt64 i -> Int64.to_string i
10991         | CallBool b -> string_of_bool b
10992       ) args
10993     )
10994   in
10995
10996   generate_lang_bindtests (
10997     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10998   );
10999
11000   pr "
11001             System.out.println (\"EOF\");
11002         }
11003         catch (Exception exn) {
11004             System.err.println (exn);
11005             System.exit (1);
11006         }
11007     }
11008 }
11009 "
11010
11011 and generate_haskell_bindtests () =
11012   generate_header HaskellStyle GPLv2plus;
11013
11014   pr "\
11015 module Bindtests where
11016 import qualified Guestfs
11017
11018 main = do
11019   g <- Guestfs.create
11020 ";
11021
11022   let mkargs args =
11023     String.concat " " (
11024       List.map (
11025         function
11026         | CallString s -> "\"" ^ s ^ "\""
11027         | CallOptString None -> "Nothing"
11028         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11029         | CallStringList xs ->
11030             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11031         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11032         | CallInt i -> string_of_int i
11033         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11034         | CallInt64 i -> Int64.to_string i
11035         | CallBool true -> "True"
11036         | CallBool false -> "False"
11037       ) args
11038     )
11039   in
11040
11041   generate_lang_bindtests (
11042     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11043   );
11044
11045   pr "  putStrLn \"EOF\"\n"
11046
11047 (* Language-independent bindings tests - we do it this way to
11048  * ensure there is parity in testing bindings across all languages.
11049  *)
11050 and generate_lang_bindtests call =
11051   call "test0" [CallString "abc"; CallOptString (Some "def");
11052                 CallStringList []; CallBool false;
11053                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11054   call "test0" [CallString "abc"; CallOptString None;
11055                 CallStringList []; CallBool false;
11056                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11057   call "test0" [CallString ""; CallOptString (Some "def");
11058                 CallStringList []; CallBool false;
11059                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11060   call "test0" [CallString ""; CallOptString (Some "");
11061                 CallStringList []; CallBool false;
11062                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11063   call "test0" [CallString "abc"; CallOptString (Some "def");
11064                 CallStringList ["1"]; CallBool false;
11065                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11066   call "test0" [CallString "abc"; CallOptString (Some "def");
11067                 CallStringList ["1"; "2"]; CallBool false;
11068                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11069   call "test0" [CallString "abc"; CallOptString (Some "def");
11070                 CallStringList ["1"]; CallBool true;
11071                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11072   call "test0" [CallString "abc"; CallOptString (Some "def");
11073                 CallStringList ["1"]; CallBool false;
11074                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11075   call "test0" [CallString "abc"; CallOptString (Some "def");
11076                 CallStringList ["1"]; CallBool false;
11077                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11078   call "test0" [CallString "abc"; CallOptString (Some "def");
11079                 CallStringList ["1"]; CallBool false;
11080                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11081   call "test0" [CallString "abc"; CallOptString (Some "def");
11082                 CallStringList ["1"]; CallBool false;
11083                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11084   call "test0" [CallString "abc"; CallOptString (Some "def");
11085                 CallStringList ["1"]; CallBool false;
11086                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11087   call "test0" [CallString "abc"; CallOptString (Some "def");
11088                 CallStringList ["1"]; CallBool false;
11089                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11090
11091 (* XXX Add here tests of the return and error functions. *)
11092
11093 (* Code to generator bindings for virt-inspector.  Currently only
11094  * implemented for OCaml code (for virt-p2v 2.0).
11095  *)
11096 let rng_input = "inspector/virt-inspector.rng"
11097
11098 (* Read the input file and parse it into internal structures.  This is
11099  * by no means a complete RELAX NG parser, but is just enough to be
11100  * able to parse the specific input file.
11101  *)
11102 type rng =
11103   | Element of string * rng list        (* <element name=name/> *)
11104   | Attribute of string * rng list        (* <attribute name=name/> *)
11105   | Interleave of rng list                (* <interleave/> *)
11106   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11107   | OneOrMore of rng                        (* <oneOrMore/> *)
11108   | Optional of rng                        (* <optional/> *)
11109   | Choice of string list                (* <choice><value/>*</choice> *)
11110   | Value of string                        (* <value>str</value> *)
11111   | Text                                (* <text/> *)
11112
11113 let rec string_of_rng = function
11114   | Element (name, xs) ->
11115       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11116   | Attribute (name, xs) ->
11117       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11118   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11119   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11120   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11121   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11122   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11123   | Value value -> "Value \"" ^ value ^ "\""
11124   | Text -> "Text"
11125
11126 and string_of_rng_list xs =
11127   String.concat ", " (List.map string_of_rng xs)
11128
11129 let rec parse_rng ?defines context = function
11130   | [] -> []
11131   | Xml.Element ("element", ["name", name], children) :: rest ->
11132       Element (name, parse_rng ?defines context children)
11133       :: parse_rng ?defines context rest
11134   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11135       Attribute (name, parse_rng ?defines context children)
11136       :: parse_rng ?defines context rest
11137   | Xml.Element ("interleave", [], children) :: rest ->
11138       Interleave (parse_rng ?defines context children)
11139       :: parse_rng ?defines context rest
11140   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11141       let rng = parse_rng ?defines context [child] in
11142       (match rng with
11143        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11144        | _ ->
11145            failwithf "%s: <zeroOrMore> contains more than one child element"
11146              context
11147       )
11148   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11149       let rng = parse_rng ?defines context [child] in
11150       (match rng with
11151        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11152        | _ ->
11153            failwithf "%s: <oneOrMore> contains more than one child element"
11154              context
11155       )
11156   | Xml.Element ("optional", [], [child]) :: rest ->
11157       let rng = parse_rng ?defines context [child] in
11158       (match rng with
11159        | [child] -> Optional child :: parse_rng ?defines context rest
11160        | _ ->
11161            failwithf "%s: <optional> contains more than one child element"
11162              context
11163       )
11164   | Xml.Element ("choice", [], children) :: rest ->
11165       let values = List.map (
11166         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11167         | _ ->
11168             failwithf "%s: can't handle anything except <value> in <choice>"
11169               context
11170       ) children in
11171       Choice values
11172       :: parse_rng ?defines context rest
11173   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11174       Value value :: parse_rng ?defines context rest
11175   | Xml.Element ("text", [], []) :: rest ->
11176       Text :: parse_rng ?defines context rest
11177   | Xml.Element ("ref", ["name", name], []) :: rest ->
11178       (* Look up the reference.  Because of limitations in this parser,
11179        * we can't handle arbitrarily nested <ref> yet.  You can only
11180        * use <ref> from inside <start>.
11181        *)
11182       (match defines with
11183        | None ->
11184            failwithf "%s: contains <ref>, but no refs are defined yet" context
11185        | Some map ->
11186            let rng = StringMap.find name map in
11187            rng @ parse_rng ?defines context rest
11188       )
11189   | x :: _ ->
11190       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11191
11192 let grammar =
11193   let xml = Xml.parse_file rng_input in
11194   match xml with
11195   | Xml.Element ("grammar", _,
11196                  Xml.Element ("start", _, gram) :: defines) ->
11197       (* The <define/> elements are referenced in the <start> section,
11198        * so build a map of those first.
11199        *)
11200       let defines = List.fold_left (
11201         fun map ->
11202           function Xml.Element ("define", ["name", name], defn) ->
11203             StringMap.add name defn map
11204           | _ ->
11205               failwithf "%s: expected <define name=name/>" rng_input
11206       ) StringMap.empty defines in
11207       let defines = StringMap.mapi parse_rng defines in
11208
11209       (* Parse the <start> clause, passing the defines. *)
11210       parse_rng ~defines "<start>" gram
11211   | _ ->
11212       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11213         rng_input
11214
11215 let name_of_field = function
11216   | Element (name, _) | Attribute (name, _)
11217   | ZeroOrMore (Element (name, _))
11218   | OneOrMore (Element (name, _))
11219   | Optional (Element (name, _)) -> name
11220   | Optional (Attribute (name, _)) -> name
11221   | Text -> (* an unnamed field in an element *)
11222       "data"
11223   | rng ->
11224       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11225
11226 (* At the moment this function only generates OCaml types.  However we
11227  * should parameterize it later so it can generate types/structs in a
11228  * variety of languages.
11229  *)
11230 let generate_types xs =
11231   (* A simple type is one that can be printed out directly, eg.
11232    * "string option".  A complex type is one which has a name and has
11233    * to be defined via another toplevel definition, eg. a struct.
11234    *
11235    * generate_type generates code for either simple or complex types.
11236    * In the simple case, it returns the string ("string option").  In
11237    * the complex case, it returns the name ("mountpoint").  In the
11238    * complex case it has to print out the definition before returning,
11239    * so it should only be called when we are at the beginning of a
11240    * new line (BOL context).
11241    *)
11242   let rec generate_type = function
11243     | Text ->                                (* string *)
11244         "string", true
11245     | Choice values ->                        (* [`val1|`val2|...] *)
11246         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11247     | ZeroOrMore rng ->                        (* <rng> list *)
11248         let t, is_simple = generate_type rng in
11249         t ^ " list (* 0 or more *)", is_simple
11250     | OneOrMore rng ->                        (* <rng> list *)
11251         let t, is_simple = generate_type rng in
11252         t ^ " list (* 1 or more *)", is_simple
11253                                         (* virt-inspector hack: bool *)
11254     | Optional (Attribute (name, [Value "1"])) ->
11255         "bool", true
11256     | Optional rng ->                        (* <rng> list *)
11257         let t, is_simple = generate_type rng in
11258         t ^ " option", is_simple
11259                                         (* type name = { fields ... } *)
11260     | Element (name, fields) when is_attrs_interleave fields ->
11261         generate_type_struct name (get_attrs_interleave fields)
11262     | Element (name, [field])                (* type name = field *)
11263     | Attribute (name, [field]) ->
11264         let t, is_simple = generate_type field in
11265         if is_simple then (t, true)
11266         else (
11267           pr "type %s = %s\n" name t;
11268           name, false
11269         )
11270     | Element (name, fields) ->              (* type name = { fields ... } *)
11271         generate_type_struct name fields
11272     | rng ->
11273         failwithf "generate_type failed at: %s" (string_of_rng rng)
11274
11275   and is_attrs_interleave = function
11276     | [Interleave _] -> true
11277     | Attribute _ :: fields -> is_attrs_interleave fields
11278     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11279     | _ -> false
11280
11281   and get_attrs_interleave = function
11282     | [Interleave fields] -> fields
11283     | ((Attribute _) as field) :: fields
11284     | ((Optional (Attribute _)) as field) :: fields ->
11285         field :: get_attrs_interleave fields
11286     | _ -> assert false
11287
11288   and generate_types xs =
11289     List.iter (fun x -> ignore (generate_type x)) xs
11290
11291   and generate_type_struct name fields =
11292     (* Calculate the types of the fields first.  We have to do this
11293      * before printing anything so we are still in BOL context.
11294      *)
11295     let types = List.map fst (List.map generate_type fields) in
11296
11297     (* Special case of a struct containing just a string and another
11298      * field.  Turn it into an assoc list.
11299      *)
11300     match types with
11301     | ["string"; other] ->
11302         let fname1, fname2 =
11303           match fields with
11304           | [f1; f2] -> name_of_field f1, name_of_field f2
11305           | _ -> assert false in
11306         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11307         name, false
11308
11309     | types ->
11310         pr "type %s = {\n" name;
11311         List.iter (
11312           fun (field, ftype) ->
11313             let fname = name_of_field field in
11314             pr "  %s_%s : %s;\n" name fname ftype
11315         ) (List.combine fields types);
11316         pr "}\n";
11317         (* Return the name of this type, and
11318          * false because it's not a simple type.
11319          *)
11320         name, false
11321   in
11322
11323   generate_types xs
11324
11325 let generate_parsers xs =
11326   (* As for generate_type above, generate_parser makes a parser for
11327    * some type, and returns the name of the parser it has generated.
11328    * Because it (may) need to print something, it should always be
11329    * called in BOL context.
11330    *)
11331   let rec generate_parser = function
11332     | Text ->                                (* string *)
11333         "string_child_or_empty"
11334     | Choice values ->                        (* [`val1|`val2|...] *)
11335         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11336           (String.concat "|"
11337              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11338     | ZeroOrMore rng ->                        (* <rng> list *)
11339         let pa = generate_parser rng in
11340         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11341     | OneOrMore rng ->                        (* <rng> list *)
11342         let pa = generate_parser rng in
11343         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11344                                         (* virt-inspector hack: bool *)
11345     | Optional (Attribute (name, [Value "1"])) ->
11346         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11347     | Optional rng ->                        (* <rng> list *)
11348         let pa = generate_parser rng in
11349         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11350                                         (* type name = { fields ... } *)
11351     | Element (name, fields) when is_attrs_interleave fields ->
11352         generate_parser_struct name (get_attrs_interleave fields)
11353     | Element (name, [field]) ->        (* type name = field *)
11354         let pa = generate_parser field in
11355         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11356         pr "let %s =\n" parser_name;
11357         pr "  %s\n" pa;
11358         pr "let parse_%s = %s\n" name parser_name;
11359         parser_name
11360     | Attribute (name, [field]) ->
11361         let pa = generate_parser field in
11362         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11363         pr "let %s =\n" parser_name;
11364         pr "  %s\n" pa;
11365         pr "let parse_%s = %s\n" name parser_name;
11366         parser_name
11367     | Element (name, fields) ->              (* type name = { fields ... } *)
11368         generate_parser_struct name ([], fields)
11369     | rng ->
11370         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11371
11372   and is_attrs_interleave = function
11373     | [Interleave _] -> true
11374     | Attribute _ :: fields -> is_attrs_interleave fields
11375     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11376     | _ -> false
11377
11378   and get_attrs_interleave = function
11379     | [Interleave fields] -> [], fields
11380     | ((Attribute _) as field) :: fields
11381     | ((Optional (Attribute _)) as field) :: fields ->
11382         let attrs, interleaves = get_attrs_interleave fields in
11383         (field :: attrs), interleaves
11384     | _ -> assert false
11385
11386   and generate_parsers xs =
11387     List.iter (fun x -> ignore (generate_parser x)) xs
11388
11389   and generate_parser_struct name (attrs, interleaves) =
11390     (* Generate parsers for the fields first.  We have to do this
11391      * before printing anything so we are still in BOL context.
11392      *)
11393     let fields = attrs @ interleaves in
11394     let pas = List.map generate_parser fields in
11395
11396     (* Generate an intermediate tuple from all the fields first.
11397      * If the type is just a string + another field, then we will
11398      * return this directly, otherwise it is turned into a record.
11399      *
11400      * RELAX NG note: This code treats <interleave> and plain lists of
11401      * fields the same.  In other words, it doesn't bother enforcing
11402      * any ordering of fields in the XML.
11403      *)
11404     pr "let parse_%s x =\n" name;
11405     pr "  let t = (\n    ";
11406     let comma = ref false in
11407     List.iter (
11408       fun x ->
11409         if !comma then pr ",\n    ";
11410         comma := true;
11411         match x with
11412         | Optional (Attribute (fname, [field])), pa ->
11413             pr "%s x" pa
11414         | Optional (Element (fname, [field])), pa ->
11415             pr "%s (optional_child %S x)" pa fname
11416         | Attribute (fname, [Text]), _ ->
11417             pr "attribute %S x" fname
11418         | (ZeroOrMore _ | OneOrMore _), pa ->
11419             pr "%s x" pa
11420         | Text, pa ->
11421             pr "%s x" pa
11422         | (field, pa) ->
11423             let fname = name_of_field field in
11424             pr "%s (child %S x)" pa fname
11425     ) (List.combine fields pas);
11426     pr "\n  ) in\n";
11427
11428     (match fields with
11429      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11430          pr "  t\n"
11431
11432      | _ ->
11433          pr "  (Obj.magic t : %s)\n" name
11434 (*
11435          List.iter (
11436            function
11437            | (Optional (Attribute (fname, [field])), pa) ->
11438                pr "  %s_%s =\n" name fname;
11439                pr "    %s x;\n" pa
11440            | (Optional (Element (fname, [field])), pa) ->
11441                pr "  %s_%s =\n" name fname;
11442                pr "    (let x = optional_child %S x in\n" fname;
11443                pr "     %s x);\n" pa
11444            | (field, pa) ->
11445                let fname = name_of_field field in
11446                pr "  %s_%s =\n" name fname;
11447                pr "    (let x = child %S x in\n" fname;
11448                pr "     %s x);\n" pa
11449          ) (List.combine fields pas);
11450          pr "}\n"
11451 *)
11452     );
11453     sprintf "parse_%s" name
11454   in
11455
11456   generate_parsers xs
11457
11458 (* Generate ocaml/guestfs_inspector.mli. *)
11459 let generate_ocaml_inspector_mli () =
11460   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11461
11462   pr "\
11463 (** This is an OCaml language binding to the external [virt-inspector]
11464     program.
11465
11466     For more information, please read the man page [virt-inspector(1)].
11467 *)
11468
11469 ";
11470
11471   generate_types grammar;
11472   pr "(** The nested information returned from the {!inspect} function. *)\n";
11473   pr "\n";
11474
11475   pr "\
11476 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11477 (** To inspect a libvirt domain called [name], pass a singleton
11478     list: [inspect [name]].  When using libvirt only, you may
11479     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11480
11481     To inspect a disk image or images, pass a list of the filenames
11482     of the disk images: [inspect filenames]
11483
11484     This function inspects the given guest or disk images and
11485     returns a list of operating system(s) found and a large amount
11486     of information about them.  In the vast majority of cases,
11487     a virtual machine only contains a single operating system.
11488
11489     If the optional [~xml] parameter is given, then this function
11490     skips running the external virt-inspector program and just
11491     parses the given XML directly (which is expected to be XML
11492     produced from a previous run of virt-inspector).  The list of
11493     names and connect URI are ignored in this case.
11494
11495     This function can throw a wide variety of exceptions, for example
11496     if the external virt-inspector program cannot be found, or if
11497     it doesn't generate valid XML.
11498 *)
11499 "
11500
11501 (* Generate ocaml/guestfs_inspector.ml. *)
11502 let generate_ocaml_inspector_ml () =
11503   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11504
11505   pr "open Unix\n";
11506   pr "\n";
11507
11508   generate_types grammar;
11509   pr "\n";
11510
11511   pr "\
11512 (* Misc functions which are used by the parser code below. *)
11513 let first_child = function
11514   | Xml.Element (_, _, c::_) -> c
11515   | Xml.Element (name, _, []) ->
11516       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11517   | Xml.PCData str ->
11518       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11519
11520 let string_child_or_empty = function
11521   | Xml.Element (_, _, [Xml.PCData s]) -> s
11522   | Xml.Element (_, _, []) -> \"\"
11523   | Xml.Element (x, _, _) ->
11524       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11525                 x ^ \" instead\")
11526   | Xml.PCData str ->
11527       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11528
11529 let optional_child name xml =
11530   let children = Xml.children xml in
11531   try
11532     Some (List.find (function
11533                      | Xml.Element (n, _, _) when n = name -> true
11534                      | _ -> false) children)
11535   with
11536     Not_found -> None
11537
11538 let child name xml =
11539   match optional_child name xml with
11540   | Some c -> c
11541   | None ->
11542       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11543
11544 let attribute name xml =
11545   try Xml.attrib xml name
11546   with Xml.No_attribute _ ->
11547     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11548
11549 ";
11550
11551   generate_parsers grammar;
11552   pr "\n";
11553
11554   pr "\
11555 (* Run external virt-inspector, then use parser to parse the XML. *)
11556 let inspect ?connect ?xml names =
11557   let xml =
11558     match xml with
11559     | None ->
11560         if names = [] then invalid_arg \"inspect: no names given\";
11561         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11562           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11563           names in
11564         let cmd = List.map Filename.quote cmd in
11565         let cmd = String.concat \" \" cmd in
11566         let chan = open_process_in cmd in
11567         let xml = Xml.parse_in chan in
11568         (match close_process_in chan with
11569          | WEXITED 0 -> ()
11570          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11571          | WSIGNALED i | WSTOPPED i ->
11572              failwith (\"external virt-inspector command died or stopped on sig \" ^
11573                        string_of_int i)
11574         );
11575         xml
11576     | Some doc ->
11577         Xml.parse_string doc in
11578   parse_operatingsystems xml
11579 "
11580
11581 (* This is used to generate the src/MAX_PROC_NR file which
11582  * contains the maximum procedure number, a surrogate for the
11583  * ABI version number.  See src/Makefile.am for the details.
11584  *)
11585 and generate_max_proc_nr () =
11586   let proc_nrs = List.map (
11587     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11588   ) daemon_functions in
11589
11590   let max_proc_nr = List.fold_left max 0 proc_nrs in
11591
11592   pr "%d\n" max_proc_nr
11593
11594 let output_to filename k =
11595   let filename_new = filename ^ ".new" in
11596   chan := open_out filename_new;
11597   k ();
11598   close_out !chan;
11599   chan := Pervasives.stdout;
11600
11601   (* Is the new file different from the current file? *)
11602   if Sys.file_exists filename && files_equal filename filename_new then
11603     unlink filename_new                 (* same, so skip it *)
11604   else (
11605     (* different, overwrite old one *)
11606     (try chmod filename 0o644 with Unix_error _ -> ());
11607     rename filename_new filename;
11608     chmod filename 0o444;
11609     printf "written %s\n%!" filename;
11610   )
11611
11612 let perror msg = function
11613   | Unix_error (err, _, _) ->
11614       eprintf "%s: %s\n" msg (error_message err)
11615   | exn ->
11616       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11617
11618 (* Main program. *)
11619 let () =
11620   let lock_fd =
11621     try openfile "HACKING" [O_RDWR] 0
11622     with
11623     | Unix_error (ENOENT, _, _) ->
11624         eprintf "\
11625 You are probably running this from the wrong directory.
11626 Run it from the top source directory using the command
11627   src/generator.ml
11628 ";
11629         exit 1
11630     | exn ->
11631         perror "open: HACKING" exn;
11632         exit 1 in
11633
11634   (* Acquire a lock so parallel builds won't try to run the generator
11635    * twice at the same time.  Subsequent builds will wait for the first
11636    * one to finish.  Note the lock is released implicitly when the
11637    * program exits.
11638    *)
11639   (try lockf lock_fd F_LOCK 1
11640    with exn ->
11641      perror "lock: HACKING" exn;
11642      exit 1);
11643
11644   check_functions ();
11645
11646   output_to "src/guestfs_protocol.x" generate_xdr;
11647   output_to "src/guestfs-structs.h" generate_structs_h;
11648   output_to "src/guestfs-actions.h" generate_actions_h;
11649   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11650   output_to "src/guestfs-actions.c" generate_client_actions;
11651   output_to "src/guestfs-bindtests.c" generate_bindtests;
11652   output_to "src/guestfs-structs.pod" generate_structs_pod;
11653   output_to "src/guestfs-actions.pod" generate_actions_pod;
11654   output_to "src/guestfs-availability.pod" generate_availability_pod;
11655   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11656   output_to "src/libguestfs.syms" generate_linker_script;
11657   output_to "daemon/actions.h" generate_daemon_actions_h;
11658   output_to "daemon/stubs.c" generate_daemon_actions;
11659   output_to "daemon/names.c" generate_daemon_names;
11660   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11661   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11662   output_to "capitests/tests.c" generate_tests;
11663   output_to "fish/cmds.c" generate_fish_cmds;
11664   output_to "fish/completion.c" generate_fish_completion;
11665   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11666   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11667   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11668   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11669   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11670   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11671   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11672   output_to "perl/Guestfs.xs" generate_perl_xs;
11673   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11674   output_to "perl/bindtests.pl" generate_perl_bindtests;
11675   output_to "python/guestfs-py.c" generate_python_c;
11676   output_to "python/guestfs.py" generate_python_py;
11677   output_to "python/bindtests.py" generate_python_bindtests;
11678   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11679   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11680   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11681
11682   List.iter (
11683     fun (typ, jtyp) ->
11684       let cols = cols_of_struct typ in
11685       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11686       output_to filename (generate_java_struct jtyp cols);
11687   ) java_structs;
11688
11689   output_to "java/Makefile.inc" generate_java_makefile_inc;
11690   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11691   output_to "java/Bindtests.java" generate_java_bindtests;
11692   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11693   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11694   output_to "csharp/Libguestfs.cs" generate_csharp;
11695
11696   (* Always generate this file last, and unconditionally.  It's used
11697    * by the Makefile to know when we must re-run the generator.
11698    *)
11699   let chan = open_out "src/stamp-generator" in
11700   fprintf chan "1\n";
11701   close_out chan;
11702
11703   printf "generated %d lines of code\n" !lines