Documentation: Use 'g' instead of 'handle' in documentation.
[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   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2032    [InitBasicFS, Always, TestOutput (
2033       [["tar_in"; "../images/helloworld.tar"; "/"];
2034        ["cat"; "/hello"]], "hello\n")],
2035    "unpack tarfile to directory",
2036    "\
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2039
2040 To upload a compressed tarball, use C<guestfs_tgz_in>
2041 or C<guestfs_txz_in>.");
2042
2043   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2044    [],
2045    "pack directory into tarfile",
2046    "\
2047 This command packs the contents of C<directory> and downloads
2048 it to local file C<tarfile>.
2049
2050 To download a compressed tarball, use C<guestfs_tgz_out>
2051 or C<guestfs_txz_out>.");
2052
2053   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2054    [InitBasicFS, Always, TestOutput (
2055       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056        ["cat"; "/hello"]], "hello\n")],
2057    "unpack compressed tarball to directory",
2058    "\
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2061
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2063
2064   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2065    [],
2066    "pack directory into compressed tarball",
2067    "\
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2070
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2072
2073   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074    [InitBasicFS, Always, TestLastFail (
2075       [["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["touch"; "/new"]]);
2078     InitBasicFS, Always, TestOutput (
2079       [["write_file"; "/new"; "data"; "0"];
2080        ["umount"; "/"];
2081        ["mount_ro"; "/dev/sda1"; "/"];
2082        ["cat"; "/new"]], "data")],
2083    "mount a guest disk, read-only",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2087
2088   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2089    [],
2090    "mount a guest disk with mount options",
2091    "\
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.");
2095
2096   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097    [],
2098    "mount a guest disk with mount options and vfstype",
2099    "\
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103
2104   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105    [],
2106    "debugging and internals",
2107    "\
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2110 qemu subprocess.
2111
2112 There is no comprehensive help for this command.  You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2115
2116   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117    [InitEmpty, Always, TestOutputList (
2118       [["part_disk"; "/dev/sda"; "mbr"];
2119        ["pvcreate"; "/dev/sda1"];
2120        ["vgcreate"; "VG"; "/dev/sda1"];
2121        ["lvcreate"; "LV1"; "VG"; "50"];
2122        ["lvcreate"; "LV2"; "VG"; "50"];
2123        ["lvremove"; "/dev/VG/LV1"];
2124        ["lvs"]], ["/dev/VG/LV2"]);
2125     InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["lvremove"; "/dev/VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG"];
2140        ["vgs"]], ["VG"])],
2141    "remove an LVM logical volume",
2142    "\
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2145
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2148
2149   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150    [InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["vgremove"; "VG"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputList (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["vgs"]], [])],
2166    "remove an LVM volume group",
2167    "\
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169
2170 This also forcibly removes all logical volumes in the volume
2171 group (if any).");
2172
2173   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174    [InitEmpty, Always, TestOutputListOfDevices (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["pvremove"; "/dev/sda1"];
2182        ["lvs"]], []);
2183     InitEmpty, Always, TestOutputListOfDevices (
2184       [["part_disk"; "/dev/sda"; "mbr"];
2185        ["pvcreate"; "/dev/sda1"];
2186        ["vgcreate"; "VG"; "/dev/sda1"];
2187        ["lvcreate"; "LV1"; "VG"; "50"];
2188        ["lvcreate"; "LV2"; "VG"; "50"];
2189        ["vgremove"; "VG"];
2190        ["pvremove"; "/dev/sda1"];
2191        ["vgs"]], []);
2192     InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["pvs"]], [])],
2201    "remove an LVM physical volume",
2202    "\
2203 This wipes a physical volume C<device> so that LVM will no longer
2204 recognise it.
2205
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2209
2210   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211    [InitBasicFS, Always, TestOutput (
2212       [["set_e2label"; "/dev/sda1"; "testlabel"];
2213        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214    "set the ext2/3/4 filesystem label",
2215    "\
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>.  Filesystem labels are limited to
2218 16 characters.
2219
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2222
2223   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224    [],
2225    "get the ext2/3/4 filesystem label",
2226    "\
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2228 C<device>.");
2229
2230   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231    (let uuid = uuidgen () in
2232     [InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; uuid];
2234         ["get_e2uuid"; "/dev/sda1"]], uuid);
2235      InitBasicFS, Always, TestOutput (
2236        [["set_e2uuid"; "/dev/sda1"; "clear"];
2237         ["get_e2uuid"; "/dev/sda1"]], "");
2238      (* We can't predict what UUIDs will be, so just check the commands run. *)
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243    "set the ext2/3/4 filesystem UUID",
2244    "\
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>.  The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2249
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2252
2253   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254    [],
2255    "get the ext2/3/4 filesystem UUID",
2256    "\
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 C<device>.");
2259
2260   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2261    [InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264     InitBasicFS, Always, TestOutputInt (
2265       [["umount"; "/dev/sda1"];
2266        ["zero"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268    "run the filesystem checker",
2269    "\
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2272
2273 The returned integer is the status.  See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2275
2276 Notes:
2277
2278 =over 4
2279
2280 =item *
2281
2282 Multiple status codes can be summed together.
2283
2284 =item *
2285
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2288
2289 =item *
2290
2291 Checking or repairing NTFS volumes is not supported
2292 (by linux-ntfs).
2293
2294 =back
2295
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297
2298   ("zero", (RErr, [Device "device"]), 85, [],
2299    [InitBasicFS, Always, TestOutput (
2300       [["umount"; "/dev/sda1"];
2301        ["zero"; "/dev/sda1"];
2302        ["file"; "/dev/sda1"]], "data")],
2303    "write zeroes to the device",
2304    "\
2305 This command writes zeroes over the first few blocks of C<device>.
2306
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device).  It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2310
2311 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2312
2313   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314    (* Test disabled because grub-install incompatible with virtio-blk driver.
2315     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316     *)
2317    [InitBasicFS, Disabled, TestOutputTrue (
2318       [["grub_install"; "/"; "/dev/sda1"];
2319        ["is_dir"; "/boot"]])],
2320    "install GRUB",
2321    "\
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2324
2325   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326    [InitBasicFS, Always, TestOutput (
2327       [["write_file"; "/old"; "file content"; "0"];
2328        ["cp"; "/old"; "/new"];
2329        ["cat"; "/new"]], "file content");
2330     InitBasicFS, Always, TestOutputTrue (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["is_file"; "/old"]]);
2334     InitBasicFS, Always, TestOutput (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["mkdir"; "/dir"];
2337        ["cp"; "/old"; "/dir/new"];
2338        ["cat"; "/dir/new"]], "file content")],
2339    "copy a file",
2340    "\
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2343
2344   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["mkdir"; "/olddir"];
2347        ["mkdir"; "/newdir"];
2348        ["write_file"; "/olddir/file"; "file content"; "0"];
2349        ["cp_a"; "/olddir"; "/newdir"];
2350        ["cat"; "/newdir/olddir/file"]], "file content")],
2351    "copy a file or directory recursively",
2352    "\
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2355
2356   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357    [InitBasicFS, Always, TestOutput (
2358       [["write_file"; "/old"; "file content"; "0"];
2359        ["mv"; "/old"; "/new"];
2360        ["cat"; "/new"]], "file content");
2361     InitBasicFS, Always, TestOutputFalse (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["is_file"; "/old"]])],
2365    "move a file",
2366    "\
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371    [InitEmpty, Always, TestRun (
2372       [["drop_caches"; "3"]])],
2373    "drop kernel page cache, dentries and inodes",
2374    "\
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches.  The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2379
2380 Setting C<whattodrop> to 3 should drop everything.
2381
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2384
2385   ("dmesg", (RString "kmsgs", []), 91, [],
2386    [InitEmpty, Always, TestRun (
2387       [["dmesg"]])],
2388    "return kernel messages",
2389    "\
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel.  This is sometimes useful for extended
2392 debugging of problems.
2393
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2398
2399   ("ping_daemon", (RErr, []), 92, [],
2400    [InitEmpty, Always, TestRun (
2401       [["ping_daemon"]])],
2402    "ping the guest daemon",
2403    "\
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess.  Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2408
2409   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410    [InitBasicFS, Always, TestOutputTrue (
2411       [["write_file"; "/file1"; "contents of a file"; "0"];
2412        ["cp"; "/file1"; "/file2"];
2413        ["equal"; "/file1"; "/file2"]]);
2414     InitBasicFS, Always, TestOutputFalse (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["write_file"; "/file2"; "contents of another file"; "0"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestLastFail (
2419       [["equal"; "/file1"; "/file2"]])],
2420    "test if two files have equal contents",
2421    "\
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2424
2425 The external L<cmp(1)> program is used for the comparison.");
2426
2427   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428    [InitISOFS, Always, TestOutputList (
2429       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430     InitISOFS, Always, TestOutputList (
2431       [["strings"; "/empty"]], [])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Disabled, TestOutputList (
2441       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding.
2447
2448 See the L<strings(1)> manpage for the full list of encodings.
2449
2450 Commonly useful encodings are C<l> (lower case L) which will
2451 show strings inside Windows/x86 files.
2452
2453 The returned strings are transcoded to UTF-8.");
2454
2455   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2456    [InitISOFS, Always, TestOutput (
2457       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2458     (* Test for RHBZ#501888c2 regression which caused large hexdump
2459      * commands to segfault.
2460      *)
2461     InitISOFS, Always, TestRun (
2462       [["hexdump"; "/100krandom"]])],
2463    "dump a file in hexadecimal",
2464    "\
2465 This runs C<hexdump -C> on the given C<path>.  The result is
2466 the human-readable, canonical hex dump of the file.");
2467
2468   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2469    [InitNone, Always, TestOutput (
2470       [["part_disk"; "/dev/sda"; "mbr"];
2471        ["mkfs"; "ext3"; "/dev/sda1"];
2472        ["mount_options"; ""; "/dev/sda1"; "/"];
2473        ["write_file"; "/new"; "test file"; "0"];
2474        ["umount"; "/dev/sda1"];
2475        ["zerofree"; "/dev/sda1"];
2476        ["mount_options"; ""; "/dev/sda1"; "/"];
2477        ["cat"; "/new"]], "test file")],
2478    "zero unused inodes and disk blocks on ext2/3 filesystem",
2479    "\
2480 This runs the I<zerofree> program on C<device>.  This program
2481 claims to zero unused inodes and disk blocks on an ext2/3
2482 filesystem, thus making it possible to compress the filesystem
2483 more effectively.
2484
2485 You should B<not> run this program if the filesystem is
2486 mounted.
2487
2488 It is possible that using this program can damage the filesystem
2489 or data on the filesystem.");
2490
2491   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2492    [],
2493    "resize an LVM physical volume",
2494    "\
2495 This resizes (expands or shrinks) an existing LVM physical
2496 volume to match the new size of the underlying device.");
2497
2498   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2499                        Int "cyls"; Int "heads"; Int "sectors";
2500                        String "line"]), 99, [DangerWillRobinson],
2501    [],
2502    "modify a single partition on a block device",
2503    "\
2504 This runs L<sfdisk(8)> option to modify just the single
2505 partition C<n> (note: C<n> counts from 1).
2506
2507 For other parameters, see C<guestfs_sfdisk>.  You should usually
2508 pass C<0> for the cyls/heads/sectors parameters.
2509
2510 See also: C<guestfs_part_add>");
2511
2512   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2513    [],
2514    "display the partition table",
2515    "\
2516 This displays the partition table on C<device>, in the
2517 human-readable output of the L<sfdisk(8)> command.  It is
2518 not intended to be parsed.
2519
2520 See also: C<guestfs_part_list>");
2521
2522   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2523    [],
2524    "display the kernel geometry",
2525    "\
2526 This displays the kernel's idea of the geometry of C<device>.
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2532    [],
2533    "display the disk geometry from the partition table",
2534    "\
2535 This displays the disk geometry of C<device> read from the
2536 partition table.  Especially in the case where the underlying
2537 block device has been resized, this can be different from the
2538 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2539
2540 The result is in human-readable format, and not designed to
2541 be parsed.");
2542
2543   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate all volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in all volume groups.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n>");
2554
2555   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2556    [],
2557    "activate or deactivate some volume groups",
2558    "\
2559 This command activates or (if C<activate> is false) deactivates
2560 all logical volumes in the listed volume groups C<volgroups>.
2561 If activated, then they are made known to the
2562 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2563 then those devices disappear.
2564
2565 This command is the same as running C<vgchange -a y|n volgroups...>
2566
2567 Note that if C<volgroups> is an empty list then B<all> volume groups
2568 are activated or deactivated.");
2569
2570   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2571    [InitNone, Always, TestOutput (
2572       [["part_disk"; "/dev/sda"; "mbr"];
2573        ["pvcreate"; "/dev/sda1"];
2574        ["vgcreate"; "VG"; "/dev/sda1"];
2575        ["lvcreate"; "LV"; "VG"; "10"];
2576        ["mkfs"; "ext2"; "/dev/VG/LV"];
2577        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2578        ["write_file"; "/new"; "test content"; "0"];
2579        ["umount"; "/"];
2580        ["lvresize"; "/dev/VG/LV"; "20"];
2581        ["e2fsck_f"; "/dev/VG/LV"];
2582        ["resize2fs"; "/dev/VG/LV"];
2583        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2584        ["cat"; "/new"]], "test content")],
2585    "resize an LVM logical volume",
2586    "\
2587 This resizes (expands or shrinks) an existing LVM logical
2588 volume to C<mbytes>.  When reducing, data in the reduced part
2589 is lost.");
2590
2591   ("resize2fs", (RErr, [Device "device"]), 106, [],
2592    [], (* lvresize tests this *)
2593    "resize an ext2/ext3 filesystem",
2594    "\
2595 This resizes an ext2 or ext3 filesystem to match the size of
2596 the underlying device.
2597
2598 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2599 on the C<device> before calling this command.  For unknown reasons
2600 C<resize2fs> sometimes gives an error about this and sometimes not.
2601 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2602 calling this function.");
2603
2604   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2605    [InitBasicFS, Always, TestOutputList (
2606       [["find"; "/"]], ["lost+found"]);
2607     InitBasicFS, Always, TestOutputList (
2608       [["touch"; "/a"];
2609        ["mkdir"; "/b"];
2610        ["touch"; "/b/c"];
2611        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2612     InitBasicFS, Always, TestOutputList (
2613       [["mkdir_p"; "/a/b/c"];
2614        ["touch"; "/a/b/c/d"];
2615        ["find"; "/a/b/"]], ["c"; "c/d"])],
2616    "find all files and directories",
2617    "\
2618 This command lists out all files and directories, recursively,
2619 starting at C<directory>.  It is essentially equivalent to
2620 running the shell command C<find directory -print> but some
2621 post-processing happens on the output, described below.
2622
2623 This returns a list of strings I<without any prefix>.  Thus
2624 if the directory structure was:
2625
2626  /tmp/a
2627  /tmp/b
2628  /tmp/c/d
2629
2630 then the returned list from C<guestfs_find> C</tmp> would be
2631 4 elements:
2632
2633  a
2634  b
2635  c
2636  c/d
2637
2638 If C<directory> is not a directory, then this command returns
2639 an error.
2640
2641 The returned list is sorted.
2642
2643 See also C<guestfs_find0>.");
2644
2645   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2646    [], (* lvresize tests this *)
2647    "check an ext2/ext3 filesystem",
2648    "\
2649 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2650 filesystem checker on C<device>, noninteractively (C<-p>),
2651 even if the filesystem appears to be clean (C<-f>).
2652
2653 This command is only needed because of C<guestfs_resize2fs>
2654 (q.v.).  Normally you should use C<guestfs_fsck>.");
2655
2656   ("sleep", (RErr, [Int "secs"]), 109, [],
2657    [InitNone, Always, TestRun (
2658       [["sleep"; "1"]])],
2659    "sleep for some seconds",
2660    "\
2661 Sleep for C<secs> seconds.");
2662
2663   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2664    [InitNone, Always, TestOutputInt (
2665       [["part_disk"; "/dev/sda"; "mbr"];
2666        ["mkfs"; "ntfs"; "/dev/sda1"];
2667        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2668     InitNone, Always, TestOutputInt (
2669       [["part_disk"; "/dev/sda"; "mbr"];
2670        ["mkfs"; "ext2"; "/dev/sda1"];
2671        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2672    "probe NTFS volume",
2673    "\
2674 This command runs the L<ntfs-3g.probe(8)> command which probes
2675 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2676 be mounted read-write, and some cannot be mounted at all).
2677
2678 C<rw> is a boolean flag.  Set it to true if you want to test
2679 if the volume can be mounted read-write.  Set it to false if
2680 you want to test if the volume can be mounted read-only.
2681
2682 The return value is an integer which C<0> if the operation
2683 would succeed, or some non-zero value documented in the
2684 L<ntfs-3g.probe(8)> manual page.");
2685
2686   ("sh", (RString "output", [String "command"]), 111, [],
2687    [], (* XXX needs tests *)
2688    "run a command via the shell",
2689    "\
2690 This call runs a command from the guest filesystem via the
2691 guest's C</bin/sh>.
2692
2693 This is like C<guestfs_command>, but passes the command to:
2694
2695  /bin/sh -c \"command\"
2696
2697 Depending on the guest's shell, this usually results in
2698 wildcards being expanded, shell expressions being interpolated
2699 and so on.
2700
2701 All the provisos about C<guestfs_command> apply to this call.");
2702
2703   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2704    [], (* XXX needs tests *)
2705    "run a command via the shell returning lines",
2706    "\
2707 This is the same as C<guestfs_sh>, but splits the result
2708 into a list of lines.
2709
2710 See also: C<guestfs_command_lines>");
2711
2712   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2713    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2714     * code in stubs.c, since all valid glob patterns must start with "/".
2715     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2716     *)
2717    [InitBasicFS, Always, TestOutputList (
2718       [["mkdir_p"; "/a/b/c"];
2719        ["touch"; "/a/b/c/d"];
2720        ["touch"; "/a/b/c/e"];
2721        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2722     InitBasicFS, Always, TestOutputList (
2723       [["mkdir_p"; "/a/b/c"];
2724        ["touch"; "/a/b/c/d"];
2725        ["touch"; "/a/b/c/e"];
2726        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2727     InitBasicFS, Always, TestOutputList (
2728       [["mkdir_p"; "/a/b/c"];
2729        ["touch"; "/a/b/c/d"];
2730        ["touch"; "/a/b/c/e"];
2731        ["glob_expand"; "/a/*/x/*"]], [])],
2732    "expand a wildcard path",
2733    "\
2734 This command searches for all the pathnames matching
2735 C<pattern> according to the wildcard expansion rules
2736 used by the shell.
2737
2738 If no paths match, then this returns an empty list
2739 (note: not an error).
2740
2741 It is just a wrapper around the C L<glob(3)> function
2742 with flags C<GLOB_MARK|GLOB_BRACE>.
2743 See that manual page for more details.");
2744
2745   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2746    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2747       [["scrub_device"; "/dev/sdc"]])],
2748    "scrub (securely wipe) a device",
2749    "\
2750 This command writes patterns over C<device> to make data retrieval
2751 more difficult.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2757    [InitBasicFS, Always, TestRun (
2758       [["write_file"; "/file"; "content"; "0"];
2759        ["scrub_file"; "/file"]])],
2760    "scrub (securely wipe) a file",
2761    "\
2762 This command writes patterns over a file to make data retrieval
2763 more difficult.
2764
2765 The file is I<removed> after scrubbing.
2766
2767 It is an interface to the L<scrub(1)> program.  See that
2768 manual page for more details.");
2769
2770   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2771    [], (* XXX needs testing *)
2772    "scrub (securely wipe) free space",
2773    "\
2774 This command creates the directory C<dir> and then fills it
2775 with files until the filesystem is full, and scrubs the files
2776 as for C<guestfs_scrub_file>, and deletes them.
2777 The intention is to scrub any free space on the partition
2778 containing C<dir>.
2779
2780 It is an interface to the L<scrub(1)> program.  See that
2781 manual page for more details.");
2782
2783   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2784    [InitBasicFS, Always, TestRun (
2785       [["mkdir"; "/tmp"];
2786        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2787    "create a temporary directory",
2788    "\
2789 This command creates a temporary directory.  The
2790 C<template> parameter should be a full pathname for the
2791 temporary directory name with the final six characters being
2792 \"XXXXXX\".
2793
2794 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2795 the second one being suitable for Windows filesystems.
2796
2797 The name of the temporary directory that was created
2798 is returned.
2799
2800 The temporary directory is created with mode 0700
2801 and is owned by root.
2802
2803 The caller is responsible for deleting the temporary
2804 directory and its contents after use.
2805
2806 See also: L<mkdtemp(3)>");
2807
2808   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2809    [InitISOFS, Always, TestOutputInt (
2810       [["wc_l"; "/10klines"]], 10000)],
2811    "count lines in a file",
2812    "\
2813 This command counts the lines in a file, using the
2814 C<wc -l> external command.");
2815
2816   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2817    [InitISOFS, Always, TestOutputInt (
2818       [["wc_w"; "/10klines"]], 10000)],
2819    "count words in a file",
2820    "\
2821 This command counts the words in a file, using the
2822 C<wc -w> external command.");
2823
2824   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2825    [InitISOFS, Always, TestOutputInt (
2826       [["wc_c"; "/100kallspaces"]], 102400)],
2827    "count characters in a file",
2828    "\
2829 This command counts the characters in a file, using the
2830 C<wc -c> external command.");
2831
2832   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2833    [InitISOFS, Always, TestOutputList (
2834       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2835    "return first 10 lines of a file",
2836    "\
2837 This command returns up to the first 10 lines of a file as
2838 a list of strings.");
2839
2840   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2841    [InitISOFS, Always, TestOutputList (
2842       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843     InitISOFS, Always, TestOutputList (
2844       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2845     InitISOFS, Always, TestOutputList (
2846       [["head_n"; "0"; "/10klines"]], [])],
2847    "return first N lines of a file",
2848    "\
2849 If the parameter C<nrlines> is a positive number, this returns the first
2850 C<nrlines> lines of the file C<path>.
2851
2852 If the parameter C<nrlines> is a negative number, this returns lines
2853 from the file C<path>, excluding the last C<nrlines> lines.
2854
2855 If the parameter C<nrlines> is zero, this returns an empty list.");
2856
2857   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2858    [InitISOFS, Always, TestOutputList (
2859       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2860    "return last 10 lines of a file",
2861    "\
2862 This command returns up to the last 10 lines of a file as
2863 a list of strings.");
2864
2865   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2866    [InitISOFS, Always, TestOutputList (
2867       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868     InitISOFS, Always, TestOutputList (
2869       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2870     InitISOFS, Always, TestOutputList (
2871       [["tail_n"; "0"; "/10klines"]], [])],
2872    "return last N lines of a file",
2873    "\
2874 If the parameter C<nrlines> is a positive number, this returns the last
2875 C<nrlines> lines of the file C<path>.
2876
2877 If the parameter C<nrlines> is a negative number, this returns lines
2878 from the file C<path>, starting with the C<-nrlines>th line.
2879
2880 If the parameter C<nrlines> is zero, this returns an empty list.");
2881
2882   ("df", (RString "output", []), 125, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage",
2887    "\
2888 This command runs the C<df> command to report disk space used.
2889
2890 This command is mostly useful for interactive sessions.  It
2891 is I<not> intended that you try to parse the output string.
2892 Use C<statvfs> from programs.");
2893
2894   ("df_h", (RString "output", []), 126, [],
2895    [], (* XXX Tricky to test because it depends on the exact format
2896         * of the 'df' command and other imponderables.
2897         *)
2898    "report file system disk space usage (human readable)",
2899    "\
2900 This command runs the C<df -h> command to report disk space used
2901 in human-readable format.
2902
2903 This command is mostly useful for interactive sessions.  It
2904 is I<not> intended that you try to parse the output string.
2905 Use C<statvfs> from programs.");
2906
2907   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2908    [InitISOFS, Always, TestOutputInt (
2909       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2910    "estimate file space usage",
2911    "\
2912 This command runs the C<du -s> command to estimate file space
2913 usage for C<path>.
2914
2915 C<path> can be a file or a directory.  If C<path> is a directory
2916 then the estimate includes the contents of the directory and all
2917 subdirectories (recursively).
2918
2919 The result is the estimated size in I<kilobytes>
2920 (ie. units of 1024 bytes).");
2921
2922   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2923    [InitISOFS, Always, TestOutputList (
2924       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2925    "list files in an initrd",
2926    "\
2927 This command lists out files contained in an initrd.
2928
2929 The files are listed without any initial C</> character.  The
2930 files are listed in the order they appear (not necessarily
2931 alphabetical).  Directory names are listed as separate items.
2932
2933 Old Linux kernels (2.4 and earlier) used a compressed ext2
2934 filesystem as initrd.  We I<only> support the newer initramfs
2935 format (compressed cpio files).");
2936
2937   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2938    [],
2939    "mount a file using the loop device",
2940    "\
2941 This command lets you mount C<file> (a filesystem image
2942 in a file) on a mount point.  It is entirely equivalent to
2943 the command C<mount -o loop file mountpoint>.");
2944
2945   ("mkswap", (RErr, [Device "device"]), 130, [],
2946    [InitEmpty, Always, TestRun (
2947       [["part_disk"; "/dev/sda"; "mbr"];
2948        ["mkswap"; "/dev/sda1"]])],
2949    "create a swap partition",
2950    "\
2951 Create a swap partition on C<device>.");
2952
2953   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2954    [InitEmpty, Always, TestRun (
2955       [["part_disk"; "/dev/sda"; "mbr"];
2956        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2957    "create a swap partition with a label",
2958    "\
2959 Create a swap partition on C<device> with label C<label>.
2960
2961 Note that you cannot attach a swap label to a block device
2962 (eg. C</dev/sda>), just to a partition.  This appears to be
2963 a limitation of the kernel or swap tools.");
2964
2965   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2966    (let uuid = uuidgen () in
2967     [InitEmpty, Always, TestRun (
2968        [["part_disk"; "/dev/sda"; "mbr"];
2969         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2970    "create a swap partition with an explicit UUID",
2971    "\
2972 Create a swap partition on C<device> with UUID C<uuid>.");
2973
2974   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2975    [InitBasicFS, Always, TestOutputStruct (
2976       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2977        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2978        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2979     InitBasicFS, Always, TestOutputStruct (
2980       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2982    "make block, character or FIFO devices",
2983    "\
2984 This call creates block or character special devices, or
2985 named pipes (FIFOs).
2986
2987 The C<mode> parameter should be the mode, using the standard
2988 constants.  C<devmajor> and C<devminor> are the
2989 device major and minor numbers, only used when creating block
2990 and character special devices.
2991
2992 The mode actually set is affected by the umask.");
2993
2994   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2995    [InitBasicFS, Always, TestOutputStruct (
2996       [["mkfifo"; "0o777"; "/node"];
2997        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2998    "make FIFO (named pipe)",
2999    "\
3000 This call creates a FIFO (named pipe) called C<path> with
3001 mode C<mode>.  It is just a convenient wrapper around
3002 C<guestfs_mknod>.
3003
3004 The mode actually set is affected by the umask.");
3005
3006   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3007    [InitBasicFS, Always, TestOutputStruct (
3008       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3009        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3010    "make block device node",
3011    "\
3012 This call creates a block device node called C<path> with
3013 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3014 It is just a convenient wrapper around C<guestfs_mknod>.
3015
3016 The mode actually set is affected by the umask.");
3017
3018   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3019    [InitBasicFS, Always, TestOutputStruct (
3020       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3021        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3022    "make char device node",
3023    "\
3024 This call creates a char 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   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3031    [InitEmpty, Always, TestOutputInt (
3032       [["umask"; "0o22"]], 0o22)],
3033    "set file mode creation mask (umask)",
3034    "\
3035 This function sets the mask used for creating new files and
3036 device nodes to C<mask & 0777>.
3037
3038 Typical umask values would be C<022> which creates new files
3039 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3040 C<002> which creates new files with permissions like
3041 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3042
3043 The default umask is C<022>.  This is important because it
3044 means that directories and device nodes will be created with
3045 C<0644> or C<0755> mode even if you specify C<0777>.
3046
3047 See also C<guestfs_get_umask>,
3048 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3049
3050 This call returns the previous umask.");
3051
3052   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3053    [],
3054    "read directories entries",
3055    "\
3056 This returns the list of directory entries in directory C<dir>.
3057
3058 All entries in the directory are returned, including C<.> and
3059 C<..>.  The entries are I<not> sorted, but returned in the same
3060 order as the underlying filesystem.
3061
3062 Also this call returns basic file type information about each
3063 file.  The C<ftyp> field will contain one of the following characters:
3064
3065 =over 4
3066
3067 =item 'b'
3068
3069 Block special
3070
3071 =item 'c'
3072
3073 Char special
3074
3075 =item 'd'
3076
3077 Directory
3078
3079 =item 'f'
3080
3081 FIFO (named pipe)
3082
3083 =item 'l'
3084
3085 Symbolic link
3086
3087 =item 'r'
3088
3089 Regular file
3090
3091 =item 's'
3092
3093 Socket
3094
3095 =item 'u'
3096
3097 Unknown file type
3098
3099 =item '?'
3100
3101 The L<readdir(3)> returned a C<d_type> field with an
3102 unexpected value
3103
3104 =back
3105
3106 This function is primarily intended for use by programs.  To
3107 get a simple list of names, use C<guestfs_ls>.  To get a printable
3108 directory for human consumption, use C<guestfs_ll>.");
3109
3110   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3111    [],
3112    "create partitions on a block device",
3113    "\
3114 This is a simplified interface to the C<guestfs_sfdisk>
3115 command, where partition sizes are specified in megabytes
3116 only (rounded to the nearest cylinder) and you don't need
3117 to specify the cyls, heads and sectors parameters which
3118 were rarely if ever used anyway.
3119
3120 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3121 and C<guestfs_part_disk>");
3122
3123   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3124    [],
3125    "determine file type inside a compressed file",
3126    "\
3127 This command runs C<file> after first decompressing C<path>
3128 using C<method>.
3129
3130 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3131
3132 Since 1.0.63, use C<guestfs_file> instead which can now
3133 process compressed files.");
3134
3135   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3136    [],
3137    "list extended attributes of a file or directory",
3138    "\
3139 This call lists the extended attributes of the file or directory
3140 C<path>.
3141
3142 At the system call level, this is a combination of the
3143 L<listxattr(2)> and L<getxattr(2)> calls.
3144
3145 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3146
3147   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3148    [],
3149    "list extended attributes of a file or directory",
3150    "\
3151 This is the same as C<guestfs_getxattrs>, but if C<path>
3152 is a symbolic link, then it returns the extended attributes
3153 of the link itself.");
3154
3155   ("setxattr", (RErr, [String "xattr";
3156                        String "val"; Int "vallen"; (* will be BufferIn *)
3157                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3158    [],
3159    "set extended attribute of a file or directory",
3160    "\
3161 This call sets the extended attribute named C<xattr>
3162 of the file C<path> to the value C<val> (of length C<vallen>).
3163 The value is arbitrary 8 bit data.
3164
3165 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3166
3167   ("lsetxattr", (RErr, [String "xattr";
3168                         String "val"; Int "vallen"; (* will be BufferIn *)
3169                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3170    [],
3171    "set extended attribute of a file or directory",
3172    "\
3173 This is the same as C<guestfs_setxattr>, but if C<path>
3174 is a symbolic link, then it sets an extended attribute
3175 of the link itself.");
3176
3177   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3178    [],
3179    "remove extended attribute of a file or directory",
3180    "\
3181 This call removes the extended attribute named C<xattr>
3182 of the file C<path>.
3183
3184 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3185
3186   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3187    [],
3188    "remove extended attribute of a file or directory",
3189    "\
3190 This is the same as C<guestfs_removexattr>, but if C<path>
3191 is a symbolic link, then it removes an extended attribute
3192 of the link itself.");
3193
3194   ("mountpoints", (RHashtable "mps", []), 147, [],
3195    [],
3196    "show mountpoints",
3197    "\
3198 This call is similar to C<guestfs_mounts>.  That call returns
3199 a list of devices.  This one returns a hash table (map) of
3200 device name to directory where the device is mounted.");
3201
3202   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3203    (* This is a special case: while you would expect a parameter
3204     * of type "Pathname", that doesn't work, because it implies
3205     * NEED_ROOT in the generated calling code in stubs.c, and
3206     * this function cannot use NEED_ROOT.
3207     *)
3208    [],
3209    "create a mountpoint",
3210    "\
3211 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3212 specialized calls that can be used to create extra mountpoints
3213 before mounting the first filesystem.
3214
3215 These calls are I<only> necessary in some very limited circumstances,
3216 mainly the case where you want to mount a mix of unrelated and/or
3217 read-only filesystems together.
3218
3219 For example, live CDs often contain a \"Russian doll\" nest of
3220 filesystems, an ISO outer layer, with a squashfs image inside, with
3221 an ext2/3 image inside that.  You can unpack this as follows
3222 in guestfish:
3223
3224  add-ro Fedora-11-i686-Live.iso
3225  run
3226  mkmountpoint /cd
3227  mkmountpoint /squash
3228  mkmountpoint /ext3
3229  mount /dev/sda /cd
3230  mount-loop /cd/LiveOS/squashfs.img /squash
3231  mount-loop /squash/LiveOS/ext3fs.img /ext3
3232
3233 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3234
3235   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3236    [],
3237    "remove a mountpoint",
3238    "\
3239 This calls removes a mountpoint that was previously created
3240 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3241 for full details.");
3242
3243   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3244    [InitISOFS, Always, TestOutputBuffer (
3245       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3246    "read a file",
3247    "\
3248 This calls returns the contents of the file C<path> as a
3249 buffer.
3250
3251 Unlike C<guestfs_cat>, this function can correctly
3252 handle files that contain embedded ASCII NUL characters.
3253 However unlike C<guestfs_download>, this function is limited
3254 in the total size of file that can be handled.");
3255
3256   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3257    [InitISOFS, Always, TestOutputList (
3258       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3259     InitISOFS, Always, TestOutputList (
3260       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3261    "return lines matching a pattern",
3262    "\
3263 This calls the external C<grep> program and returns the
3264 matching lines.");
3265
3266   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3267    [InitISOFS, Always, TestOutputList (
3268       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3269    "return lines matching a pattern",
3270    "\
3271 This calls the external C<egrep> program and returns the
3272 matching lines.");
3273
3274   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3275    [InitISOFS, Always, TestOutputList (
3276       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3277    "return lines matching a pattern",
3278    "\
3279 This calls the external C<fgrep> program and returns the
3280 matching lines.");
3281
3282   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3283    [InitISOFS, Always, TestOutputList (
3284       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3285    "return lines matching a pattern",
3286    "\
3287 This calls the external C<grep -i> program and returns the
3288 matching lines.");
3289
3290   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3291    [InitISOFS, Always, TestOutputList (
3292       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3293    "return lines matching a pattern",
3294    "\
3295 This calls the external C<egrep -i> program and returns the
3296 matching lines.");
3297
3298   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3299    [InitISOFS, Always, TestOutputList (
3300       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3301    "return lines matching a pattern",
3302    "\
3303 This calls the external C<fgrep -i> program and returns the
3304 matching lines.");
3305
3306   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3307    [InitISOFS, Always, TestOutputList (
3308       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3309    "return lines matching a pattern",
3310    "\
3311 This calls the external C<zgrep> program and returns the
3312 matching lines.");
3313
3314   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3315    [InitISOFS, Always, TestOutputList (
3316       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3317    "return lines matching a pattern",
3318    "\
3319 This calls the external C<zegrep> program and returns the
3320 matching lines.");
3321
3322   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3325    "return lines matching a pattern",
3326    "\
3327 This calls the external C<zfgrep> program and returns the
3328 matching lines.");
3329
3330   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3331    [InitISOFS, Always, TestOutputList (
3332       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<zgrep -i> program and returns the
3336 matching lines.");
3337
3338   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<zegrep -i> program and returns the
3344 matching lines.");
3345
3346   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<zfgrep -i> program and returns the
3352 matching lines.");
3353
3354   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3355    [InitISOFS, Always, TestOutput (
3356       [["realpath"; "/../directory"]], "/directory")],
3357    "canonicalized absolute pathname",
3358    "\
3359 Return the canonicalized absolute pathname of C<path>.  The
3360 returned path has no C<.>, C<..> or symbolic link path elements.");
3361
3362   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln"; "/a"; "/b"];
3366        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3367    "create a hard link",
3368    "\
3369 This command creates a hard link using the C<ln> command.");
3370
3371   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3372    [InitBasicFS, Always, TestOutputStruct (
3373       [["touch"; "/a"];
3374        ["touch"; "/b"];
3375        ["ln_f"; "/a"; "/b"];
3376        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3377    "create a hard link",
3378    "\
3379 This command creates a hard link using the C<ln -f> command.
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3383    [InitBasicFS, Always, TestOutputStruct (
3384       [["touch"; "/a"];
3385        ["ln_s"; "a"; "/b"];
3386        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3387    "create a symbolic link",
3388    "\
3389 This command creates a symbolic link using the C<ln -s> command.");
3390
3391   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3392    [InitBasicFS, Always, TestOutput (
3393       [["mkdir_p"; "/a/b"];
3394        ["touch"; "/a/b/c"];
3395        ["ln_sf"; "../d"; "/a/b/c"];
3396        ["readlink"; "/a/b/c"]], "../d")],
3397    "create a symbolic link",
3398    "\
3399 This command creates a symbolic link using the C<ln -sf> command,
3400 The C<-f> option removes the link (C<linkname>) if it exists already.");
3401
3402   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3403    [] (* XXX tested above *),
3404    "read the target of a symbolic link",
3405    "\
3406 This command reads the target of a symbolic link.");
3407
3408   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3409    [InitBasicFS, Always, TestOutputStruct (
3410       [["fallocate"; "/a"; "1000000"];
3411        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3412    "preallocate a file in the guest filesystem",
3413    "\
3414 This command preallocates a file (containing zero bytes) named
3415 C<path> of size C<len> bytes.  If the file exists already, it
3416 is overwritten.
3417
3418 Do not confuse this with the guestfish-specific
3419 C<alloc> command which allocates a file in the host and
3420 attaches it as a device.");
3421
3422   ("swapon_device", (RErr, [Device "device"]), 170, [],
3423    [InitPartition, Always, TestRun (
3424       [["mkswap"; "/dev/sda1"];
3425        ["swapon_device"; "/dev/sda1"];
3426        ["swapoff_device"; "/dev/sda1"]])],
3427    "enable swap on device",
3428    "\
3429 This command enables the libguestfs appliance to use the
3430 swap device or partition named C<device>.  The increased
3431 memory is made available for all commands, for example
3432 those run using C<guestfs_command> or C<guestfs_sh>.
3433
3434 Note that you should not swap to existing guest swap
3435 partitions unless you know what you are doing.  They may
3436 contain hibernation information, or other information that
3437 the guest doesn't want you to trash.  You also risk leaking
3438 information about the host to the guest this way.  Instead,
3439 attach a new host device to the guest and swap on that.");
3440
3441   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3442    [], (* XXX tested by swapon_device *)
3443    "disable swap on device",
3444    "\
3445 This command disables the libguestfs appliance swap
3446 device or partition named C<device>.
3447 See C<guestfs_swapon_device>.");
3448
3449   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3450    [InitBasicFS, Always, TestRun (
3451       [["fallocate"; "/swap"; "8388608"];
3452        ["mkswap_file"; "/swap"];
3453        ["swapon_file"; "/swap"];
3454        ["swapoff_file"; "/swap"]])],
3455    "enable swap on file",
3456    "\
3457 This command enables swap to a file.
3458 See C<guestfs_swapon_device> for other notes.");
3459
3460   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3461    [], (* XXX tested by swapon_file *)
3462    "disable swap on file",
3463    "\
3464 This command disables the libguestfs appliance swap on file.");
3465
3466   ("swapon_label", (RErr, [String "label"]), 174, [],
3467    [InitEmpty, Always, TestRun (
3468       [["part_disk"; "/dev/sdb"; "mbr"];
3469        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3470        ["swapon_label"; "swapit"];
3471        ["swapoff_label"; "swapit"];
3472        ["zero"; "/dev/sdb"];
3473        ["blockdev_rereadpt"; "/dev/sdb"]])],
3474    "enable swap on labeled swap partition",
3475    "\
3476 This command enables swap to a labeled swap partition.
3477 See C<guestfs_swapon_device> for other notes.");
3478
3479   ("swapoff_label", (RErr, [String "label"]), 175, [],
3480    [], (* XXX tested by swapon_label *)
3481    "disable swap on labeled swap partition",
3482    "\
3483 This command disables the libguestfs appliance swap on
3484 labeled swap partition.");
3485
3486   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3487    (let uuid = uuidgen () in
3488     [InitEmpty, Always, TestRun (
3489        [["mkswap_U"; uuid; "/dev/sdb"];
3490         ["swapon_uuid"; uuid];
3491         ["swapoff_uuid"; uuid]])]),
3492    "enable swap on swap partition by UUID",
3493    "\
3494 This command enables swap to a swap partition with the given UUID.
3495 See C<guestfs_swapon_device> for other notes.");
3496
3497   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3498    [], (* XXX tested by swapon_uuid *)
3499    "disable swap on swap partition by UUID",
3500    "\
3501 This command disables the libguestfs appliance swap partition
3502 with the given UUID.");
3503
3504   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3505    [InitBasicFS, Always, TestRun (
3506       [["fallocate"; "/swap"; "8388608"];
3507        ["mkswap_file"; "/swap"]])],
3508    "create a swap file",
3509    "\
3510 Create a swap file.
3511
3512 This command just writes a swap file signature to an existing
3513 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3514
3515   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3516    [InitISOFS, Always, TestRun (
3517       [["inotify_init"; "0"]])],
3518    "create an inotify handle",
3519    "\
3520 This command creates a new inotify handle.
3521 The inotify subsystem can be used to notify events which happen to
3522 objects in the guest filesystem.
3523
3524 C<maxevents> is the maximum number of events which will be
3525 queued up between calls to C<guestfs_inotify_read> or
3526 C<guestfs_inotify_files>.
3527 If this is passed as C<0>, then the kernel (or previously set)
3528 default is used.  For Linux 2.6.29 the default was 16384 events.
3529 Beyond this limit, the kernel throws away events, but records
3530 the fact that it threw them away by setting a flag
3531 C<IN_Q_OVERFLOW> in the returned structure list (see
3532 C<guestfs_inotify_read>).
3533
3534 Before any events are generated, you have to add some
3535 watches to the internal watch list.  See:
3536 C<guestfs_inotify_add_watch>,
3537 C<guestfs_inotify_rm_watch> and
3538 C<guestfs_inotify_watch_all>.
3539
3540 Queued up events should be read periodically by calling
3541 C<guestfs_inotify_read>
3542 (or C<guestfs_inotify_files> which is just a helpful
3543 wrapper around C<guestfs_inotify_read>).  If you don't
3544 read the events out often enough then you risk the internal
3545 queue overflowing.
3546
3547 The handle should be closed after use by calling
3548 C<guestfs_inotify_close>.  This also removes any
3549 watches automatically.
3550
3551 See also L<inotify(7)> for an overview of the inotify interface
3552 as exposed by the Linux kernel, which is roughly what we expose
3553 via libguestfs.  Note that there is one global inotify handle
3554 per libguestfs instance.");
3555
3556   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3557    [InitBasicFS, Always, TestOutputList (
3558       [["inotify_init"; "0"];
3559        ["inotify_add_watch"; "/"; "1073741823"];
3560        ["touch"; "/a"];
3561        ["touch"; "/b"];
3562        ["inotify_files"]], ["a"; "b"])],
3563    "add an inotify watch",
3564    "\
3565 Watch C<path> for the events listed in C<mask>.
3566
3567 Note that if C<path> is a directory then events within that
3568 directory are watched, but this does I<not> happen recursively
3569 (in subdirectories).
3570
3571 Note for non-C or non-Linux callers: the inotify events are
3572 defined by the Linux kernel ABI and are listed in
3573 C</usr/include/sys/inotify.h>.");
3574
3575   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3576    [],
3577    "remove an inotify watch",
3578    "\
3579 Remove a previously defined inotify watch.
3580 See C<guestfs_inotify_add_watch>.");
3581
3582   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3583    [],
3584    "return list of inotify events",
3585    "\
3586 Return the complete queue of events that have happened
3587 since the previous read call.
3588
3589 If no events have happened, this returns an empty list.
3590
3591 I<Note>: In order to make sure that all events have been
3592 read, you must call this function repeatedly until it
3593 returns an empty list.  The reason is that the call will
3594 read events up to the maximum appliance-to-host message
3595 size and leave remaining events in the queue.");
3596
3597   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3598    [],
3599    "return list of watched files that had events",
3600    "\
3601 This function is a helpful wrapper around C<guestfs_inotify_read>
3602 which just returns a list of pathnames of objects that were
3603 touched.  The returned pathnames are sorted and deduplicated.");
3604
3605   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3606    [],
3607    "close the inotify handle",
3608    "\
3609 This closes the inotify handle which was previously
3610 opened by inotify_init.  It removes all watches, throws
3611 away any pending events, and deallocates all resources.");
3612
3613   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3614    [],
3615    "set SELinux security context",
3616    "\
3617 This sets the SELinux security context of the daemon
3618 to the string C<context>.
3619
3620 See the documentation about SELINUX in L<guestfs(3)>.");
3621
3622   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3623    [],
3624    "get SELinux security context",
3625    "\
3626 This gets the SELinux security context of the daemon.
3627
3628 See the documentation about SELINUX in L<guestfs(3)>,
3629 and C<guestfs_setcon>");
3630
3631   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3632    [InitEmpty, Always, TestOutput (
3633       [["part_disk"; "/dev/sda"; "mbr"];
3634        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3635        ["mount_options"; ""; "/dev/sda1"; "/"];
3636        ["write_file"; "/new"; "new file contents"; "0"];
3637        ["cat"; "/new"]], "new file contents")],
3638    "make a filesystem with block size",
3639    "\
3640 This call is similar to C<guestfs_mkfs>, but it allows you to
3641 control the block size of the resulting filesystem.  Supported
3642 block sizes depend on the filesystem type, but typically they
3643 are C<1024>, C<2048> or C<4096> only.");
3644
3645   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3646    [InitEmpty, Always, TestOutput (
3647       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3648        ["mke2journal"; "4096"; "/dev/sda1"];
3649        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3650        ["mount_options"; ""; "/dev/sda2"; "/"];
3651        ["write_file"; "/new"; "new file contents"; "0"];
3652        ["cat"; "/new"]], "new file contents")],
3653    "make ext2/3/4 external journal",
3654    "\
3655 This creates an ext2 external journal on C<device>.  It is equivalent
3656 to the command:
3657
3658  mke2fs -O journal_dev -b blocksize device");
3659
3660   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3661    [InitEmpty, Always, TestOutput (
3662       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3663        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3664        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3665        ["mount_options"; ""; "/dev/sda2"; "/"];
3666        ["write_file"; "/new"; "new file contents"; "0"];
3667        ["cat"; "/new"]], "new file contents")],
3668    "make ext2/3/4 external journal with label",
3669    "\
3670 This creates an ext2 external journal on C<device> with label C<label>.");
3671
3672   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3673    (let uuid = uuidgen () in
3674     [InitEmpty, Always, TestOutput (
3675        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3676         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3677         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3678         ["mount_options"; ""; "/dev/sda2"; "/"];
3679         ["write_file"; "/new"; "new file contents"; "0"];
3680         ["cat"; "/new"]], "new file contents")]),
3681    "make ext2/3/4 external journal with UUID",
3682    "\
3683 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3684
3685   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3686    [],
3687    "make ext2/3/4 filesystem with external journal",
3688    "\
3689 This creates an ext2/3/4 filesystem on C<device> with
3690 an external journal on C<journal>.  It is equivalent
3691 to the command:
3692
3693  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3694
3695 See also C<guestfs_mke2journal>.");
3696
3697   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
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 the journal labeled C<label>.
3703
3704 See also C<guestfs_mke2journal_L>.");
3705
3706   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3707    [],
3708    "make ext2/3/4 filesystem with external journal",
3709    "\
3710 This creates an ext2/3/4 filesystem on C<device> with
3711 an external journal on the journal with UUID C<uuid>.
3712
3713 See also C<guestfs_mke2journal_U>.");
3714
3715   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3716    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3717    "load a kernel module",
3718    "\
3719 This loads a kernel module in the appliance.
3720
3721 The kernel module must have been whitelisted when libguestfs
3722 was built (see C<appliance/kmod.whitelist.in> in the source).");
3723
3724   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3725    [InitNone, Always, TestOutput (
3726       [["echo_daemon"; "This is a test"]], "This is a test"
3727     )],
3728    "echo arguments back to the client",
3729    "\
3730 This command concatenate the list of C<words> passed with single spaces between
3731 them and returns the resulting string.
3732
3733 You can use this command to test the connection through to the daemon.
3734
3735 See also C<guestfs_ping_daemon>.");
3736
3737   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3738    [], (* There is a regression test for this. *)
3739    "find all files and directories, returning NUL-separated list",
3740    "\
3741 This command lists out all files and directories, recursively,
3742 starting at C<directory>, placing the resulting list in the
3743 external file called C<files>.
3744
3745 This command works the same way as C<guestfs_find> with the
3746 following exceptions:
3747
3748 =over 4
3749
3750 =item *
3751
3752 The resulting list is written to an external file.
3753
3754 =item *
3755
3756 Items (filenames) in the result are separated
3757 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3758
3759 =item *
3760
3761 This command is not limited in the number of names that it
3762 can return.
3763
3764 =item *
3765
3766 The result list is not sorted.
3767
3768 =back");
3769
3770   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3771    [InitISOFS, Always, TestOutput (
3772       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3773     InitISOFS, Always, TestOutput (
3774       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3775     InitISOFS, Always, TestOutput (
3776       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3777     InitISOFS, Always, TestLastFail (
3778       [["case_sensitive_path"; "/Known-1/"]]);
3779     InitBasicFS, Always, TestOutput (
3780       [["mkdir"; "/a"];
3781        ["mkdir"; "/a/bbb"];
3782        ["touch"; "/a/bbb/c"];
3783        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3784     InitBasicFS, Always, TestOutput (
3785       [["mkdir"; "/a"];
3786        ["mkdir"; "/a/bbb"];
3787        ["touch"; "/a/bbb/c"];
3788        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3789     InitBasicFS, Always, TestLastFail (
3790       [["mkdir"; "/a"];
3791        ["mkdir"; "/a/bbb"];
3792        ["touch"; "/a/bbb/c"];
3793        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3794    "return true path on case-insensitive filesystem",
3795    "\
3796 This can be used to resolve case insensitive paths on
3797 a filesystem which is case sensitive.  The use case is
3798 to resolve paths which you have read from Windows configuration
3799 files or the Windows Registry, to the true path.
3800
3801 The command handles a peculiarity of the Linux ntfs-3g
3802 filesystem driver (and probably others), which is that although
3803 the underlying filesystem is case-insensitive, the driver
3804 exports the filesystem to Linux as case-sensitive.
3805
3806 One consequence of this is that special directories such
3807 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3808 (or other things) depending on the precise details of how
3809 they were created.  In Windows itself this would not be
3810 a problem.
3811
3812 Bug or feature?  You decide:
3813 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3814
3815 This function resolves the true case of each element in the
3816 path and returns the case-sensitive path.
3817
3818 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3819 might return C<\"/WINDOWS/system32\"> (the exact return value
3820 would depend on details of how the directories were originally
3821 created under Windows).
3822
3823 I<Note>:
3824 This function does not handle drive names, backslashes etc.
3825
3826 See also C<guestfs_realpath>.");
3827
3828   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3829    [InitBasicFS, Always, TestOutput (
3830       [["vfs_type"; "/dev/sda1"]], "ext2")],
3831    "get the Linux VFS type corresponding to a mounted device",
3832    "\
3833 This command gets the block device type corresponding to
3834 a mounted device called C<device>.
3835
3836 Usually the result is the name of the Linux VFS module that
3837 is used to mount this device (probably determined automatically
3838 if you used the C<guestfs_mount> call).");
3839
3840   ("truncate", (RErr, [Pathname "path"]), 199, [],
3841    [InitBasicFS, Always, TestOutputStruct (
3842       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3843        ["truncate"; "/test"];
3844        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3845    "truncate a file to zero size",
3846    "\
3847 This command truncates C<path> to a zero-length file.  The
3848 file must exist already.");
3849
3850   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3851    [InitBasicFS, Always, TestOutputStruct (
3852       [["touch"; "/test"];
3853        ["truncate_size"; "/test"; "1000"];
3854        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3855    "truncate a file to a particular size",
3856    "\
3857 This command truncates C<path> to size C<size> bytes.  The file
3858 must exist already.  If the file is smaller than C<size> then
3859 the file is extended to the required size with null bytes.");
3860
3861   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3862    [InitBasicFS, Always, TestOutputStruct (
3863       [["touch"; "/test"];
3864        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3865        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3866    "set timestamp of a file with nanosecond precision",
3867    "\
3868 This command sets the timestamps of a file with nanosecond
3869 precision.
3870
3871 C<atsecs, atnsecs> are the last access time (atime) in secs and
3872 nanoseconds from the epoch.
3873
3874 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3875 secs and nanoseconds from the epoch.
3876
3877 If the C<*nsecs> field contains the special value C<-1> then
3878 the corresponding timestamp is set to the current time.  (The
3879 C<*secs> field is ignored in this case).
3880
3881 If the C<*nsecs> field contains the special value C<-2> then
3882 the corresponding timestamp is left unchanged.  (The
3883 C<*secs> field is ignored in this case).");
3884
3885   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3886    [InitBasicFS, Always, TestOutputStruct (
3887       [["mkdir_mode"; "/test"; "0o111"];
3888        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3889    "create a directory with a particular mode",
3890    "\
3891 This command creates a directory, setting the initial permissions
3892 of the directory to C<mode>.
3893
3894 For common Linux filesystems, the actual mode which is set will
3895 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3896 interpret the mode in other ways.
3897
3898 See also C<guestfs_mkdir>, C<guestfs_umask>");
3899
3900   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3901    [], (* XXX *)
3902    "change file owner and group",
3903    "\
3904 Change the file owner to C<owner> and group to C<group>.
3905 This is like C<guestfs_chown> but if C<path> is a symlink then
3906 the link itself is changed, not the target.
3907
3908 Only numeric uid and gid are supported.  If you want to use
3909 names, you will need to locate and parse the password file
3910 yourself (Augeas support makes this relatively easy).");
3911
3912   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3913    [], (* XXX *)
3914    "lstat on multiple files",
3915    "\
3916 This call allows you to perform the C<guestfs_lstat> operation
3917 on multiple files, where all files are in the directory C<path>.
3918 C<names> is the list of files from this directory.
3919
3920 On return you get a list of stat structs, with a one-to-one
3921 correspondence to the C<names> list.  If any name did not exist
3922 or could not be lstat'd, then the C<ino> field of that structure
3923 is set to C<-1>.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lxattrlist> for a similarly efficient call
3928 for getting extended attributes.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3934    [], (* XXX *)
3935    "lgetxattr on multiple files",
3936    "\
3937 This call allows you to get the extended attributes
3938 of multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a flat list of xattr structs which must be
3942 interpreted sequentially.  The first xattr struct always has a zero-length
3943 C<attrname>.  C<attrval> in this struct is zero-length
3944 to indicate there was an error doing C<lgetxattr> for this
3945 file, I<or> is a C string which is a decimal number
3946 (the number of following attributes for this file, which could
3947 be C<\"0\">).  Then after the first xattr struct are the
3948 zero or more attributes for the first named file.
3949 This repeats for the second and subsequent files.
3950
3951 This call is intended for programs that want to efficiently
3952 list a directory contents without making many round-trips.
3953 See also C<guestfs_lstatlist> for a similarly efficient call
3954 for getting standard stats.  Very long directory listings
3955 might cause the protocol message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3960    [], (* XXX *)
3961    "readlink on multiple files",
3962    "\
3963 This call allows you to do a C<readlink> operation
3964 on multiple files, where all files are in the directory C<path>.
3965 C<names> is the list of files from this directory.
3966
3967 On return you get a list of strings, with a one-to-one
3968 correspondence to the C<names> list.  Each string is the
3969 value of the symbol link.
3970
3971 If the C<readlink(2)> operation fails on any name, then
3972 the corresponding result string is the empty string C<\"\">.
3973 However the whole operation is completed even if there
3974 were C<readlink(2)> errors, and so you can call this
3975 function with names where you don't know if they are
3976 symbolic links already (albeit slightly less efficient).
3977
3978 This call is intended for programs that want to efficiently
3979 list a directory contents without making many round-trips.
3980 Very long directory listings might cause the protocol
3981 message size to be exceeded, causing
3982 this call to fail.  The caller must split up such requests
3983 into smaller groups of names.");
3984
3985   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3986    [InitISOFS, Always, TestOutputBuffer (
3987       [["pread"; "/known-4"; "1"; "3"]], "\n");
3988     InitISOFS, Always, TestOutputBuffer (
3989       [["pread"; "/empty"; "0"; "100"]], "")],
3990    "read part of a file",
3991    "\
3992 This command lets you read part of a file.  It reads C<count>
3993 bytes of the file, starting at C<offset>, from file C<path>.
3994
3995 This may read fewer bytes than requested.  For further details
3996 see the L<pread(2)> system call.");
3997
3998   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3999    [InitEmpty, Always, TestRun (
4000       [["part_init"; "/dev/sda"; "gpt"]])],
4001    "create an empty partition table",
4002    "\
4003 This creates an empty partition table on C<device> of one of the
4004 partition types listed below.  Usually C<parttype> should be
4005 either C<msdos> or C<gpt> (for large disks).
4006
4007 Initially there are no partitions.  Following this, you should
4008 call C<guestfs_part_add> for each partition required.
4009
4010 Possible values for C<parttype> are:
4011
4012 =over 4
4013
4014 =item B<efi> | B<gpt>
4015
4016 Intel EFI / GPT partition table.
4017
4018 This is recommended for >= 2 TB partitions that will be accessed
4019 from Linux and Intel-based Mac OS X.  It also has limited backwards
4020 compatibility with the C<mbr> format.
4021
4022 =item B<mbr> | B<msdos>
4023
4024 The standard PC \"Master Boot Record\" (MBR) format used
4025 by MS-DOS and Windows.  This partition type will B<only> work
4026 for device sizes up to 2 TB.  For large disks we recommend
4027 using C<gpt>.
4028
4029 =back
4030
4031 Other partition table types that may work but are not
4032 supported include:
4033
4034 =over 4
4035
4036 =item B<aix>
4037
4038 AIX disk labels.
4039
4040 =item B<amiga> | B<rdb>
4041
4042 Amiga \"Rigid Disk Block\" format.
4043
4044 =item B<bsd>
4045
4046 BSD disk labels.
4047
4048 =item B<dasd>
4049
4050 DASD, used on IBM mainframes.
4051
4052 =item B<dvh>
4053
4054 MIPS/SGI volumes.
4055
4056 =item B<mac>
4057
4058 Old Mac partition format.  Modern Macs use C<gpt>.
4059
4060 =item B<pc98>
4061
4062 NEC PC-98 format, common in Japan apparently.
4063
4064 =item B<sun>
4065
4066 Sun disk labels.
4067
4068 =back");
4069
4070   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4071    [InitEmpty, Always, TestRun (
4072       [["part_init"; "/dev/sda"; "mbr"];
4073        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4074     InitEmpty, Always, TestRun (
4075       [["part_init"; "/dev/sda"; "gpt"];
4076        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4077        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_init"; "/dev/sda"; "mbr"];
4080        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4081        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4082        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4083        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4084    "add a partition to the device",
4085    "\
4086 This command adds a partition to C<device>.  If there is no partition
4087 table on the device, call C<guestfs_part_init> first.
4088
4089 The C<prlogex> parameter is the type of partition.  Normally you
4090 should pass C<p> or C<primary> here, but MBR partition tables also
4091 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4092 types.
4093
4094 C<startsect> and C<endsect> are the start and end of the partition
4095 in I<sectors>.  C<endsect> may be negative, which means it counts
4096 backwards from the end of the disk (C<-1> is the last sector).
4097
4098 Creating a partition which covers the whole disk is not so easy.
4099 Use C<guestfs_part_disk> to do that.");
4100
4101   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4102    [InitEmpty, Always, TestRun (
4103       [["part_disk"; "/dev/sda"; "mbr"]]);
4104     InitEmpty, Always, TestRun (
4105       [["part_disk"; "/dev/sda"; "gpt"]])],
4106    "partition whole disk with a single primary partition",
4107    "\
4108 This command is simply a combination of C<guestfs_part_init>
4109 followed by C<guestfs_part_add> to create a single primary partition
4110 covering the whole disk.
4111
4112 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4113 but other possible values are described in C<guestfs_part_init>.");
4114
4115   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4116    [InitEmpty, Always, TestRun (
4117       [["part_disk"; "/dev/sda"; "mbr"];
4118        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4119    "make a partition bootable",
4120    "\
4121 This sets the bootable flag on partition numbered C<partnum> on
4122 device C<device>.  Note that partitions are numbered from 1.
4123
4124 The bootable flag is used by some operating systems (notably
4125 Windows) to determine which partition to boot from.  It is by
4126 no means universally recognized.");
4127
4128   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4129    [InitEmpty, Always, TestRun (
4130       [["part_disk"; "/dev/sda"; "gpt"];
4131        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4132    "set partition name",
4133    "\
4134 This sets the partition name on partition numbered C<partnum> on
4135 device C<device>.  Note that partitions are numbered from 1.
4136
4137 The partition name can only be set on certain types of partition
4138 table.  This works on C<gpt> but not on C<mbr> partitions.");
4139
4140   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4141    [], (* XXX Add a regression test for this. *)
4142    "list partitions on a device",
4143    "\
4144 This command parses the partition table on C<device> and
4145 returns the list of partitions found.
4146
4147 The fields in the returned structure are:
4148
4149 =over 4
4150
4151 =item B<part_num>
4152
4153 Partition number, counting from 1.
4154
4155 =item B<part_start>
4156
4157 Start of the partition I<in bytes>.  To get sectors you have to
4158 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4159
4160 =item B<part_end>
4161
4162 End of the partition in bytes.
4163
4164 =item B<part_size>
4165
4166 Size of the partition in bytes.
4167
4168 =back");
4169
4170   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4171    [InitEmpty, Always, TestOutput (
4172       [["part_disk"; "/dev/sda"; "gpt"];
4173        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4174    "get the partition table type",
4175    "\
4176 This command examines the partition table on C<device> and
4177 returns the partition table type (format) being used.
4178
4179 Common return values include: C<msdos> (a DOS/Windows style MBR
4180 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4181 values are possible, although unusual.  See C<guestfs_part_init>
4182 for a full list.");
4183
4184   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4185    [InitBasicFS, Always, TestOutputBuffer (
4186       [["fill"; "0x63"; "10"; "/test"];
4187        ["read_file"; "/test"]], "cccccccccc")],
4188    "fill a file with octets",
4189    "\
4190 This command creates a new file called C<path>.  The initial
4191 content of the file is C<len> octets of C<c>, where C<c>
4192 must be a number in the range C<[0..255]>.
4193
4194 To fill a file with zero bytes (sparsely), it is
4195 much more efficient to use C<guestfs_truncate_size>.");
4196
4197   ("available", (RErr, [StringList "groups"]), 216, [],
4198    [InitNone, Always, TestRun [["available"; ""]]],
4199    "test availability of some parts of the API",
4200    "\
4201 This command is used to check the availability of some
4202 groups of functionality in the appliance, which not all builds of
4203 the libguestfs appliance will be able to provide.
4204
4205 The libguestfs groups, and the functions that those
4206 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4207
4208 The argument C<groups> is a list of group names, eg:
4209 C<[\"inotify\", \"augeas\"]> would check for the availability of
4210 the Linux inotify functions and Augeas (configuration file
4211 editing) functions.
4212
4213 The command returns no error if I<all> requested groups are available.
4214
4215 It fails with an error if one or more of the requested
4216 groups is unavailable in the appliance.
4217
4218 If an unknown group name is included in the
4219 list of groups then an error is always returned.
4220
4221 I<Notes:>
4222
4223 =over 4
4224
4225 =item *
4226
4227 You must call C<guestfs_launch> before calling this function.
4228
4229 The reason is because we don't know what groups are
4230 supported by the appliance/daemon until it is running and can
4231 be queried.
4232
4233 =item *
4234
4235 If a group of functions is available, this does not necessarily
4236 mean that they will work.  You still have to check for errors
4237 when calling individual API functions even if they are
4238 available.
4239
4240 =item *
4241
4242 It is usually the job of distro packagers to build
4243 complete functionality into the libguestfs appliance.
4244 Upstream libguestfs, if built from source with all
4245 requirements satisfied, will support everything.
4246
4247 =item *
4248
4249 This call was added in version C<1.0.80>.  In previous
4250 versions of libguestfs all you could do would be to speculatively
4251 execute a command to find out if the daemon implemented it.
4252 See also C<guestfs_version>.
4253
4254 =back");
4255
4256   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4257    [InitBasicFS, Always, TestOutputBuffer (
4258       [["write_file"; "/src"; "hello, world"; "0"];
4259        ["dd"; "/src"; "/dest"];
4260        ["read_file"; "/dest"]], "hello, world")],
4261    "copy from source to destination using dd",
4262    "\
4263 This command copies from one source device or file C<src>
4264 to another destination device or file C<dest>.  Normally you
4265 would use this to copy to or from a device or partition, for
4266 example to duplicate a filesystem.
4267
4268 If the destination is a device, it must be as large or larger
4269 than the source file or device, otherwise the copy will fail.
4270 This command cannot do partial copies (see C<guestfs_copy_size>).");
4271
4272   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4273    [InitBasicFS, Always, TestOutputInt (
4274       [["write_file"; "/file"; "hello, world"; "0"];
4275        ["filesize"; "/file"]], 12)],
4276    "return the size of the file in bytes",
4277    "\
4278 This command returns the size of C<file> in bytes.
4279
4280 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4281 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4282 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4283
4284   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4285    [InitBasicFSonLVM, Always, TestOutputList (
4286       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4287        ["lvs"]], ["/dev/VG/LV2"])],
4288    "rename an LVM logical volume",
4289    "\
4290 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4291
4292   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4293    [InitBasicFSonLVM, Always, TestOutputList (
4294       [["umount"; "/"];
4295        ["vg_activate"; "false"; "VG"];
4296        ["vgrename"; "VG"; "VG2"];
4297        ["vg_activate"; "true"; "VG2"];
4298        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4299        ["vgs"]], ["VG2"])],
4300    "rename an LVM volume group",
4301    "\
4302 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4303
4304   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4305    [InitISOFS, Always, TestOutputBuffer (
4306       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4307    "list the contents of a single file in an initrd",
4308    "\
4309 This command unpacks the file C<filename> from the initrd file
4310 called C<initrdpath>.  The filename must be given I<without> the
4311 initial C</> character.
4312
4313 For example, in guestfish you could use the following command
4314 to examine the boot script (usually called C</init>)
4315 contained in a Linux initrd or initramfs image:
4316
4317  initrd-cat /boot/initrd-<version>.img init
4318
4319 See also C<guestfs_initrd_list>.");
4320
4321   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4322    [],
4323    "get the UUID of a physical volume",
4324    "\
4325 This command returns the UUID of the LVM PV C<device>.");
4326
4327   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4328    [],
4329    "get the UUID of a volume group",
4330    "\
4331 This command returns the UUID of the LVM VG named C<vgname>.");
4332
4333   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4334    [],
4335    "get the UUID of a logical volume",
4336    "\
4337 This command returns the UUID of the LVM LV C<device>.");
4338
4339   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4340    [],
4341    "get the PV UUIDs containing the volume group",
4342    "\
4343 Given a VG called C<vgname>, this returns the UUIDs of all
4344 the physical volumes that this volume group resides on.
4345
4346 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4347 calls to associate physical volumes and volume groups.
4348
4349 See also C<guestfs_vglvuuids>.");
4350
4351   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4352    [],
4353    "get the LV UUIDs of all LVs in the volume group",
4354    "\
4355 Given a VG called C<vgname>, this returns the UUIDs of all
4356 the logical volumes created in this volume group.
4357
4358 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4359 calls to associate logical volumes and volume groups.
4360
4361 See also C<guestfs_vgpvuuids>.");
4362
4363   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4364    [InitBasicFS, Always, TestOutputBuffer (
4365       [["write_file"; "/src"; "hello, world"; "0"];
4366        ["copy_size"; "/src"; "/dest"; "5"];
4367        ["read_file"; "/dest"]], "hello")],
4368    "copy size bytes from source to destination using dd",
4369    "\
4370 This command copies exactly C<size> bytes from one source device
4371 or file C<src> to another destination device or file C<dest>.
4372
4373 Note this will fail if the source is too short or if the destination
4374 is not large enough.");
4375
4376   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4377    [InitBasicFSonLVM, Always, TestRun (
4378       [["zero_device"; "/dev/VG/LV"]])],
4379    "write zeroes to an entire device",
4380    "\
4381 This command writes zeroes over the entire C<device>.  Compare
4382 with C<guestfs_zero> which just zeroes the first few blocks of
4383 a device.");
4384
4385   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4386    [InitBasicFS, Always, TestOutput (
4387       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4388        ["cat"; "/hello"]], "hello\n")],
4389    "unpack compressed tarball to directory",
4390    "\
4391 This command uploads and unpacks local file C<tarball> (an
4392 I<xz compressed> tar file) into C<directory>.");
4393
4394   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4395    [],
4396    "pack directory into compressed tarball",
4397    "\
4398 This command packs the contents of C<directory> and downloads
4399 it to local file C<tarball> (as an xz compressed tar archive).");
4400
4401   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4402    [],
4403    "resize an NTFS filesystem",
4404    "\
4405 This command resizes an NTFS filesystem, expanding or
4406 shrinking it to the size of the underlying device.
4407 See also L<ntfsresize(8)>.");
4408
4409   ("vgscan", (RErr, []), 232, [],
4410    [InitEmpty, Always, TestRun (
4411       [["vgscan"]])],
4412    "rescan for LVM physical volumes, volume groups and logical volumes",
4413    "\
4414 This rescans all block devices and rebuilds the list of LVM
4415 physical volumes, volume groups and logical volumes.");
4416
4417   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4418    [InitEmpty, Always, TestRun (
4419       [["part_init"; "/dev/sda"; "mbr"];
4420        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4421        ["part_del"; "/dev/sda"; "1"]])],
4422    "delete a partition",
4423    "\
4424 This command deletes the partition numbered C<partnum> on C<device>.
4425
4426 Note that in the case of MBR partitioning, deleting an
4427 extended partition also deletes any logical partitions
4428 it contains.");
4429
4430   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4431    [InitEmpty, Always, TestOutputTrue (
4432       [["part_init"; "/dev/sda"; "mbr"];
4433        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4434        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4435        ["part_get_bootable"; "/dev/sda"; "1"]])],
4436    "return true if a partition is bootable",
4437    "\
4438 This command returns true if the partition C<partnum> on
4439 C<device> has the bootable flag set.
4440
4441 See also C<guestfs_part_set_bootable>.");
4442
4443   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4444    [InitEmpty, Always, TestOutputInt (
4445       [["part_init"; "/dev/sda"; "mbr"];
4446        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4447        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4448        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4449    "get the MBR type byte (ID byte) from a partition",
4450    "\
4451 Returns the MBR type byte (also known as the ID byte) from
4452 the numbered partition C<partnum>.
4453
4454 Note that only MBR (old DOS-style) partitions have type bytes.
4455 You will get undefined results for other partition table
4456 types (see C<guestfs_part_get_parttype>).");
4457
4458   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4459    [], (* tested by part_get_mbr_id *)
4460    "set the MBR type byte (ID byte) of a partition",
4461    "\
4462 Sets the MBR type byte (also known as the ID byte) of
4463 the numbered partition C<partnum> to C<idbyte>.  Note
4464 that the type bytes quoted in most documentation are
4465 in fact hexadecimal numbers, but usually documented
4466 without any leading \"0x\" which might be confusing.
4467
4468 Note that only MBR (old DOS-style) partitions have type bytes.
4469 You will get undefined results for other partition table
4470 types (see C<guestfs_part_get_parttype>).");
4471
4472   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4473    [InitISOFS, Always, TestOutput (
4474       [["checksum_device"; "md5"; "/dev/sdd"]],
4475       (Digest.to_hex (Digest.file "images/test.iso")))],
4476    "compute MD5, SHAx or CRC checksum of the contents of a device",
4477    "\
4478 This call computes the MD5, SHAx or CRC checksum of the
4479 contents of the device named C<device>.  For the types of
4480 checksums supported see the C<guestfs_checksum> command.");
4481
4482   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4483    [InitNone, Always, TestRun (
4484       [["part_disk"; "/dev/sda"; "mbr"];
4485        ["pvcreate"; "/dev/sda1"];
4486        ["vgcreate"; "VG"; "/dev/sda1"];
4487        ["lvcreate"; "LV"; "VG"; "10"];
4488        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4489    "expand an LV to fill free space",
4490    "\
4491 This expands an existing logical volume C<lv> so that it fills
4492 C<pc>% of the remaining free space in the volume group.  Commonly
4493 you would call this with pc = 100 which expands the logical volume
4494 as much as possible, using all remaining free space in the volume
4495 group.");
4496
4497   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4498    [], (* XXX Augeas code needs tests. *)
4499    "clear Augeas path",
4500    "\
4501 Set the value associated with C<path> to C<NULL>.  This
4502 is the same as the L<augtool(1)> C<clear> command.");
4503
4504   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4505    [InitEmpty, Always, TestOutputInt (
4506       [["get_umask"]], 0o22)],
4507    "get the current umask",
4508    "\
4509 Return the current umask.  By default the umask is C<022>
4510 unless it has been set by calling C<guestfs_umask>.");
4511
4512 ]
4513
4514 let all_functions = non_daemon_functions @ daemon_functions
4515
4516 (* In some places we want the functions to be displayed sorted
4517  * alphabetically, so this is useful:
4518  *)
4519 let all_functions_sorted =
4520   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4521                compare n1 n2) all_functions
4522
4523 (* Field types for structures. *)
4524 type field =
4525   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4526   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4527   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4528   | FUInt32
4529   | FInt32
4530   | FUInt64
4531   | FInt64
4532   | FBytes                      (* Any int measure that counts bytes. *)
4533   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4534   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4535
4536 (* Because we generate extra parsing code for LVM command line tools,
4537  * we have to pull out the LVM columns separately here.
4538  *)
4539 let lvm_pv_cols = [
4540   "pv_name", FString;
4541   "pv_uuid", FUUID;
4542   "pv_fmt", FString;
4543   "pv_size", FBytes;
4544   "dev_size", FBytes;
4545   "pv_free", FBytes;
4546   "pv_used", FBytes;
4547   "pv_attr", FString (* XXX *);
4548   "pv_pe_count", FInt64;
4549   "pv_pe_alloc_count", FInt64;
4550   "pv_tags", FString;
4551   "pe_start", FBytes;
4552   "pv_mda_count", FInt64;
4553   "pv_mda_free", FBytes;
4554   (* Not in Fedora 10:
4555      "pv_mda_size", FBytes;
4556   *)
4557 ]
4558 let lvm_vg_cols = [
4559   "vg_name", FString;
4560   "vg_uuid", FUUID;
4561   "vg_fmt", FString;
4562   "vg_attr", FString (* XXX *);
4563   "vg_size", FBytes;
4564   "vg_free", FBytes;
4565   "vg_sysid", FString;
4566   "vg_extent_size", FBytes;
4567   "vg_extent_count", FInt64;
4568   "vg_free_count", FInt64;
4569   "max_lv", FInt64;
4570   "max_pv", FInt64;
4571   "pv_count", FInt64;
4572   "lv_count", FInt64;
4573   "snap_count", FInt64;
4574   "vg_seqno", FInt64;
4575   "vg_tags", FString;
4576   "vg_mda_count", FInt64;
4577   "vg_mda_free", FBytes;
4578   (* Not in Fedora 10:
4579      "vg_mda_size", FBytes;
4580   *)
4581 ]
4582 let lvm_lv_cols = [
4583   "lv_name", FString;
4584   "lv_uuid", FUUID;
4585   "lv_attr", FString (* XXX *);
4586   "lv_major", FInt64;
4587   "lv_minor", FInt64;
4588   "lv_kernel_major", FInt64;
4589   "lv_kernel_minor", FInt64;
4590   "lv_size", FBytes;
4591   "seg_count", FInt64;
4592   "origin", FString;
4593   "snap_percent", FOptPercent;
4594   "copy_percent", FOptPercent;
4595   "move_pv", FString;
4596   "lv_tags", FString;
4597   "mirror_log", FString;
4598   "modules", FString;
4599 ]
4600
4601 (* Names and fields in all structures (in RStruct and RStructList)
4602  * that we support.
4603  *)
4604 let structs = [
4605   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4606    * not use this struct in any new code.
4607    *)
4608   "int_bool", [
4609     "i", FInt32;                (* for historical compatibility *)
4610     "b", FInt32;                (* for historical compatibility *)
4611   ];
4612
4613   (* LVM PVs, VGs, LVs. *)
4614   "lvm_pv", lvm_pv_cols;
4615   "lvm_vg", lvm_vg_cols;
4616   "lvm_lv", lvm_lv_cols;
4617
4618   (* Column names and types from stat structures.
4619    * NB. Can't use things like 'st_atime' because glibc header files
4620    * define some of these as macros.  Ugh.
4621    *)
4622   "stat", [
4623     "dev", FInt64;
4624     "ino", FInt64;
4625     "mode", FInt64;
4626     "nlink", FInt64;
4627     "uid", FInt64;
4628     "gid", FInt64;
4629     "rdev", FInt64;
4630     "size", FInt64;
4631     "blksize", FInt64;
4632     "blocks", FInt64;
4633     "atime", FInt64;
4634     "mtime", FInt64;
4635     "ctime", FInt64;
4636   ];
4637   "statvfs", [
4638     "bsize", FInt64;
4639     "frsize", FInt64;
4640     "blocks", FInt64;
4641     "bfree", FInt64;
4642     "bavail", FInt64;
4643     "files", FInt64;
4644     "ffree", FInt64;
4645     "favail", FInt64;
4646     "fsid", FInt64;
4647     "flag", FInt64;
4648     "namemax", FInt64;
4649   ];
4650
4651   (* Column names in dirent structure. *)
4652   "dirent", [
4653     "ino", FInt64;
4654     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4655     "ftyp", FChar;
4656     "name", FString;
4657   ];
4658
4659   (* Version numbers. *)
4660   "version", [
4661     "major", FInt64;
4662     "minor", FInt64;
4663     "release", FInt64;
4664     "extra", FString;
4665   ];
4666
4667   (* Extended attribute. *)
4668   "xattr", [
4669     "attrname", FString;
4670     "attrval", FBuffer;
4671   ];
4672
4673   (* Inotify events. *)
4674   "inotify_event", [
4675     "in_wd", FInt64;
4676     "in_mask", FUInt32;
4677     "in_cookie", FUInt32;
4678     "in_name", FString;
4679   ];
4680
4681   (* Partition table entry. *)
4682   "partition", [
4683     "part_num", FInt32;
4684     "part_start", FBytes;
4685     "part_end", FBytes;
4686     "part_size", FBytes;
4687   ];
4688 ] (* end of structs *)
4689
4690 (* Ugh, Java has to be different ..
4691  * These names are also used by the Haskell bindings.
4692  *)
4693 let java_structs = [
4694   "int_bool", "IntBool";
4695   "lvm_pv", "PV";
4696   "lvm_vg", "VG";
4697   "lvm_lv", "LV";
4698   "stat", "Stat";
4699   "statvfs", "StatVFS";
4700   "dirent", "Dirent";
4701   "version", "Version";
4702   "xattr", "XAttr";
4703   "inotify_event", "INotifyEvent";
4704   "partition", "Partition";
4705 ]
4706
4707 (* What structs are actually returned. *)
4708 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4709
4710 (* Returns a list of RStruct/RStructList structs that are returned
4711  * by any function.  Each element of returned list is a pair:
4712  *
4713  * (structname, RStructOnly)
4714  *    == there exists function which returns RStruct (_, structname)
4715  * (structname, RStructListOnly)
4716  *    == there exists function which returns RStructList (_, structname)
4717  * (structname, RStructAndList)
4718  *    == there are functions returning both RStruct (_, structname)
4719  *                                      and RStructList (_, structname)
4720  *)
4721 let rstructs_used_by functions =
4722   (* ||| is a "logical OR" for rstructs_used_t *)
4723   let (|||) a b =
4724     match a, b with
4725     | RStructAndList, _
4726     | _, RStructAndList -> RStructAndList
4727     | RStructOnly, RStructListOnly
4728     | RStructListOnly, RStructOnly -> RStructAndList
4729     | RStructOnly, RStructOnly -> RStructOnly
4730     | RStructListOnly, RStructListOnly -> RStructListOnly
4731   in
4732
4733   let h = Hashtbl.create 13 in
4734
4735   (* if elem->oldv exists, update entry using ||| operator,
4736    * else just add elem->newv to the hash
4737    *)
4738   let update elem newv =
4739     try  let oldv = Hashtbl.find h elem in
4740          Hashtbl.replace h elem (newv ||| oldv)
4741     with Not_found -> Hashtbl.add h elem newv
4742   in
4743
4744   List.iter (
4745     fun (_, style, _, _, _, _, _) ->
4746       match fst style with
4747       | RStruct (_, structname) -> update structname RStructOnly
4748       | RStructList (_, structname) -> update structname RStructListOnly
4749       | _ -> ()
4750   ) functions;
4751
4752   (* return key->values as a list of (key,value) *)
4753   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4754
4755 (* Used for testing language bindings. *)
4756 type callt =
4757   | CallString of string
4758   | CallOptString of string option
4759   | CallStringList of string list
4760   | CallInt of int
4761   | CallInt64 of int64
4762   | CallBool of bool
4763
4764 (* Used to memoize the result of pod2text. *)
4765 let pod2text_memo_filename = "src/.pod2text.data"
4766 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4767   try
4768     let chan = open_in pod2text_memo_filename in
4769     let v = input_value chan in
4770     close_in chan;
4771     v
4772   with
4773     _ -> Hashtbl.create 13
4774 let pod2text_memo_updated () =
4775   let chan = open_out pod2text_memo_filename in
4776   output_value chan pod2text_memo;
4777   close_out chan
4778
4779 (* Useful functions.
4780  * Note we don't want to use any external OCaml libraries which
4781  * makes this a bit harder than it should be.
4782  *)
4783 module StringMap = Map.Make (String)
4784
4785 let failwithf fs = ksprintf failwith fs
4786
4787 let unique = let i = ref 0 in fun () -> incr i; !i
4788
4789 let replace_char s c1 c2 =
4790   let s2 = String.copy s in
4791   let r = ref false in
4792   for i = 0 to String.length s2 - 1 do
4793     if String.unsafe_get s2 i = c1 then (
4794       String.unsafe_set s2 i c2;
4795       r := true
4796     )
4797   done;
4798   if not !r then s else s2
4799
4800 let isspace c =
4801   c = ' '
4802   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4803
4804 let triml ?(test = isspace) str =
4805   let i = ref 0 in
4806   let n = ref (String.length str) in
4807   while !n > 0 && test str.[!i]; do
4808     decr n;
4809     incr i
4810   done;
4811   if !i = 0 then str
4812   else String.sub str !i !n
4813
4814 let trimr ?(test = isspace) str =
4815   let n = ref (String.length str) in
4816   while !n > 0 && test str.[!n-1]; do
4817     decr n
4818   done;
4819   if !n = String.length str then str
4820   else String.sub str 0 !n
4821
4822 let trim ?(test = isspace) str =
4823   trimr ~test (triml ~test str)
4824
4825 let rec find s sub =
4826   let len = String.length s in
4827   let sublen = String.length sub in
4828   let rec loop i =
4829     if i <= len-sublen then (
4830       let rec loop2 j =
4831         if j < sublen then (
4832           if s.[i+j] = sub.[j] then loop2 (j+1)
4833           else -1
4834         ) else
4835           i (* found *)
4836       in
4837       let r = loop2 0 in
4838       if r = -1 then loop (i+1) else r
4839     ) else
4840       -1 (* not found *)
4841   in
4842   loop 0
4843
4844 let rec replace_str s s1 s2 =
4845   let len = String.length s in
4846   let sublen = String.length s1 in
4847   let i = find s s1 in
4848   if i = -1 then s
4849   else (
4850     let s' = String.sub s 0 i in
4851     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4852     s' ^ s2 ^ replace_str s'' s1 s2
4853   )
4854
4855 let rec string_split sep str =
4856   let len = String.length str in
4857   let seplen = String.length sep in
4858   let i = find str sep in
4859   if i = -1 then [str]
4860   else (
4861     let s' = String.sub str 0 i in
4862     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4863     s' :: string_split sep s''
4864   )
4865
4866 let files_equal n1 n2 =
4867   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4868   match Sys.command cmd with
4869   | 0 -> true
4870   | 1 -> false
4871   | i -> failwithf "%s: failed with error code %d" cmd i
4872
4873 let rec filter_map f = function
4874   | [] -> []
4875   | x :: xs ->
4876       match f x with
4877       | Some y -> y :: filter_map f xs
4878       | None -> filter_map f xs
4879
4880 let rec find_map f = function
4881   | [] -> raise Not_found
4882   | x :: xs ->
4883       match f x with
4884       | Some y -> y
4885       | None -> find_map f xs
4886
4887 let iteri f xs =
4888   let rec loop i = function
4889     | [] -> ()
4890     | x :: xs -> f i x; loop (i+1) xs
4891   in
4892   loop 0 xs
4893
4894 let mapi f xs =
4895   let rec loop i = function
4896     | [] -> []
4897     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4898   in
4899   loop 0 xs
4900
4901 let count_chars c str =
4902   let count = ref 0 in
4903   for i = 0 to String.length str - 1 do
4904     if c = String.unsafe_get str i then incr count
4905   done;
4906   !count
4907
4908 let name_of_argt = function
4909   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4910   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4911   | FileIn n | FileOut n -> n
4912
4913 let java_name_of_struct typ =
4914   try List.assoc typ java_structs
4915   with Not_found ->
4916     failwithf
4917       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4918
4919 let cols_of_struct typ =
4920   try List.assoc typ structs
4921   with Not_found ->
4922     failwithf "cols_of_struct: unknown struct %s" typ
4923
4924 let seq_of_test = function
4925   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4926   | TestOutputListOfDevices (s, _)
4927   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4928   | TestOutputTrue s | TestOutputFalse s
4929   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4930   | TestOutputStruct (s, _)
4931   | TestLastFail s -> s
4932
4933 (* Handling for function flags. *)
4934 let protocol_limit_warning =
4935   "Because of the message protocol, there is a transfer limit
4936 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4937
4938 let danger_will_robinson =
4939   "B<This command is dangerous.  Without careful use you
4940 can easily destroy all your data>."
4941
4942 let deprecation_notice flags =
4943   try
4944     let alt =
4945       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4946     let txt =
4947       sprintf "This function is deprecated.
4948 In new code, use the C<%s> call instead.
4949
4950 Deprecated functions will not be removed from the API, but the
4951 fact that they are deprecated indicates that there are problems
4952 with correct use of these functions." alt in
4953     Some txt
4954   with
4955     Not_found -> None
4956
4957 (* Create list of optional groups. *)
4958 let optgroups =
4959   let h = Hashtbl.create 13 in
4960   List.iter (
4961     fun (name, _, _, flags, _, _, _) ->
4962       List.iter (
4963         function
4964         | Optional group ->
4965             let names = try Hashtbl.find h group with Not_found -> [] in
4966             Hashtbl.replace h group (name :: names)
4967         | _ -> ()
4968       ) flags
4969   ) daemon_functions;
4970   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4971   let groups =
4972     List.map (
4973       fun group -> group, List.sort compare (Hashtbl.find h group)
4974     ) groups in
4975   List.sort (fun x y -> compare (fst x) (fst y)) groups
4976
4977 (* Check function names etc. for consistency. *)
4978 let check_functions () =
4979   let contains_uppercase str =
4980     let len = String.length str in
4981     let rec loop i =
4982       if i >= len then false
4983       else (
4984         let c = str.[i] in
4985         if c >= 'A' && c <= 'Z' then true
4986         else loop (i+1)
4987       )
4988     in
4989     loop 0
4990   in
4991
4992   (* Check function names. *)
4993   List.iter (
4994     fun (name, _, _, _, _, _, _) ->
4995       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4996         failwithf "function name %s does not need 'guestfs' prefix" name;
4997       if name = "" then
4998         failwithf "function name is empty";
4999       if name.[0] < 'a' || name.[0] > 'z' then
5000         failwithf "function name %s must start with lowercase a-z" name;
5001       if String.contains name '-' then
5002         failwithf "function name %s should not contain '-', use '_' instead."
5003           name
5004   ) all_functions;
5005
5006   (* Check function parameter/return names. *)
5007   List.iter (
5008     fun (name, style, _, _, _, _, _) ->
5009       let check_arg_ret_name n =
5010         if contains_uppercase n then
5011           failwithf "%s param/ret %s should not contain uppercase chars"
5012             name n;
5013         if String.contains n '-' || String.contains n '_' then
5014           failwithf "%s param/ret %s should not contain '-' or '_'"
5015             name n;
5016         if n = "value" then
5017           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;
5018         if n = "int" || n = "char" || n = "short" || n = "long" then
5019           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5020         if n = "i" || n = "n" then
5021           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5022         if n = "argv" || n = "args" then
5023           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5024
5025         (* List Haskell, OCaml and C keywords here.
5026          * http://www.haskell.org/haskellwiki/Keywords
5027          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5028          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5029          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5030          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5031          * Omitting _-containing words, since they're handled above.
5032          * Omitting the OCaml reserved word, "val", is ok,
5033          * and saves us from renaming several parameters.
5034          *)
5035         let reserved = [
5036           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5037           "char"; "class"; "const"; "constraint"; "continue"; "data";
5038           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5039           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5040           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5041           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5042           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5043           "interface";
5044           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5045           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5046           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5047           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5048           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5049           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5050           "volatile"; "when"; "where"; "while";
5051           ] in
5052         if List.mem n reserved then
5053           failwithf "%s has param/ret using reserved word %s" name n;
5054       in
5055
5056       (match fst style with
5057        | RErr -> ()
5058        | RInt n | RInt64 n | RBool n
5059        | RConstString n | RConstOptString n | RString n
5060        | RStringList n | RStruct (n, _) | RStructList (n, _)
5061        | RHashtable n | RBufferOut n ->
5062            check_arg_ret_name n
5063       );
5064       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5065   ) all_functions;
5066
5067   (* Check short descriptions. *)
5068   List.iter (
5069     fun (name, _, _, _, _, shortdesc, _) ->
5070       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5071         failwithf "short description of %s should begin with lowercase." name;
5072       let c = shortdesc.[String.length shortdesc-1] in
5073       if c = '\n' || c = '.' then
5074         failwithf "short description of %s should not end with . or \\n." name
5075   ) all_functions;
5076
5077   (* Check long descriptions. *)
5078   List.iter (
5079     fun (name, _, _, _, _, _, longdesc) ->
5080       if longdesc.[String.length longdesc-1] = '\n' then
5081         failwithf "long description of %s should not end with \\n." name
5082   ) all_functions;
5083
5084   (* Check proc_nrs. *)
5085   List.iter (
5086     fun (name, _, proc_nr, _, _, _, _) ->
5087       if proc_nr <= 0 then
5088         failwithf "daemon function %s should have proc_nr > 0" name
5089   ) daemon_functions;
5090
5091   List.iter (
5092     fun (name, _, proc_nr, _, _, _, _) ->
5093       if proc_nr <> -1 then
5094         failwithf "non-daemon function %s should have proc_nr -1" name
5095   ) non_daemon_functions;
5096
5097   let proc_nrs =
5098     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5099       daemon_functions in
5100   let proc_nrs =
5101     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5102   let rec loop = function
5103     | [] -> ()
5104     | [_] -> ()
5105     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5106         loop rest
5107     | (name1,nr1) :: (name2,nr2) :: _ ->
5108         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5109           name1 name2 nr1 nr2
5110   in
5111   loop proc_nrs;
5112
5113   (* Check tests. *)
5114   List.iter (
5115     function
5116       (* Ignore functions that have no tests.  We generate a
5117        * warning when the user does 'make check' instead.
5118        *)
5119     | name, _, _, _, [], _, _ -> ()
5120     | name, _, _, _, tests, _, _ ->
5121         let funcs =
5122           List.map (
5123             fun (_, _, test) ->
5124               match seq_of_test test with
5125               | [] ->
5126                   failwithf "%s has a test containing an empty sequence" name
5127               | cmds -> List.map List.hd cmds
5128           ) tests in
5129         let funcs = List.flatten funcs in
5130
5131         let tested = List.mem name funcs in
5132
5133         if not tested then
5134           failwithf "function %s has tests but does not test itself" name
5135   ) all_functions
5136
5137 (* 'pr' prints to the current output file. *)
5138 let chan = ref Pervasives.stdout
5139 let lines = ref 0
5140 let pr fs =
5141   ksprintf
5142     (fun str ->
5143        let i = count_chars '\n' str in
5144        lines := !lines + i;
5145        output_string !chan str
5146     ) fs
5147
5148 let copyright_years =
5149   let this_year = 1900 + (localtime (time ())).tm_year in
5150   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5151
5152 (* Generate a header block in a number of standard styles. *)
5153 type comment_style =
5154     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5155 type license = GPLv2plus | LGPLv2plus
5156
5157 let generate_header ?(extra_inputs = []) comment license =
5158   let inputs = "src/generator.ml" :: extra_inputs in
5159   let c = match comment with
5160     | CStyle ->         pr "/* "; " *"
5161     | CPlusPlusStyle -> pr "// "; "//"
5162     | HashStyle ->      pr "# ";  "#"
5163     | OCamlStyle ->     pr "(* "; " *"
5164     | HaskellStyle ->   pr "{- "; "  " in
5165   pr "libguestfs generated file\n";
5166   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5167   List.iter (pr "%s   %s\n" c) inputs;
5168   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5169   pr "%s\n" c;
5170   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5171   pr "%s\n" c;
5172   (match license with
5173    | GPLv2plus ->
5174        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5175        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5176        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5177        pr "%s (at your option) any later version.\n" c;
5178        pr "%s\n" c;
5179        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5180        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5181        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5182        pr "%s GNU General Public License for more details.\n" c;
5183        pr "%s\n" c;
5184        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5185        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5186        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5187
5188    | LGPLv2plus ->
5189        pr "%s This library is free software; you can redistribute it and/or\n" c;
5190        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5191        pr "%s License as published by the Free Software Foundation; either\n" c;
5192        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5193        pr "%s\n" c;
5194        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5195        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5196        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5197        pr "%s Lesser General Public License for more details.\n" c;
5198        pr "%s\n" c;
5199        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5200        pr "%s License along with this library; if not, write to the Free Software\n" c;
5201        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5202   );
5203   (match comment with
5204    | CStyle -> pr " */\n"
5205    | CPlusPlusStyle
5206    | HashStyle -> ()
5207    | OCamlStyle -> pr " *)\n"
5208    | HaskellStyle -> pr "-}\n"
5209   );
5210   pr "\n"
5211
5212 (* Start of main code generation functions below this line. *)
5213
5214 (* Generate the pod documentation for the C API. *)
5215 let rec generate_actions_pod () =
5216   List.iter (
5217     fun (shortname, style, _, flags, _, _, longdesc) ->
5218       if not (List.mem NotInDocs flags) then (
5219         let name = "guestfs_" ^ shortname in
5220         pr "=head2 %s\n\n" name;
5221         pr " ";
5222         generate_prototype ~extern:false ~handle:"g" name style;
5223         pr "\n\n";
5224         pr "%s\n\n" longdesc;
5225         (match fst style with
5226          | RErr ->
5227              pr "This function returns 0 on success or -1 on error.\n\n"
5228          | RInt _ ->
5229              pr "On error this function returns -1.\n\n"
5230          | RInt64 _ ->
5231              pr "On error this function returns -1.\n\n"
5232          | RBool _ ->
5233              pr "This function returns a C truth value on success or -1 on error.\n\n"
5234          | RConstString _ ->
5235              pr "This function returns a string, or NULL on error.
5236 The string is owned by the guest handle and must I<not> be freed.\n\n"
5237          | RConstOptString _ ->
5238              pr "This function returns a string which may be NULL.
5239 There is way to return an error from this function.
5240 The string is owned by the guest handle and must I<not> be freed.\n\n"
5241          | RString _ ->
5242              pr "This function returns a string, or NULL on error.
5243 I<The caller must free the returned string after use>.\n\n"
5244          | RStringList _ ->
5245              pr "This function returns a NULL-terminated array of strings
5246 (like L<environ(3)>), or NULL if there was an error.
5247 I<The caller must free the strings and the array after use>.\n\n"
5248          | RStruct (_, typ) ->
5249              pr "This function returns a C<struct guestfs_%s *>,
5250 or NULL if there was an error.
5251 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5252          | RStructList (_, typ) ->
5253              pr "This function returns a C<struct guestfs_%s_list *>
5254 (see E<lt>guestfs-structs.hE<gt>),
5255 or NULL if there was an error.
5256 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5257          | RHashtable _ ->
5258              pr "This function returns a NULL-terminated array of
5259 strings, or NULL if there was an error.
5260 The array of strings will always have length C<2n+1>, where
5261 C<n> keys and values alternate, followed by the trailing NULL entry.
5262 I<The caller must free the strings and the array after use>.\n\n"
5263          | RBufferOut _ ->
5264              pr "This function returns a buffer, or NULL on error.
5265 The size of the returned buffer is written to C<*size_r>.
5266 I<The caller must free the returned buffer after use>.\n\n"
5267         );
5268         if List.mem ProtocolLimitWarning flags then
5269           pr "%s\n\n" protocol_limit_warning;
5270         if List.mem DangerWillRobinson flags then
5271           pr "%s\n\n" danger_will_robinson;
5272         match deprecation_notice flags with
5273         | None -> ()
5274         | Some txt -> pr "%s\n\n" txt
5275       )
5276   ) all_functions_sorted
5277
5278 and generate_structs_pod () =
5279   (* Structs documentation. *)
5280   List.iter (
5281     fun (typ, cols) ->
5282       pr "=head2 guestfs_%s\n" typ;
5283       pr "\n";
5284       pr " struct guestfs_%s {\n" typ;
5285       List.iter (
5286         function
5287         | name, FChar -> pr "   char %s;\n" name
5288         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5289         | name, FInt32 -> pr "   int32_t %s;\n" name
5290         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5291         | name, FInt64 -> pr "   int64_t %s;\n" name
5292         | name, FString -> pr "   char *%s;\n" name
5293         | name, FBuffer ->
5294             pr "   /* The next two fields describe a byte array. */\n";
5295             pr "   uint32_t %s_len;\n" name;
5296             pr "   char *%s;\n" name
5297         | name, FUUID ->
5298             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5299             pr "   char %s[32];\n" name
5300         | name, FOptPercent ->
5301             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5302             pr "   float %s;\n" name
5303       ) cols;
5304       pr " };\n";
5305       pr " \n";
5306       pr " struct guestfs_%s_list {\n" typ;
5307       pr "   uint32_t len; /* Number of elements in list. */\n";
5308       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5309       pr " };\n";
5310       pr " \n";
5311       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5312       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5313         typ typ;
5314       pr "\n"
5315   ) structs
5316
5317 and generate_availability_pod () =
5318   (* Availability documentation. *)
5319   pr "=over 4\n";
5320   pr "\n";
5321   List.iter (
5322     fun (group, functions) ->
5323       pr "=item B<%s>\n" group;
5324       pr "\n";
5325       pr "The following functions:\n";
5326       List.iter (pr "L</guestfs_%s>\n") functions;
5327       pr "\n"
5328   ) optgroups;
5329   pr "=back\n";
5330   pr "\n"
5331
5332 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5333  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5334  *
5335  * We have to use an underscore instead of a dash because otherwise
5336  * rpcgen generates incorrect code.
5337  *
5338  * This header is NOT exported to clients, but see also generate_structs_h.
5339  *)
5340 and generate_xdr () =
5341   generate_header CStyle LGPLv2plus;
5342
5343   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5344   pr "typedef string str<>;\n";
5345   pr "\n";
5346
5347   (* Internal structures. *)
5348   List.iter (
5349     function
5350     | typ, cols ->
5351         pr "struct guestfs_int_%s {\n" typ;
5352         List.iter (function
5353                    | name, FChar -> pr "  char %s;\n" name
5354                    | name, FString -> pr "  string %s<>;\n" name
5355                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5356                    | name, FUUID -> pr "  opaque %s[32];\n" name
5357                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5358                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5359                    | name, FOptPercent -> pr "  float %s;\n" name
5360                   ) cols;
5361         pr "};\n";
5362         pr "\n";
5363         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5364         pr "\n";
5365   ) structs;
5366
5367   List.iter (
5368     fun (shortname, style, _, _, _, _, _) ->
5369       let name = "guestfs_" ^ shortname in
5370
5371       (match snd style with
5372        | [] -> ()
5373        | args ->
5374            pr "struct %s_args {\n" name;
5375            List.iter (
5376              function
5377              | Pathname n | Device n | Dev_or_Path n | String n ->
5378                  pr "  string %s<>;\n" n
5379              | OptString n -> pr "  str *%s;\n" n
5380              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5381              | Bool n -> pr "  bool %s;\n" n
5382              | Int n -> pr "  int %s;\n" n
5383              | Int64 n -> pr "  hyper %s;\n" n
5384              | FileIn _ | FileOut _ -> ()
5385            ) args;
5386            pr "};\n\n"
5387       );
5388       (match fst style with
5389        | RErr -> ()
5390        | RInt n ->
5391            pr "struct %s_ret {\n" name;
5392            pr "  int %s;\n" n;
5393            pr "};\n\n"
5394        | RInt64 n ->
5395            pr "struct %s_ret {\n" name;
5396            pr "  hyper %s;\n" n;
5397            pr "};\n\n"
5398        | RBool n ->
5399            pr "struct %s_ret {\n" name;
5400            pr "  bool %s;\n" n;
5401            pr "};\n\n"
5402        | RConstString _ | RConstOptString _ ->
5403            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5404        | RString n ->
5405            pr "struct %s_ret {\n" name;
5406            pr "  string %s<>;\n" n;
5407            pr "};\n\n"
5408        | RStringList n ->
5409            pr "struct %s_ret {\n" name;
5410            pr "  str %s<>;\n" n;
5411            pr "};\n\n"
5412        | RStruct (n, typ) ->
5413            pr "struct %s_ret {\n" name;
5414            pr "  guestfs_int_%s %s;\n" typ n;
5415            pr "};\n\n"
5416        | RStructList (n, typ) ->
5417            pr "struct %s_ret {\n" name;
5418            pr "  guestfs_int_%s_list %s;\n" typ n;
5419            pr "};\n\n"
5420        | RHashtable n ->
5421            pr "struct %s_ret {\n" name;
5422            pr "  str %s<>;\n" n;
5423            pr "};\n\n"
5424        | RBufferOut n ->
5425            pr "struct %s_ret {\n" name;
5426            pr "  opaque %s<>;\n" n;
5427            pr "};\n\n"
5428       );
5429   ) daemon_functions;
5430
5431   (* Table of procedure numbers. *)
5432   pr "enum guestfs_procedure {\n";
5433   List.iter (
5434     fun (shortname, _, proc_nr, _, _, _, _) ->
5435       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5436   ) daemon_functions;
5437   pr "  GUESTFS_PROC_NR_PROCS\n";
5438   pr "};\n";
5439   pr "\n";
5440
5441   (* Having to choose a maximum message size is annoying for several
5442    * reasons (it limits what we can do in the API), but it (a) makes
5443    * the protocol a lot simpler, and (b) provides a bound on the size
5444    * of the daemon which operates in limited memory space.
5445    *)
5446   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5447   pr "\n";
5448
5449   (* Message header, etc. *)
5450   pr "\
5451 /* The communication protocol is now documented in the guestfs(3)
5452  * manpage.
5453  */
5454
5455 const GUESTFS_PROGRAM = 0x2000F5F5;
5456 const GUESTFS_PROTOCOL_VERSION = 1;
5457
5458 /* These constants must be larger than any possible message length. */
5459 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5460 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5461
5462 enum guestfs_message_direction {
5463   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5464   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5465 };
5466
5467 enum guestfs_message_status {
5468   GUESTFS_STATUS_OK = 0,
5469   GUESTFS_STATUS_ERROR = 1
5470 };
5471
5472 const GUESTFS_ERROR_LEN = 256;
5473
5474 struct guestfs_message_error {
5475   string error_message<GUESTFS_ERROR_LEN>;
5476 };
5477
5478 struct guestfs_message_header {
5479   unsigned prog;                     /* GUESTFS_PROGRAM */
5480   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5481   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5482   guestfs_message_direction direction;
5483   unsigned serial;                   /* message serial number */
5484   guestfs_message_status status;
5485 };
5486
5487 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5488
5489 struct guestfs_chunk {
5490   int cancel;                        /* if non-zero, transfer is cancelled */
5491   /* data size is 0 bytes if the transfer has finished successfully */
5492   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5493 };
5494 "
5495
5496 (* Generate the guestfs-structs.h file. *)
5497 and generate_structs_h () =
5498   generate_header CStyle LGPLv2plus;
5499
5500   (* This is a public exported header file containing various
5501    * structures.  The structures are carefully written to have
5502    * exactly the same in-memory format as the XDR structures that
5503    * we use on the wire to the daemon.  The reason for creating
5504    * copies of these structures here is just so we don't have to
5505    * export the whole of guestfs_protocol.h (which includes much
5506    * unrelated and XDR-dependent stuff that we don't want to be
5507    * public, or required by clients).
5508    *
5509    * To reiterate, we will pass these structures to and from the
5510    * client with a simple assignment or memcpy, so the format
5511    * must be identical to what rpcgen / the RFC defines.
5512    *)
5513
5514   (* Public structures. *)
5515   List.iter (
5516     fun (typ, cols) ->
5517       pr "struct guestfs_%s {\n" typ;
5518       List.iter (
5519         function
5520         | name, FChar -> pr "  char %s;\n" name
5521         | name, FString -> pr "  char *%s;\n" name
5522         | name, FBuffer ->
5523             pr "  uint32_t %s_len;\n" name;
5524             pr "  char *%s;\n" name
5525         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5526         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5527         | name, FInt32 -> pr "  int32_t %s;\n" name
5528         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5529         | name, FInt64 -> pr "  int64_t %s;\n" name
5530         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5531       ) cols;
5532       pr "};\n";
5533       pr "\n";
5534       pr "struct guestfs_%s_list {\n" typ;
5535       pr "  uint32_t len;\n";
5536       pr "  struct guestfs_%s *val;\n" typ;
5537       pr "};\n";
5538       pr "\n";
5539       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5540       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5541       pr "\n"
5542   ) structs
5543
5544 (* Generate the guestfs-actions.h file. *)
5545 and generate_actions_h () =
5546   generate_header CStyle LGPLv2plus;
5547   List.iter (
5548     fun (shortname, style, _, _, _, _, _) ->
5549       let name = "guestfs_" ^ shortname in
5550       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5551         name style
5552   ) all_functions
5553
5554 (* Generate the guestfs-internal-actions.h file. *)
5555 and generate_internal_actions_h () =
5556   generate_header CStyle LGPLv2plus;
5557   List.iter (
5558     fun (shortname, style, _, _, _, _, _) ->
5559       let name = "guestfs__" ^ shortname in
5560       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5561         name style
5562   ) non_daemon_functions
5563
5564 (* Generate the client-side dispatch stubs. *)
5565 and generate_client_actions () =
5566   generate_header CStyle LGPLv2plus;
5567
5568   pr "\
5569 #include <stdio.h>
5570 #include <stdlib.h>
5571 #include <stdint.h>
5572 #include <string.h>
5573 #include <inttypes.h>
5574
5575 #include \"guestfs.h\"
5576 #include \"guestfs-internal.h\"
5577 #include \"guestfs-internal-actions.h\"
5578 #include \"guestfs_protocol.h\"
5579
5580 #define error guestfs_error
5581 //#define perrorf guestfs_perrorf
5582 #define safe_malloc guestfs_safe_malloc
5583 #define safe_realloc guestfs_safe_realloc
5584 //#define safe_strdup guestfs_safe_strdup
5585 #define safe_memdup guestfs_safe_memdup
5586
5587 /* Check the return message from a call for validity. */
5588 static int
5589 check_reply_header (guestfs_h *g,
5590                     const struct guestfs_message_header *hdr,
5591                     unsigned int proc_nr, unsigned int serial)
5592 {
5593   if (hdr->prog != GUESTFS_PROGRAM) {
5594     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5595     return -1;
5596   }
5597   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5598     error (g, \"wrong protocol version (%%d/%%d)\",
5599            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5600     return -1;
5601   }
5602   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5603     error (g, \"unexpected message direction (%%d/%%d)\",
5604            hdr->direction, GUESTFS_DIRECTION_REPLY);
5605     return -1;
5606   }
5607   if (hdr->proc != proc_nr) {
5608     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5609     return -1;
5610   }
5611   if (hdr->serial != serial) {
5612     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5613     return -1;
5614   }
5615
5616   return 0;
5617 }
5618
5619 /* Check we are in the right state to run a high-level action. */
5620 static int
5621 check_state (guestfs_h *g, const char *caller)
5622 {
5623   if (!guestfs__is_ready (g)) {
5624     if (guestfs__is_config (g) || guestfs__is_launching (g))
5625       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5626         caller);
5627     else
5628       error (g, \"%%s called from the wrong state, %%d != READY\",
5629         caller, guestfs__get_state (g));
5630     return -1;
5631   }
5632   return 0;
5633 }
5634
5635 ";
5636
5637   (* Generate code to generate guestfish call traces. *)
5638   let trace_call shortname style =
5639     pr "  if (guestfs__get_trace (g)) {\n";
5640
5641     let needs_i =
5642       List.exists (function
5643                    | StringList _ | DeviceList _ -> true
5644                    | _ -> false) (snd style) in
5645     if needs_i then (
5646       pr "    int i;\n";
5647       pr "\n"
5648     );
5649
5650     pr "    printf (\"%s\");\n" shortname;
5651     List.iter (
5652       function
5653       | String n                        (* strings *)
5654       | Device n
5655       | Pathname n
5656       | Dev_or_Path n
5657       | FileIn n
5658       | FileOut n ->
5659           (* guestfish doesn't support string escaping, so neither do we *)
5660           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5661       | OptString n ->                  (* string option *)
5662           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5663           pr "    else printf (\" null\");\n"
5664       | StringList n
5665       | DeviceList n ->                 (* string list *)
5666           pr "    putchar (' ');\n";
5667           pr "    putchar ('\"');\n";
5668           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5669           pr "      if (i > 0) putchar (' ');\n";
5670           pr "      fputs (%s[i], stdout);\n" n;
5671           pr "    }\n";
5672           pr "    putchar ('\"');\n";
5673       | Bool n ->                       (* boolean *)
5674           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5675       | Int n ->                        (* int *)
5676           pr "    printf (\" %%d\", %s);\n" n
5677       | Int64 n ->
5678           pr "    printf (\" %%\" PRIi64, %s);\n" n
5679     ) (snd style);
5680     pr "    putchar ('\\n');\n";
5681     pr "  }\n";
5682     pr "\n";
5683   in
5684
5685   (* For non-daemon functions, generate a wrapper around each function. *)
5686   List.iter (
5687     fun (shortname, style, _, _, _, _, _) ->
5688       let name = "guestfs_" ^ shortname in
5689
5690       generate_prototype ~extern:false ~semicolon:false ~newline:true
5691         ~handle:"g" name style;
5692       pr "{\n";
5693       trace_call shortname style;
5694       pr "  return guestfs__%s " shortname;
5695       generate_c_call_args ~handle:"g" style;
5696       pr ";\n";
5697       pr "}\n";
5698       pr "\n"
5699   ) non_daemon_functions;
5700
5701   (* Client-side stubs for each function. *)
5702   List.iter (
5703     fun (shortname, style, _, _, _, _, _) ->
5704       let name = "guestfs_" ^ shortname in
5705
5706       (* Generate the action stub. *)
5707       generate_prototype ~extern:false ~semicolon:false ~newline:true
5708         ~handle:"g" name style;
5709
5710       let error_code =
5711         match fst style with
5712         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5713         | RConstString _ | RConstOptString _ ->
5714             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5715         | RString _ | RStringList _
5716         | RStruct _ | RStructList _
5717         | RHashtable _ | RBufferOut _ ->
5718             "NULL" in
5719
5720       pr "{\n";
5721
5722       (match snd style with
5723        | [] -> ()
5724        | _ -> pr "  struct %s_args args;\n" name
5725       );
5726
5727       pr "  guestfs_message_header hdr;\n";
5728       pr "  guestfs_message_error err;\n";
5729       let has_ret =
5730         match fst style with
5731         | RErr -> false
5732         | RConstString _ | RConstOptString _ ->
5733             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5734         | RInt _ | RInt64 _
5735         | RBool _ | RString _ | RStringList _
5736         | RStruct _ | RStructList _
5737         | RHashtable _ | RBufferOut _ ->
5738             pr "  struct %s_ret ret;\n" name;
5739             true in
5740
5741       pr "  int serial;\n";
5742       pr "  int r;\n";
5743       pr "\n";
5744       trace_call shortname style;
5745       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5746         shortname error_code;
5747       pr "  guestfs___set_busy (g);\n";
5748       pr "\n";
5749
5750       (* Send the main header and arguments. *)
5751       (match snd style with
5752        | [] ->
5753            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5754              (String.uppercase shortname)
5755        | args ->
5756            List.iter (
5757              function
5758              | Pathname n | Device n | Dev_or_Path n | String n ->
5759                  pr "  args.%s = (char *) %s;\n" n n
5760              | OptString n ->
5761                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5762              | StringList n | DeviceList n ->
5763                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5764                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5765              | Bool n ->
5766                  pr "  args.%s = %s;\n" n n
5767              | Int n ->
5768                  pr "  args.%s = %s;\n" n n
5769              | Int64 n ->
5770                  pr "  args.%s = %s;\n" n n
5771              | FileIn _ | FileOut _ -> ()
5772            ) args;
5773            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5774              (String.uppercase shortname);
5775            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5776              name;
5777       );
5778       pr "  if (serial == -1) {\n";
5779       pr "    guestfs___end_busy (g);\n";
5780       pr "    return %s;\n" error_code;
5781       pr "  }\n";
5782       pr "\n";
5783
5784       (* Send any additional files (FileIn) requested. *)
5785       let need_read_reply_label = ref false in
5786       List.iter (
5787         function
5788         | FileIn n ->
5789             pr "  r = guestfs___send_file (g, %s);\n" n;
5790             pr "  if (r == -1) {\n";
5791             pr "    guestfs___end_busy (g);\n";
5792             pr "    return %s;\n" error_code;
5793             pr "  }\n";
5794             pr "  if (r == -2) /* daemon cancelled */\n";
5795             pr "    goto read_reply;\n";
5796             need_read_reply_label := true;
5797             pr "\n";
5798         | _ -> ()
5799       ) (snd style);
5800
5801       (* Wait for the reply from the remote end. *)
5802       if !need_read_reply_label then pr " read_reply:\n";
5803       pr "  memset (&hdr, 0, sizeof hdr);\n";
5804       pr "  memset (&err, 0, sizeof err);\n";
5805       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5806       pr "\n";
5807       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5808       if not has_ret then
5809         pr "NULL, NULL"
5810       else
5811         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5812       pr ");\n";
5813
5814       pr "  if (r == -1) {\n";
5815       pr "    guestfs___end_busy (g);\n";
5816       pr "    return %s;\n" error_code;
5817       pr "  }\n";
5818       pr "\n";
5819
5820       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5821         (String.uppercase shortname);
5822       pr "    guestfs___end_busy (g);\n";
5823       pr "    return %s;\n" error_code;
5824       pr "  }\n";
5825       pr "\n";
5826
5827       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5828       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5829       pr "    free (err.error_message);\n";
5830       pr "    guestfs___end_busy (g);\n";
5831       pr "    return %s;\n" error_code;
5832       pr "  }\n";
5833       pr "\n";
5834
5835       (* Expecting to receive further files (FileOut)? *)
5836       List.iter (
5837         function
5838         | FileOut n ->
5839             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5840             pr "    guestfs___end_busy (g);\n";
5841             pr "    return %s;\n" error_code;
5842             pr "  }\n";
5843             pr "\n";
5844         | _ -> ()
5845       ) (snd style);
5846
5847       pr "  guestfs___end_busy (g);\n";
5848
5849       (match fst style with
5850        | RErr -> pr "  return 0;\n"
5851        | RInt n | RInt64 n | RBool n ->
5852            pr "  return ret.%s;\n" n
5853        | RConstString _ | RConstOptString _ ->
5854            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5855        | RString n ->
5856            pr "  return ret.%s; /* caller will free */\n" n
5857        | RStringList n | RHashtable n ->
5858            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5859            pr "  ret.%s.%s_val =\n" n n;
5860            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5861            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5862              n n;
5863            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5864            pr "  return ret.%s.%s_val;\n" n n
5865        | RStruct (n, _) ->
5866            pr "  /* caller will free this */\n";
5867            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5868        | RStructList (n, _) ->
5869            pr "  /* caller will free this */\n";
5870            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5871        | RBufferOut n ->
5872            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5873            pr "   * _val might be NULL here.  To make the API saner for\n";
5874            pr "   * callers, we turn this case into a unique pointer (using\n";
5875            pr "   * malloc(1)).\n";
5876            pr "   */\n";
5877            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5878            pr "    *size_r = ret.%s.%s_len;\n" n n;
5879            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5880            pr "  } else {\n";
5881            pr "    free (ret.%s.%s_val);\n" n n;
5882            pr "    char *p = safe_malloc (g, 1);\n";
5883            pr "    *size_r = ret.%s.%s_len;\n" n n;
5884            pr "    return p;\n";
5885            pr "  }\n";
5886       );
5887
5888       pr "}\n\n"
5889   ) daemon_functions;
5890
5891   (* Functions to free structures. *)
5892   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5893   pr " * structure format is identical to the XDR format.  See note in\n";
5894   pr " * generator.ml.\n";
5895   pr " */\n";
5896   pr "\n";
5897
5898   List.iter (
5899     fun (typ, _) ->
5900       pr "void\n";
5901       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5902       pr "{\n";
5903       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5904       pr "  free (x);\n";
5905       pr "}\n";
5906       pr "\n";
5907
5908       pr "void\n";
5909       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5910       pr "{\n";
5911       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5912       pr "  free (x);\n";
5913       pr "}\n";
5914       pr "\n";
5915
5916   ) structs;
5917
5918 (* Generate daemon/actions.h. *)
5919 and generate_daemon_actions_h () =
5920   generate_header CStyle GPLv2plus;
5921
5922   pr "#include \"../src/guestfs_protocol.h\"\n";
5923   pr "\n";
5924
5925   List.iter (
5926     fun (name, style, _, _, _, _, _) ->
5927       generate_prototype
5928         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5929         name style;
5930   ) daemon_functions
5931
5932 (* Generate the linker script which controls the visibility of
5933  * symbols in the public ABI and ensures no other symbols get
5934  * exported accidentally.
5935  *)
5936 and generate_linker_script () =
5937   generate_header HashStyle GPLv2plus;
5938
5939   let globals = [
5940     "guestfs_create";
5941     "guestfs_close";
5942     "guestfs_get_error_handler";
5943     "guestfs_get_out_of_memory_handler";
5944     "guestfs_last_error";
5945     "guestfs_set_error_handler";
5946     "guestfs_set_launch_done_callback";
5947     "guestfs_set_log_message_callback";
5948     "guestfs_set_out_of_memory_handler";
5949     "guestfs_set_subprocess_quit_callback";
5950
5951     (* Unofficial parts of the API: the bindings code use these
5952      * functions, so it is useful to export them.
5953      *)
5954     "guestfs_safe_calloc";
5955     "guestfs_safe_malloc";
5956   ] in
5957   let functions =
5958     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5959       all_functions in
5960   let structs =
5961     List.concat (
5962       List.map (fun (typ, _) ->
5963                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5964         structs
5965     ) in
5966   let globals = List.sort compare (globals @ functions @ structs) in
5967
5968   pr "{\n";
5969   pr "    global:\n";
5970   List.iter (pr "        %s;\n") globals;
5971   pr "\n";
5972
5973   pr "    local:\n";
5974   pr "        *;\n";
5975   pr "};\n"
5976
5977 (* Generate the server-side stubs. *)
5978 and generate_daemon_actions () =
5979   generate_header CStyle GPLv2plus;
5980
5981   pr "#include <config.h>\n";
5982   pr "\n";
5983   pr "#include <stdio.h>\n";
5984   pr "#include <stdlib.h>\n";
5985   pr "#include <string.h>\n";
5986   pr "#include <inttypes.h>\n";
5987   pr "#include <rpc/types.h>\n";
5988   pr "#include <rpc/xdr.h>\n";
5989   pr "\n";
5990   pr "#include \"daemon.h\"\n";
5991   pr "#include \"c-ctype.h\"\n";
5992   pr "#include \"../src/guestfs_protocol.h\"\n";
5993   pr "#include \"actions.h\"\n";
5994   pr "\n";
5995
5996   List.iter (
5997     fun (name, style, _, _, _, _, _) ->
5998       (* Generate server-side stubs. *)
5999       pr "static void %s_stub (XDR *xdr_in)\n" name;
6000       pr "{\n";
6001       let error_code =
6002         match fst style with
6003         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6004         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6005         | RBool _ -> pr "  int r;\n"; "-1"
6006         | RConstString _ | RConstOptString _ ->
6007             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6008         | RString _ -> pr "  char *r;\n"; "NULL"
6009         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6010         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6011         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6012         | RBufferOut _ ->
6013             pr "  size_t size = 1;\n";
6014             pr "  char *r;\n";
6015             "NULL" in
6016
6017       (match snd style with
6018        | [] -> ()
6019        | args ->
6020            pr "  struct guestfs_%s_args args;\n" name;
6021            List.iter (
6022              function
6023              | Device n | Dev_or_Path n
6024              | Pathname n
6025              | String n -> ()
6026              | OptString n -> pr "  char *%s;\n" n
6027              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6028              | Bool n -> pr "  int %s;\n" n
6029              | Int n -> pr "  int %s;\n" n
6030              | Int64 n -> pr "  int64_t %s;\n" n
6031              | FileIn _ | FileOut _ -> ()
6032            ) args
6033       );
6034       pr "\n";
6035
6036       let is_filein =
6037         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6038
6039       (match snd style with
6040        | [] -> ()
6041        | args ->
6042            pr "  memset (&args, 0, sizeof args);\n";
6043            pr "\n";
6044            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6045            if is_filein then
6046              pr "    cancel_receive ();\n";
6047            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6048            pr "    goto done;\n";
6049            pr "  }\n";
6050            let pr_args n =
6051              pr "  char *%s = args.%s;\n" n n
6052            in
6053            let pr_list_handling_code n =
6054              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6055              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6056              pr "  if (%s == NULL) {\n" n;
6057              if is_filein then
6058                pr "    cancel_receive ();\n";
6059              pr "    reply_with_perror (\"realloc\");\n";
6060              pr "    goto done;\n";
6061              pr "  }\n";
6062              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6063              pr "  args.%s.%s_val = %s;\n" n n n;
6064            in
6065            List.iter (
6066              function
6067              | Pathname n ->
6068                  pr_args n;
6069                  pr "  ABS_PATH (%s, %s, goto done);\n"
6070                    n (if is_filein then "cancel_receive ()" else "");
6071              | Device n ->
6072                  pr_args n;
6073                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6074                    n (if is_filein then "cancel_receive ()" else "");
6075              | Dev_or_Path n ->
6076                  pr_args n;
6077                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6078                    n (if is_filein then "cancel_receive ()" else "");
6079              | String n -> pr_args n
6080              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6081              | StringList n ->
6082                  pr_list_handling_code n;
6083              | DeviceList n ->
6084                  pr_list_handling_code n;
6085                  pr "  /* Ensure that each is a device,\n";
6086                  pr "   * and perform device name translation. */\n";
6087                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6088                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6089                    (if is_filein then "cancel_receive ()" else "");
6090                  pr "  }\n";
6091              | Bool n -> pr "  %s = args.%s;\n" n n
6092              | Int n -> pr "  %s = args.%s;\n" n n
6093              | Int64 n -> pr "  %s = args.%s;\n" n n
6094              | FileIn _ | FileOut _ -> ()
6095            ) args;
6096            pr "\n"
6097       );
6098
6099
6100       (* this is used at least for do_equal *)
6101       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6102         (* Emit NEED_ROOT just once, even when there are two or
6103            more Pathname args *)
6104         pr "  NEED_ROOT (%s, goto done);\n"
6105           (if is_filein then "cancel_receive ()" else "");
6106       );
6107
6108       (* Don't want to call the impl with any FileIn or FileOut
6109        * parameters, since these go "outside" the RPC protocol.
6110        *)
6111       let args' =
6112         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6113           (snd style) in
6114       pr "  r = do_%s " name;
6115       generate_c_call_args (fst style, args');
6116       pr ";\n";
6117
6118       (match fst style with
6119        | RErr | RInt _ | RInt64 _ | RBool _
6120        | RConstString _ | RConstOptString _
6121        | RString _ | RStringList _ | RHashtable _
6122        | RStruct (_, _) | RStructList (_, _) ->
6123            pr "  if (r == %s)\n" error_code;
6124            pr "    /* do_%s has already called reply_with_error */\n" name;
6125            pr "    goto done;\n";
6126            pr "\n"
6127        | RBufferOut _ ->
6128            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6129            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6130            pr "   */\n";
6131            pr "  if (size == 1 && r == %s)\n" error_code;
6132            pr "    /* do_%s has already called reply_with_error */\n" name;
6133            pr "    goto done;\n";
6134            pr "\n"
6135       );
6136
6137       (* If there are any FileOut parameters, then the impl must
6138        * send its own reply.
6139        *)
6140       let no_reply =
6141         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6142       if no_reply then
6143         pr "  /* do_%s has already sent a reply */\n" name
6144       else (
6145         match fst style with
6146         | RErr -> pr "  reply (NULL, NULL);\n"
6147         | RInt n | RInt64 n | RBool n ->
6148             pr "  struct guestfs_%s_ret ret;\n" name;
6149             pr "  ret.%s = r;\n" n;
6150             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6151               name
6152         | RConstString _ | RConstOptString _ ->
6153             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6154         | RString n ->
6155             pr "  struct guestfs_%s_ret ret;\n" name;
6156             pr "  ret.%s = r;\n" n;
6157             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6158               name;
6159             pr "  free (r);\n"
6160         | RStringList n | RHashtable n ->
6161             pr "  struct guestfs_%s_ret ret;\n" name;
6162             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6163             pr "  ret.%s.%s_val = r;\n" n n;
6164             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6165               name;
6166             pr "  free_strings (r);\n"
6167         | RStruct (n, _) ->
6168             pr "  struct guestfs_%s_ret ret;\n" name;
6169             pr "  ret.%s = *r;\n" n;
6170             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6171               name;
6172             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6173               name
6174         | RStructList (n, _) ->
6175             pr "  struct guestfs_%s_ret ret;\n" name;
6176             pr "  ret.%s = *r;\n" n;
6177             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6178               name;
6179             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6180               name
6181         | RBufferOut n ->
6182             pr "  struct guestfs_%s_ret ret;\n" name;
6183             pr "  ret.%s.%s_val = r;\n" n n;
6184             pr "  ret.%s.%s_len = size;\n" n n;
6185             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6186               name;
6187             pr "  free (r);\n"
6188       );
6189
6190       (* Free the args. *)
6191       pr "done:\n";
6192       (match snd style with
6193        | [] -> ()
6194        | _ ->
6195            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6196              name
6197       );
6198       pr "  return;\n";
6199       pr "}\n\n";
6200   ) daemon_functions;
6201
6202   (* Dispatch function. *)
6203   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6204   pr "{\n";
6205   pr "  switch (proc_nr) {\n";
6206
6207   List.iter (
6208     fun (name, style, _, _, _, _, _) ->
6209       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6210       pr "      %s_stub (xdr_in);\n" name;
6211       pr "      break;\n"
6212   ) daemon_functions;
6213
6214   pr "    default:\n";
6215   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";
6216   pr "  }\n";
6217   pr "}\n";
6218   pr "\n";
6219
6220   (* LVM columns and tokenization functions. *)
6221   (* XXX This generates crap code.  We should rethink how we
6222    * do this parsing.
6223    *)
6224   List.iter (
6225     function
6226     | typ, cols ->
6227         pr "static const char *lvm_%s_cols = \"%s\";\n"
6228           typ (String.concat "," (List.map fst cols));
6229         pr "\n";
6230
6231         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6232         pr "{\n";
6233         pr "  char *tok, *p, *next;\n";
6234         pr "  int i, j;\n";
6235         pr "\n";
6236         (*
6237           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6238           pr "\n";
6239         *)
6240         pr "  if (!str) {\n";
6241         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6242         pr "    return -1;\n";
6243         pr "  }\n";
6244         pr "  if (!*str || c_isspace (*str)) {\n";
6245         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6246         pr "    return -1;\n";
6247         pr "  }\n";
6248         pr "  tok = str;\n";
6249         List.iter (
6250           fun (name, coltype) ->
6251             pr "  if (!tok) {\n";
6252             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6253             pr "    return -1;\n";
6254             pr "  }\n";
6255             pr "  p = strchrnul (tok, ',');\n";
6256             pr "  if (*p) next = p+1; else next = NULL;\n";
6257             pr "  *p = '\\0';\n";
6258             (match coltype with
6259              | FString ->
6260                  pr "  r->%s = strdup (tok);\n" name;
6261                  pr "  if (r->%s == NULL) {\n" name;
6262                  pr "    perror (\"strdup\");\n";
6263                  pr "    return -1;\n";
6264                  pr "  }\n"
6265              | FUUID ->
6266                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6267                  pr "    if (tok[j] == '\\0') {\n";
6268                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6269                  pr "      return -1;\n";
6270                  pr "    } else if (tok[j] != '-')\n";
6271                  pr "      r->%s[i++] = tok[j];\n" name;
6272                  pr "  }\n";
6273              | FBytes ->
6274                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6275                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6276                  pr "    return -1;\n";
6277                  pr "  }\n";
6278              | FInt64 ->
6279                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6280                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6281                  pr "    return -1;\n";
6282                  pr "  }\n";
6283              | FOptPercent ->
6284                  pr "  if (tok[0] == '\\0')\n";
6285                  pr "    r->%s = -1;\n" name;
6286                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6287                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6288                  pr "    return -1;\n";
6289                  pr "  }\n";
6290              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6291                  assert false (* can never be an LVM column *)
6292             );
6293             pr "  tok = next;\n";
6294         ) cols;
6295
6296         pr "  if (tok != NULL) {\n";
6297         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6298         pr "    return -1;\n";
6299         pr "  }\n";
6300         pr "  return 0;\n";
6301         pr "}\n";
6302         pr "\n";
6303
6304         pr "guestfs_int_lvm_%s_list *\n" typ;
6305         pr "parse_command_line_%ss (void)\n" typ;
6306         pr "{\n";
6307         pr "  char *out, *err;\n";
6308         pr "  char *p, *pend;\n";
6309         pr "  int r, i;\n";
6310         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6311         pr "  void *newp;\n";
6312         pr "\n";
6313         pr "  ret = malloc (sizeof *ret);\n";
6314         pr "  if (!ret) {\n";
6315         pr "    reply_with_perror (\"malloc\");\n";
6316         pr "    return NULL;\n";
6317         pr "  }\n";
6318         pr "\n";
6319         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6320         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6321         pr "\n";
6322         pr "  r = command (&out, &err,\n";
6323         pr "           \"lvm\", \"%ss\",\n" typ;
6324         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6325         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6326         pr "  if (r == -1) {\n";
6327         pr "    reply_with_error (\"%%s\", err);\n";
6328         pr "    free (out);\n";
6329         pr "    free (err);\n";
6330         pr "    free (ret);\n";
6331         pr "    return NULL;\n";
6332         pr "  }\n";
6333         pr "\n";
6334         pr "  free (err);\n";
6335         pr "\n";
6336         pr "  /* Tokenize each line of the output. */\n";
6337         pr "  p = out;\n";
6338         pr "  i = 0;\n";
6339         pr "  while (p) {\n";
6340         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6341         pr "    if (pend) {\n";
6342         pr "      *pend = '\\0';\n";
6343         pr "      pend++;\n";
6344         pr "    }\n";
6345         pr "\n";
6346         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6347         pr "      p++;\n";
6348         pr "\n";
6349         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6350         pr "      p = pend;\n";
6351         pr "      continue;\n";
6352         pr "    }\n";
6353         pr "\n";
6354         pr "    /* Allocate some space to store this next entry. */\n";
6355         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6356         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6357         pr "    if (newp == NULL) {\n";
6358         pr "      reply_with_perror (\"realloc\");\n";
6359         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6360         pr "      free (ret);\n";
6361         pr "      free (out);\n";
6362         pr "      return NULL;\n";
6363         pr "    }\n";
6364         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6365         pr "\n";
6366         pr "    /* Tokenize the next entry. */\n";
6367         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6368         pr "    if (r == -1) {\n";
6369         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6370         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6371         pr "      free (ret);\n";
6372         pr "      free (out);\n";
6373         pr "      return NULL;\n";
6374         pr "    }\n";
6375         pr "\n";
6376         pr "    ++i;\n";
6377         pr "    p = pend;\n";
6378         pr "  }\n";
6379         pr "\n";
6380         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6381         pr "\n";
6382         pr "  free (out);\n";
6383         pr "  return ret;\n";
6384         pr "}\n"
6385
6386   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6387
6388 (* Generate a list of function names, for debugging in the daemon.. *)
6389 and generate_daemon_names () =
6390   generate_header CStyle GPLv2plus;
6391
6392   pr "#include <config.h>\n";
6393   pr "\n";
6394   pr "#include \"daemon.h\"\n";
6395   pr "\n";
6396
6397   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6398   pr "const char *function_names[] = {\n";
6399   List.iter (
6400     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6401   ) daemon_functions;
6402   pr "};\n";
6403
6404 (* Generate the optional groups for the daemon to implement
6405  * guestfs_available.
6406  *)
6407 and generate_daemon_optgroups_c () =
6408   generate_header CStyle GPLv2plus;
6409
6410   pr "#include <config.h>\n";
6411   pr "\n";
6412   pr "#include \"daemon.h\"\n";
6413   pr "#include \"optgroups.h\"\n";
6414   pr "\n";
6415
6416   pr "struct optgroup optgroups[] = {\n";
6417   List.iter (
6418     fun (group, _) ->
6419       pr "  { \"%s\", optgroup_%s_available },\n" group group
6420   ) optgroups;
6421   pr "  { NULL, NULL }\n";
6422   pr "};\n"
6423
6424 and generate_daemon_optgroups_h () =
6425   generate_header CStyle GPLv2plus;
6426
6427   List.iter (
6428     fun (group, _) ->
6429       pr "extern int optgroup_%s_available (void);\n" group
6430   ) optgroups
6431
6432 (* Generate the tests. *)
6433 and generate_tests () =
6434   generate_header CStyle GPLv2plus;
6435
6436   pr "\
6437 #include <stdio.h>
6438 #include <stdlib.h>
6439 #include <string.h>
6440 #include <unistd.h>
6441 #include <sys/types.h>
6442 #include <fcntl.h>
6443
6444 #include \"guestfs.h\"
6445 #include \"guestfs-internal.h\"
6446
6447 static guestfs_h *g;
6448 static int suppress_error = 0;
6449
6450 static void print_error (guestfs_h *g, void *data, const char *msg)
6451 {
6452   if (!suppress_error)
6453     fprintf (stderr, \"%%s\\n\", msg);
6454 }
6455
6456 /* FIXME: nearly identical code appears in fish.c */
6457 static void print_strings (char *const *argv)
6458 {
6459   int argc;
6460
6461   for (argc = 0; argv[argc] != NULL; ++argc)
6462     printf (\"\\t%%s\\n\", argv[argc]);
6463 }
6464
6465 /*
6466 static void print_table (char const *const *argv)
6467 {
6468   int i;
6469
6470   for (i = 0; argv[i] != NULL; i += 2)
6471     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6472 }
6473 */
6474
6475 ";
6476
6477   (* Generate a list of commands which are not tested anywhere. *)
6478   pr "static void no_test_warnings (void)\n";
6479   pr "{\n";
6480
6481   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6482   List.iter (
6483     fun (_, _, _, _, tests, _, _) ->
6484       let tests = filter_map (
6485         function
6486         | (_, (Always|If _|Unless _), test) -> Some test
6487         | (_, Disabled, _) -> None
6488       ) tests in
6489       let seq = List.concat (List.map seq_of_test tests) in
6490       let cmds_tested = List.map List.hd seq in
6491       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6492   ) all_functions;
6493
6494   List.iter (
6495     fun (name, _, _, _, _, _, _) ->
6496       if not (Hashtbl.mem hash name) then
6497         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6498   ) all_functions;
6499
6500   pr "}\n";
6501   pr "\n";
6502
6503   (* Generate the actual tests.  Note that we generate the tests
6504    * in reverse order, deliberately, so that (in general) the
6505    * newest tests run first.  This makes it quicker and easier to
6506    * debug them.
6507    *)
6508   let test_names =
6509     List.map (
6510       fun (name, _, _, flags, tests, _, _) ->
6511         mapi (generate_one_test name flags) tests
6512     ) (List.rev all_functions) in
6513   let test_names = List.concat test_names in
6514   let nr_tests = List.length test_names in
6515
6516   pr "\
6517 int main (int argc, char *argv[])
6518 {
6519   char c = 0;
6520   unsigned long int n_failed = 0;
6521   const char *filename;
6522   int fd;
6523   int nr_tests, test_num = 0;
6524
6525   setbuf (stdout, NULL);
6526
6527   no_test_warnings ();
6528
6529   g = guestfs_create ();
6530   if (g == NULL) {
6531     printf (\"guestfs_create FAILED\\n\");
6532     exit (EXIT_FAILURE);
6533   }
6534
6535   guestfs_set_error_handler (g, print_error, NULL);
6536
6537   guestfs_set_path (g, \"../appliance\");
6538
6539   filename = \"test1.img\";
6540   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6541   if (fd == -1) {
6542     perror (filename);
6543     exit (EXIT_FAILURE);
6544   }
6545   if (lseek (fd, %d, SEEK_SET) == -1) {
6546     perror (\"lseek\");
6547     close (fd);
6548     unlink (filename);
6549     exit (EXIT_FAILURE);
6550   }
6551   if (write (fd, &c, 1) == -1) {
6552     perror (\"write\");
6553     close (fd);
6554     unlink (filename);
6555     exit (EXIT_FAILURE);
6556   }
6557   if (close (fd) == -1) {
6558     perror (filename);
6559     unlink (filename);
6560     exit (EXIT_FAILURE);
6561   }
6562   if (guestfs_add_drive (g, filename) == -1) {
6563     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6564     exit (EXIT_FAILURE);
6565   }
6566
6567   filename = \"test2.img\";
6568   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6569   if (fd == -1) {
6570     perror (filename);
6571     exit (EXIT_FAILURE);
6572   }
6573   if (lseek (fd, %d, SEEK_SET) == -1) {
6574     perror (\"lseek\");
6575     close (fd);
6576     unlink (filename);
6577     exit (EXIT_FAILURE);
6578   }
6579   if (write (fd, &c, 1) == -1) {
6580     perror (\"write\");
6581     close (fd);
6582     unlink (filename);
6583     exit (EXIT_FAILURE);
6584   }
6585   if (close (fd) == -1) {
6586     perror (filename);
6587     unlink (filename);
6588     exit (EXIT_FAILURE);
6589   }
6590   if (guestfs_add_drive (g, filename) == -1) {
6591     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6592     exit (EXIT_FAILURE);
6593   }
6594
6595   filename = \"test3.img\";
6596   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6597   if (fd == -1) {
6598     perror (filename);
6599     exit (EXIT_FAILURE);
6600   }
6601   if (lseek (fd, %d, SEEK_SET) == -1) {
6602     perror (\"lseek\");
6603     close (fd);
6604     unlink (filename);
6605     exit (EXIT_FAILURE);
6606   }
6607   if (write (fd, &c, 1) == -1) {
6608     perror (\"write\");
6609     close (fd);
6610     unlink (filename);
6611     exit (EXIT_FAILURE);
6612   }
6613   if (close (fd) == -1) {
6614     perror (filename);
6615     unlink (filename);
6616     exit (EXIT_FAILURE);
6617   }
6618   if (guestfs_add_drive (g, filename) == -1) {
6619     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6620     exit (EXIT_FAILURE);
6621   }
6622
6623   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6624     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6625     exit (EXIT_FAILURE);
6626   }
6627
6628   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6629   alarm (600);
6630
6631   if (guestfs_launch (g) == -1) {
6632     printf (\"guestfs_launch FAILED\\n\");
6633     exit (EXIT_FAILURE);
6634   }
6635
6636   /* Cancel previous alarm. */
6637   alarm (0);
6638
6639   nr_tests = %d;
6640
6641 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6642
6643   iteri (
6644     fun i test_name ->
6645       pr "  test_num++;\n";
6646       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6647       pr "  if (%s () == -1) {\n" test_name;
6648       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6649       pr "    n_failed++;\n";
6650       pr "  }\n";
6651   ) test_names;
6652   pr "\n";
6653
6654   pr "  guestfs_close (g);\n";
6655   pr "  unlink (\"test1.img\");\n";
6656   pr "  unlink (\"test2.img\");\n";
6657   pr "  unlink (\"test3.img\");\n";
6658   pr "\n";
6659
6660   pr "  if (n_failed > 0) {\n";
6661   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6662   pr "    exit (EXIT_FAILURE);\n";
6663   pr "  }\n";
6664   pr "\n";
6665
6666   pr "  exit (EXIT_SUCCESS);\n";
6667   pr "}\n"
6668
6669 and generate_one_test name flags i (init, prereq, test) =
6670   let test_name = sprintf "test_%s_%d" name i in
6671
6672   pr "\
6673 static int %s_skip (void)
6674 {
6675   const char *str;
6676
6677   str = getenv (\"TEST_ONLY\");
6678   if (str)
6679     return strstr (str, \"%s\") == NULL;
6680   str = getenv (\"SKIP_%s\");
6681   if (str && STREQ (str, \"1\")) return 1;
6682   str = getenv (\"SKIP_TEST_%s\");
6683   if (str && STREQ (str, \"1\")) return 1;
6684   return 0;
6685 }
6686
6687 " test_name name (String.uppercase test_name) (String.uppercase name);
6688
6689   (match prereq with
6690    | Disabled | Always -> ()
6691    | If code | Unless code ->
6692        pr "static int %s_prereq (void)\n" test_name;
6693        pr "{\n";
6694        pr "  %s\n" code;
6695        pr "}\n";
6696        pr "\n";
6697   );
6698
6699   pr "\
6700 static int %s (void)
6701 {
6702   if (%s_skip ()) {
6703     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6704     return 0;
6705   }
6706
6707 " test_name test_name test_name;
6708
6709   (* Optional functions should only be tested if the relevant
6710    * support is available in the daemon.
6711    *)
6712   List.iter (
6713     function
6714     | Optional group ->
6715         pr "  {\n";
6716         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6717         pr "    int r;\n";
6718         pr "    suppress_error = 1;\n";
6719         pr "    r = guestfs_available (g, (char **) groups);\n";
6720         pr "    suppress_error = 0;\n";
6721         pr "    if (r == -1) {\n";
6722         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6723         pr "      return 0;\n";
6724         pr "    }\n";
6725         pr "  }\n";
6726     | _ -> ()
6727   ) flags;
6728
6729   (match prereq with
6730    | Disabled ->
6731        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6732    | If _ ->
6733        pr "  if (! %s_prereq ()) {\n" test_name;
6734        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6735        pr "    return 0;\n";
6736        pr "  }\n";
6737        pr "\n";
6738        generate_one_test_body name i test_name init test;
6739    | Unless _ ->
6740        pr "  if (%s_prereq ()) {\n" test_name;
6741        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6742        pr "    return 0;\n";
6743        pr "  }\n";
6744        pr "\n";
6745        generate_one_test_body name i test_name init test;
6746    | Always ->
6747        generate_one_test_body name i test_name init test
6748   );
6749
6750   pr "  return 0;\n";
6751   pr "}\n";
6752   pr "\n";
6753   test_name
6754
6755 and generate_one_test_body name i test_name init test =
6756   (match init with
6757    | InitNone (* XXX at some point, InitNone and InitEmpty became
6758                * folded together as the same thing.  Really we should
6759                * make InitNone do nothing at all, but the tests may
6760                * need to be checked to make sure this is OK.
6761                *)
6762    | InitEmpty ->
6763        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6764        List.iter (generate_test_command_call test_name)
6765          [["blockdev_setrw"; "/dev/sda"];
6766           ["umount_all"];
6767           ["lvm_remove_all"]]
6768    | InitPartition ->
6769        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6770        List.iter (generate_test_command_call test_name)
6771          [["blockdev_setrw"; "/dev/sda"];
6772           ["umount_all"];
6773           ["lvm_remove_all"];
6774           ["part_disk"; "/dev/sda"; "mbr"]]
6775    | InitBasicFS ->
6776        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6777        List.iter (generate_test_command_call test_name)
6778          [["blockdev_setrw"; "/dev/sda"];
6779           ["umount_all"];
6780           ["lvm_remove_all"];
6781           ["part_disk"; "/dev/sda"; "mbr"];
6782           ["mkfs"; "ext2"; "/dev/sda1"];
6783           ["mount_options"; ""; "/dev/sda1"; "/"]]
6784    | InitBasicFSonLVM ->
6785        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6786          test_name;
6787        List.iter (generate_test_command_call test_name)
6788          [["blockdev_setrw"; "/dev/sda"];
6789           ["umount_all"];
6790           ["lvm_remove_all"];
6791           ["part_disk"; "/dev/sda"; "mbr"];
6792           ["pvcreate"; "/dev/sda1"];
6793           ["vgcreate"; "VG"; "/dev/sda1"];
6794           ["lvcreate"; "LV"; "VG"; "8"];
6795           ["mkfs"; "ext2"; "/dev/VG/LV"];
6796           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6797    | InitISOFS ->
6798        pr "  /* InitISOFS for %s */\n" test_name;
6799        List.iter (generate_test_command_call test_name)
6800          [["blockdev_setrw"; "/dev/sda"];
6801           ["umount_all"];
6802           ["lvm_remove_all"];
6803           ["mount_ro"; "/dev/sdd"; "/"]]
6804   );
6805
6806   let get_seq_last = function
6807     | [] ->
6808         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6809           test_name
6810     | seq ->
6811         let seq = List.rev seq in
6812         List.rev (List.tl seq), List.hd seq
6813   in
6814
6815   match test with
6816   | TestRun seq ->
6817       pr "  /* TestRun for %s (%d) */\n" name i;
6818       List.iter (generate_test_command_call test_name) seq
6819   | TestOutput (seq, expected) ->
6820       pr "  /* TestOutput for %s (%d) */\n" name i;
6821       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6822       let seq, last = get_seq_last seq in
6823       let test () =
6824         pr "    if (STRNEQ (r, expected)) {\n";
6825         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6826         pr "      return -1;\n";
6827         pr "    }\n"
6828       in
6829       List.iter (generate_test_command_call test_name) seq;
6830       generate_test_command_call ~test test_name last
6831   | TestOutputList (seq, expected) ->
6832       pr "  /* TestOutputList for %s (%d) */\n" name i;
6833       let seq, last = get_seq_last seq in
6834       let test () =
6835         iteri (
6836           fun i str ->
6837             pr "    if (!r[%d]) {\n" i;
6838             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6839             pr "      print_strings (r);\n";
6840             pr "      return -1;\n";
6841             pr "    }\n";
6842             pr "    {\n";
6843             pr "      const char *expected = \"%s\";\n" (c_quote str);
6844             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6845             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6846             pr "        return -1;\n";
6847             pr "      }\n";
6848             pr "    }\n"
6849         ) expected;
6850         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6851         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6852           test_name;
6853         pr "      print_strings (r);\n";
6854         pr "      return -1;\n";
6855         pr "    }\n"
6856       in
6857       List.iter (generate_test_command_call test_name) seq;
6858       generate_test_command_call ~test test_name last
6859   | TestOutputListOfDevices (seq, expected) ->
6860       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6861       let seq, last = get_seq_last seq in
6862       let test () =
6863         iteri (
6864           fun i str ->
6865             pr "    if (!r[%d]) {\n" i;
6866             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6867             pr "      print_strings (r);\n";
6868             pr "      return -1;\n";
6869             pr "    }\n";
6870             pr "    {\n";
6871             pr "      const char *expected = \"%s\";\n" (c_quote str);
6872             pr "      r[%d][5] = 's';\n" i;
6873             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6874             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6875             pr "        return -1;\n";
6876             pr "      }\n";
6877             pr "    }\n"
6878         ) expected;
6879         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6880         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6881           test_name;
6882         pr "      print_strings (r);\n";
6883         pr "      return -1;\n";
6884         pr "    }\n"
6885       in
6886       List.iter (generate_test_command_call test_name) seq;
6887       generate_test_command_call ~test test_name last
6888   | TestOutputInt (seq, expected) ->
6889       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6890       let seq, last = get_seq_last seq in
6891       let test () =
6892         pr "    if (r != %d) {\n" expected;
6893         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6894           test_name expected;
6895         pr "               (int) r);\n";
6896         pr "      return -1;\n";
6897         pr "    }\n"
6898       in
6899       List.iter (generate_test_command_call test_name) seq;
6900       generate_test_command_call ~test test_name last
6901   | TestOutputIntOp (seq, op, expected) ->
6902       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6903       let seq, last = get_seq_last seq in
6904       let test () =
6905         pr "    if (! (r %s %d)) {\n" op expected;
6906         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6907           test_name op expected;
6908         pr "               (int) 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   | TestOutputTrue seq ->
6915       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6916       let seq, last = get_seq_last seq in
6917       let test () =
6918         pr "    if (!r) {\n";
6919         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6920           test_name;
6921         pr "      return -1;\n";
6922         pr "    }\n"
6923       in
6924       List.iter (generate_test_command_call test_name) seq;
6925       generate_test_command_call ~test test_name last
6926   | TestOutputFalse seq ->
6927       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6928       let seq, last = get_seq_last seq in
6929       let test () =
6930         pr "    if (r) {\n";
6931         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6932           test_name;
6933         pr "      return -1;\n";
6934         pr "    }\n"
6935       in
6936       List.iter (generate_test_command_call test_name) seq;
6937       generate_test_command_call ~test test_name last
6938   | TestOutputLength (seq, expected) ->
6939       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6940       let seq, last = get_seq_last seq in
6941       let test () =
6942         pr "    int j;\n";
6943         pr "    for (j = 0; j < %d; ++j)\n" expected;
6944         pr "      if (r[j] == NULL) {\n";
6945         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6946           test_name;
6947         pr "        print_strings (r);\n";
6948         pr "        return -1;\n";
6949         pr "      }\n";
6950         pr "    if (r[j] != NULL) {\n";
6951         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6952           test_name;
6953         pr "      print_strings (r);\n";
6954         pr "      return -1;\n";
6955         pr "    }\n"
6956       in
6957       List.iter (generate_test_command_call test_name) seq;
6958       generate_test_command_call ~test test_name last
6959   | TestOutputBuffer (seq, expected) ->
6960       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6961       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6962       let seq, last = get_seq_last seq in
6963       let len = String.length expected in
6964       let test () =
6965         pr "    if (size != %d) {\n" len;
6966         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6967         pr "      return -1;\n";
6968         pr "    }\n";
6969         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6970         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6971         pr "      return -1;\n";
6972         pr "    }\n"
6973       in
6974       List.iter (generate_test_command_call test_name) seq;
6975       generate_test_command_call ~test test_name last
6976   | TestOutputStruct (seq, checks) ->
6977       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6978       let seq, last = get_seq_last seq in
6979       let test () =
6980         List.iter (
6981           function
6982           | CompareWithInt (field, expected) ->
6983               pr "    if (r->%s != %d) {\n" field expected;
6984               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6985                 test_name field expected;
6986               pr "               (int) r->%s);\n" field;
6987               pr "      return -1;\n";
6988               pr "    }\n"
6989           | CompareWithIntOp (field, op, expected) ->
6990               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6991               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6992                 test_name field op expected;
6993               pr "               (int) r->%s);\n" field;
6994               pr "      return -1;\n";
6995               pr "    }\n"
6996           | CompareWithString (field, expected) ->
6997               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6998               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6999                 test_name field expected;
7000               pr "               r->%s);\n" field;
7001               pr "      return -1;\n";
7002               pr "    }\n"
7003           | CompareFieldsIntEq (field1, field2) ->
7004               pr "    if (r->%s != r->%s) {\n" field1 field2;
7005               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7006                 test_name field1 field2;
7007               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7008               pr "      return -1;\n";
7009               pr "    }\n"
7010           | CompareFieldsStrEq (field1, field2) ->
7011               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7012               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7013                 test_name field1 field2;
7014               pr "               r->%s, r->%s);\n" field1 field2;
7015               pr "      return -1;\n";
7016               pr "    }\n"
7017         ) checks
7018       in
7019       List.iter (generate_test_command_call test_name) seq;
7020       generate_test_command_call ~test test_name last
7021   | TestLastFail seq ->
7022       pr "  /* TestLastFail for %s (%d) */\n" name i;
7023       let seq, last = get_seq_last seq in
7024       List.iter (generate_test_command_call test_name) seq;
7025       generate_test_command_call test_name ~expect_error:true last
7026
7027 (* Generate the code to run a command, leaving the result in 'r'.
7028  * If you expect to get an error then you should set expect_error:true.
7029  *)
7030 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7031   match cmd with
7032   | [] -> assert false
7033   | name :: args ->
7034       (* Look up the command to find out what args/ret it has. *)
7035       let style =
7036         try
7037           let _, style, _, _, _, _, _ =
7038             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7039           style
7040         with Not_found ->
7041           failwithf "%s: in test, command %s was not found" test_name name in
7042
7043       if List.length (snd style) <> List.length args then
7044         failwithf "%s: in test, wrong number of args given to %s"
7045           test_name name;
7046
7047       pr "  {\n";
7048
7049       List.iter (
7050         function
7051         | OptString n, "NULL" -> ()
7052         | Pathname n, arg
7053         | Device n, arg
7054         | Dev_or_Path n, arg
7055         | String n, arg
7056         | OptString n, arg ->
7057             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7058         | Int _, _
7059         | Int64 _, _
7060         | Bool _, _
7061         | FileIn _, _ | FileOut _, _ -> ()
7062         | StringList n, "" | DeviceList n, "" ->
7063             pr "    const char *const %s[1] = { NULL };\n" n
7064         | StringList n, arg | DeviceList n, arg ->
7065             let strs = string_split " " arg in
7066             iteri (
7067               fun i str ->
7068                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7069             ) strs;
7070             pr "    const char *const %s[] = {\n" n;
7071             iteri (
7072               fun i _ -> pr "      %s_%d,\n" n i
7073             ) strs;
7074             pr "      NULL\n";
7075             pr "    };\n";
7076       ) (List.combine (snd style) args);
7077
7078       let error_code =
7079         match fst style with
7080         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7081         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7082         | RConstString _ | RConstOptString _ ->
7083             pr "    const char *r;\n"; "NULL"
7084         | RString _ -> pr "    char *r;\n"; "NULL"
7085         | RStringList _ | RHashtable _ ->
7086             pr "    char **r;\n";
7087             pr "    int i;\n";
7088             "NULL"
7089         | RStruct (_, typ) ->
7090             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7091         | RStructList (_, typ) ->
7092             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7093         | RBufferOut _ ->
7094             pr "    char *r;\n";
7095             pr "    size_t size;\n";
7096             "NULL" in
7097
7098       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7099       pr "    r = guestfs_%s (g" name;
7100
7101       (* Generate the parameters. *)
7102       List.iter (
7103         function
7104         | OptString _, "NULL" -> pr ", NULL"
7105         | Pathname n, _
7106         | Device n, _ | Dev_or_Path n, _
7107         | String n, _
7108         | OptString n, _ ->
7109             pr ", %s" n
7110         | FileIn _, arg | FileOut _, arg ->
7111             pr ", \"%s\"" (c_quote arg)
7112         | StringList n, _ | DeviceList n, _ ->
7113             pr ", (char **) %s" n
7114         | Int _, arg ->
7115             let i =
7116               try int_of_string arg
7117               with Failure "int_of_string" ->
7118                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7119             pr ", %d" i
7120         | Int64 _, arg ->
7121             let i =
7122               try Int64.of_string arg
7123               with Failure "int_of_string" ->
7124                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7125             pr ", %Ld" i
7126         | Bool _, arg ->
7127             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7128       ) (List.combine (snd style) args);
7129
7130       (match fst style with
7131        | RBufferOut _ -> pr ", &size"
7132        | _ -> ()
7133       );
7134
7135       pr ");\n";
7136
7137       if not expect_error then
7138         pr "    if (r == %s)\n" error_code
7139       else
7140         pr "    if (r != %s)\n" error_code;
7141       pr "      return -1;\n";
7142
7143       (* Insert the test code. *)
7144       (match test with
7145        | None -> ()
7146        | Some f -> f ()
7147       );
7148
7149       (match fst style with
7150        | RErr | RInt _ | RInt64 _ | RBool _
7151        | RConstString _ | RConstOptString _ -> ()
7152        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7153        | RStringList _ | RHashtable _ ->
7154            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7155            pr "      free (r[i]);\n";
7156            pr "    free (r);\n"
7157        | RStruct (_, typ) ->
7158            pr "    guestfs_free_%s (r);\n" typ
7159        | RStructList (_, typ) ->
7160            pr "    guestfs_free_%s_list (r);\n" typ
7161       );
7162
7163       pr "  }\n"
7164
7165 and c_quote str =
7166   let str = replace_str str "\r" "\\r" in
7167   let str = replace_str str "\n" "\\n" in
7168   let str = replace_str str "\t" "\\t" in
7169   let str = replace_str str "\000" "\\0" in
7170   str
7171
7172 (* Generate a lot of different functions for guestfish. *)
7173 and generate_fish_cmds () =
7174   generate_header CStyle GPLv2plus;
7175
7176   let all_functions =
7177     List.filter (
7178       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7179     ) all_functions in
7180   let all_functions_sorted =
7181     List.filter (
7182       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7183     ) all_functions_sorted in
7184
7185   pr "#include <config.h>\n";
7186   pr "\n";
7187   pr "#include <stdio.h>\n";
7188   pr "#include <stdlib.h>\n";
7189   pr "#include <string.h>\n";
7190   pr "#include <inttypes.h>\n";
7191   pr "\n";
7192   pr "#include <guestfs.h>\n";
7193   pr "#include \"c-ctype.h\"\n";
7194   pr "#include \"full-write.h\"\n";
7195   pr "#include \"xstrtol.h\"\n";
7196   pr "#include \"fish.h\"\n";
7197   pr "\n";
7198
7199   (* list_commands function, which implements guestfish -h *)
7200   pr "void list_commands (void)\n";
7201   pr "{\n";
7202   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7203   pr "  list_builtin_commands ();\n";
7204   List.iter (
7205     fun (name, _, _, flags, _, shortdesc, _) ->
7206       let name = replace_char name '_' '-' in
7207       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7208         name shortdesc
7209   ) all_functions_sorted;
7210   pr "  printf (\"    %%s\\n\",";
7211   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7212   pr "}\n";
7213   pr "\n";
7214
7215   (* display_command function, which implements guestfish -h cmd *)
7216   pr "void display_command (const char *cmd)\n";
7217   pr "{\n";
7218   List.iter (
7219     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7220       let name2 = replace_char name '_' '-' in
7221       let alias =
7222         try find_map (function FishAlias n -> Some n | _ -> None) flags
7223         with Not_found -> name in
7224       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7225       let synopsis =
7226         match snd style with
7227         | [] -> name2
7228         | args ->
7229             sprintf "%s %s"
7230               name2 (String.concat " " (List.map name_of_argt args)) in
7231
7232       let warnings =
7233         if List.mem ProtocolLimitWarning flags then
7234           ("\n\n" ^ protocol_limit_warning)
7235         else "" in
7236
7237       (* For DangerWillRobinson commands, we should probably have
7238        * guestfish prompt before allowing you to use them (especially
7239        * in interactive mode). XXX
7240        *)
7241       let warnings =
7242         warnings ^
7243           if List.mem DangerWillRobinson flags then
7244             ("\n\n" ^ danger_will_robinson)
7245           else "" in
7246
7247       let warnings =
7248         warnings ^
7249           match deprecation_notice flags with
7250           | None -> ""
7251           | Some txt -> "\n\n" ^ txt in
7252
7253       let describe_alias =
7254         if name <> alias then
7255           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7256         else "" in
7257
7258       pr "  if (";
7259       pr "STRCASEEQ (cmd, \"%s\")" name;
7260       if name <> name2 then
7261         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7262       if name <> alias then
7263         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7264       pr ")\n";
7265       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7266         name2 shortdesc
7267         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7268          "=head1 DESCRIPTION\n\n" ^
7269          longdesc ^ warnings ^ describe_alias);
7270       pr "  else\n"
7271   ) all_functions;
7272   pr "    display_builtin_command (cmd);\n";
7273   pr "}\n";
7274   pr "\n";
7275
7276   let emit_print_list_function typ =
7277     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7278       typ typ typ;
7279     pr "{\n";
7280     pr "  unsigned int i;\n";
7281     pr "\n";
7282     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7283     pr "    printf (\"[%%d] = {\\n\", i);\n";
7284     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7285     pr "    printf (\"}\\n\");\n";
7286     pr "  }\n";
7287     pr "}\n";
7288     pr "\n";
7289   in
7290
7291   (* print_* functions *)
7292   List.iter (
7293     fun (typ, cols) ->
7294       let needs_i =
7295         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7296
7297       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7298       pr "{\n";
7299       if needs_i then (
7300         pr "  unsigned int i;\n";
7301         pr "\n"
7302       );
7303       List.iter (
7304         function
7305         | name, FString ->
7306             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7307         | name, FUUID ->
7308             pr "  printf (\"%%s%s: \", indent);\n" name;
7309             pr "  for (i = 0; i < 32; ++i)\n";
7310             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7311             pr "  printf (\"\\n\");\n"
7312         | name, FBuffer ->
7313             pr "  printf (\"%%s%s: \", indent);\n" name;
7314             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7315             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7316             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7317             pr "    else\n";
7318             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7319             pr "  printf (\"\\n\");\n"
7320         | name, (FUInt64|FBytes) ->
7321             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7322               name typ name
7323         | name, FInt64 ->
7324             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7325               name typ name
7326         | name, FUInt32 ->
7327             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7328               name typ name
7329         | name, FInt32 ->
7330             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7331               name typ name
7332         | name, FChar ->
7333             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7334               name typ name
7335         | name, FOptPercent ->
7336             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7337               typ name name typ name;
7338             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7339       ) cols;
7340       pr "}\n";
7341       pr "\n";
7342   ) structs;
7343
7344   (* Emit a print_TYPE_list function definition only if that function is used. *)
7345   List.iter (
7346     function
7347     | typ, (RStructListOnly | RStructAndList) ->
7348         (* generate the function for typ *)
7349         emit_print_list_function typ
7350     | typ, _ -> () (* empty *)
7351   ) (rstructs_used_by all_functions);
7352
7353   (* Emit a print_TYPE function definition only if that function is used. *)
7354   List.iter (
7355     function
7356     | typ, (RStructOnly | RStructAndList) ->
7357         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7358         pr "{\n";
7359         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7360         pr "}\n";
7361         pr "\n";
7362     | typ, _ -> () (* empty *)
7363   ) (rstructs_used_by all_functions);
7364
7365   (* run_<action> actions *)
7366   List.iter (
7367     fun (name, style, _, flags, _, _, _) ->
7368       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7369       pr "{\n";
7370       (match fst style with
7371        | RErr
7372        | RInt _
7373        | RBool _ -> pr "  int r;\n"
7374        | RInt64 _ -> pr "  int64_t r;\n"
7375        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7376        | RString _ -> pr "  char *r;\n"
7377        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7378        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7379        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7380        | RBufferOut _ ->
7381            pr "  char *r;\n";
7382            pr "  size_t size;\n";
7383       );
7384       List.iter (
7385         function
7386         | Device n
7387         | String n
7388         | OptString n
7389         | FileIn n
7390         | FileOut n -> pr "  const char *%s;\n" n
7391         | Pathname n
7392         | Dev_or_Path n -> pr "  char *%s;\n" n
7393         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7394         | Bool n -> pr "  int %s;\n" n
7395         | Int n -> pr "  int %s;\n" n
7396         | Int64 n -> pr "  int64_t %s;\n" n
7397       ) (snd style);
7398
7399       (* Check and convert parameters. *)
7400       let argc_expected = List.length (snd style) in
7401       pr "  if (argc != %d) {\n" argc_expected;
7402       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7403         argc_expected;
7404       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7405       pr "    return -1;\n";
7406       pr "  }\n";
7407
7408       let parse_integer fn fntyp rtyp range name i =
7409         pr "  {\n";
7410         pr "    strtol_error xerr;\n";
7411         pr "    %s r;\n" fntyp;
7412         pr "\n";
7413         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7414         pr "    if (xerr != LONGINT_OK) {\n";
7415         pr "      fprintf (stderr,\n";
7416         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7417         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7418         pr "      return -1;\n";
7419         pr "    }\n";
7420         (match range with
7421          | None -> ()
7422          | Some (min, max, comment) ->
7423              pr "    /* %s */\n" comment;
7424              pr "    if (r < %s || r > %s) {\n" min max;
7425              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7426                name;
7427              pr "      return -1;\n";
7428              pr "    }\n";
7429              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7430         );
7431         pr "    %s = r;\n" name;
7432         pr "  }\n";
7433       in
7434
7435       iteri (
7436         fun i ->
7437           function
7438           | Device name
7439           | String name ->
7440               pr "  %s = argv[%d];\n" name i
7441           | Pathname name
7442           | Dev_or_Path name ->
7443               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7444               pr "  if (%s == NULL) return -1;\n" name
7445           | OptString name ->
7446               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7447                 name i i
7448           | FileIn name ->
7449               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7450                 name i i
7451           | FileOut name ->
7452               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7453                 name i i
7454           | StringList name | DeviceList name ->
7455               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7456               pr "  if (%s == NULL) return -1;\n" name;
7457           | Bool name ->
7458               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7459           | Int name ->
7460               let range =
7461                 let min = "(-(2LL<<30))"
7462                 and max = "((2LL<<30)-1)"
7463                 and comment =
7464                   "The Int type in the generator is a signed 31 bit int." in
7465                 Some (min, max, comment) in
7466               parse_integer "xstrtoll" "long long" "int" range name i
7467           | Int64 name ->
7468               parse_integer "xstrtoll" "long long" "int64_t" None name i
7469       ) (snd style);
7470
7471       (* Call C API function. *)
7472       let fn =
7473         try find_map (function FishAction n -> Some n | _ -> None) flags
7474         with Not_found -> sprintf "guestfs_%s" name in
7475       pr "  r = %s " fn;
7476       generate_c_call_args ~handle:"g" style;
7477       pr ";\n";
7478
7479       List.iter (
7480         function
7481         | Device name | String name
7482         | OptString name | FileIn name | FileOut name | Bool name
7483         | Int name | Int64 name -> ()
7484         | Pathname name | Dev_or_Path name ->
7485             pr "  free (%s);\n" name
7486         | StringList name | DeviceList name ->
7487             pr "  free_strings (%s);\n" name
7488       ) (snd style);
7489
7490       (* Any output flags? *)
7491       let fish_output =
7492         let flags = filter_map (
7493           function FishOutput flag -> Some flag | _ -> None
7494         ) flags in
7495         match flags with
7496         | [] -> None
7497         | [f] -> Some f
7498         | _ ->
7499             failwithf "%s: more than one FishOutput flag is not allowed" name in
7500
7501       (* Check return value for errors and display command results. *)
7502       (match fst style with
7503        | RErr -> pr "  return r;\n"
7504        | RInt _ ->
7505            pr "  if (r == -1) return -1;\n";
7506            (match fish_output with
7507             | None ->
7508                 pr "  printf (\"%%d\\n\", r);\n";
7509             | Some FishOutputOctal ->
7510                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7511             | Some FishOutputHexadecimal ->
7512                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7513            pr "  return 0;\n"
7514        | RInt64 _ ->
7515            pr "  if (r == -1) return -1;\n";
7516            (match fish_output with
7517             | None ->
7518                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7519             | Some FishOutputOctal ->
7520                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7521             | Some FishOutputHexadecimal ->
7522                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7523            pr "  return 0;\n"
7524        | RBool _ ->
7525            pr "  if (r == -1) return -1;\n";
7526            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7527            pr "  return 0;\n"
7528        | RConstString _ ->
7529            pr "  if (r == NULL) return -1;\n";
7530            pr "  printf (\"%%s\\n\", r);\n";
7531            pr "  return 0;\n"
7532        | RConstOptString _ ->
7533            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7534            pr "  return 0;\n"
7535        | RString _ ->
7536            pr "  if (r == NULL) return -1;\n";
7537            pr "  printf (\"%%s\\n\", r);\n";
7538            pr "  free (r);\n";
7539            pr "  return 0;\n"
7540        | RStringList _ ->
7541            pr "  if (r == NULL) return -1;\n";
7542            pr "  print_strings (r);\n";
7543            pr "  free_strings (r);\n";
7544            pr "  return 0;\n"
7545        | RStruct (_, typ) ->
7546            pr "  if (r == NULL) return -1;\n";
7547            pr "  print_%s (r);\n" typ;
7548            pr "  guestfs_free_%s (r);\n" typ;
7549            pr "  return 0;\n"
7550        | RStructList (_, typ) ->
7551            pr "  if (r == NULL) return -1;\n";
7552            pr "  print_%s_list (r);\n" typ;
7553            pr "  guestfs_free_%s_list (r);\n" typ;
7554            pr "  return 0;\n"
7555        | RHashtable _ ->
7556            pr "  if (r == NULL) return -1;\n";
7557            pr "  print_table (r);\n";
7558            pr "  free_strings (r);\n";
7559            pr "  return 0;\n"
7560        | RBufferOut _ ->
7561            pr "  if (r == NULL) return -1;\n";
7562            pr "  if (full_write (1, r, size) != size) {\n";
7563            pr "    perror (\"write\");\n";
7564            pr "    free (r);\n";
7565            pr "    return -1;\n";
7566            pr "  }\n";
7567            pr "  free (r);\n";
7568            pr "  return 0;\n"
7569       );
7570       pr "}\n";
7571       pr "\n"
7572   ) all_functions;
7573
7574   (* run_action function *)
7575   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7576   pr "{\n";
7577   List.iter (
7578     fun (name, _, _, flags, _, _, _) ->
7579       let name2 = replace_char name '_' '-' in
7580       let alias =
7581         try find_map (function FishAlias n -> Some n | _ -> None) flags
7582         with Not_found -> name in
7583       pr "  if (";
7584       pr "STRCASEEQ (cmd, \"%s\")" name;
7585       if name <> name2 then
7586         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7587       if name <> alias then
7588         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7589       pr ")\n";
7590       pr "    return run_%s (cmd, argc, argv);\n" name;
7591       pr "  else\n";
7592   ) all_functions;
7593   pr "    {\n";
7594   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7595   pr "      if (command_num == 1)\n";
7596   pr "        extended_help_message ();\n";
7597   pr "      return -1;\n";
7598   pr "    }\n";
7599   pr "  return 0;\n";
7600   pr "}\n";
7601   pr "\n"
7602
7603 (* Readline completion for guestfish. *)
7604 and generate_fish_completion () =
7605   generate_header CStyle GPLv2plus;
7606
7607   let all_functions =
7608     List.filter (
7609       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7610     ) all_functions in
7611
7612   pr "\
7613 #include <config.h>
7614
7615 #include <stdio.h>
7616 #include <stdlib.h>
7617 #include <string.h>
7618
7619 #ifdef HAVE_LIBREADLINE
7620 #include <readline/readline.h>
7621 #endif
7622
7623 #include \"fish.h\"
7624
7625 #ifdef HAVE_LIBREADLINE
7626
7627 static const char *const commands[] = {
7628   BUILTIN_COMMANDS_FOR_COMPLETION,
7629 ";
7630
7631   (* Get the commands, including the aliases.  They don't need to be
7632    * sorted - the generator() function just does a dumb linear search.
7633    *)
7634   let commands =
7635     List.map (
7636       fun (name, _, _, flags, _, _, _) ->
7637         let name2 = replace_char name '_' '-' in
7638         let alias =
7639           try find_map (function FishAlias n -> Some n | _ -> None) flags
7640           with Not_found -> name in
7641
7642         if name <> alias then [name2; alias] else [name2]
7643     ) all_functions in
7644   let commands = List.flatten commands in
7645
7646   List.iter (pr "  \"%s\",\n") commands;
7647
7648   pr "  NULL
7649 };
7650
7651 static char *
7652 generator (const char *text, int state)
7653 {
7654   static int index, len;
7655   const char *name;
7656
7657   if (!state) {
7658     index = 0;
7659     len = strlen (text);
7660   }
7661
7662   rl_attempted_completion_over = 1;
7663
7664   while ((name = commands[index]) != NULL) {
7665     index++;
7666     if (STRCASEEQLEN (name, text, len))
7667       return strdup (name);
7668   }
7669
7670   return NULL;
7671 }
7672
7673 #endif /* HAVE_LIBREADLINE */
7674
7675 #ifdef HAVE_RL_COMPLETION_MATCHES
7676 #define RL_COMPLETION_MATCHES rl_completion_matches
7677 #else
7678 #ifdef HAVE_COMPLETION_MATCHES
7679 #define RL_COMPLETION_MATCHES completion_matches
7680 #endif
7681 #endif /* else just fail if we don't have either symbol */
7682
7683 char **
7684 do_completion (const char *text, int start, int end)
7685 {
7686   char **matches = NULL;
7687
7688 #ifdef HAVE_LIBREADLINE
7689   rl_completion_append_character = ' ';
7690
7691   if (start == 0)
7692     matches = RL_COMPLETION_MATCHES (text, generator);
7693   else if (complete_dest_paths)
7694     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7695 #endif
7696
7697   return matches;
7698 }
7699 ";
7700
7701 (* Generate the POD documentation for guestfish. *)
7702 and generate_fish_actions_pod () =
7703   let all_functions_sorted =
7704     List.filter (
7705       fun (_, _, _, flags, _, _, _) ->
7706         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7707     ) all_functions_sorted in
7708
7709   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7710
7711   List.iter (
7712     fun (name, style, _, flags, _, _, longdesc) ->
7713       let longdesc =
7714         Str.global_substitute rex (
7715           fun s ->
7716             let sub =
7717               try Str.matched_group 1 s
7718               with Not_found ->
7719                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7720             "C<" ^ replace_char sub '_' '-' ^ ">"
7721         ) longdesc in
7722       let name = replace_char name '_' '-' in
7723       let alias =
7724         try find_map (function FishAlias n -> Some n | _ -> None) flags
7725         with Not_found -> name in
7726
7727       pr "=head2 %s" name;
7728       if name <> alias then
7729         pr " | %s" alias;
7730       pr "\n";
7731       pr "\n";
7732       pr " %s" name;
7733       List.iter (
7734         function
7735         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7736         | OptString n -> pr " %s" n
7737         | StringList n | DeviceList n -> pr " '%s ...'" n
7738         | Bool _ -> pr " true|false"
7739         | Int n -> pr " %s" n
7740         | Int64 n -> pr " %s" n
7741         | FileIn n | FileOut n -> pr " (%s|-)" n
7742       ) (snd style);
7743       pr "\n";
7744       pr "\n";
7745       pr "%s\n\n" longdesc;
7746
7747       if List.exists (function FileIn _ | FileOut _ -> true
7748                       | _ -> false) (snd style) then
7749         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7750
7751       if List.mem ProtocolLimitWarning flags then
7752         pr "%s\n\n" protocol_limit_warning;
7753
7754       if List.mem DangerWillRobinson flags then
7755         pr "%s\n\n" danger_will_robinson;
7756
7757       match deprecation_notice flags with
7758       | None -> ()
7759       | Some txt -> pr "%s\n\n" txt
7760   ) all_functions_sorted
7761
7762 (* Generate a C function prototype. *)
7763 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7764     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7765     ?(prefix = "")
7766     ?handle name style =
7767   if extern then pr "extern ";
7768   if static then pr "static ";
7769   (match fst style with
7770    | RErr -> pr "int "
7771    | RInt _ -> pr "int "
7772    | RInt64 _ -> pr "int64_t "
7773    | RBool _ -> pr "int "
7774    | RConstString _ | RConstOptString _ -> pr "const char *"
7775    | RString _ | RBufferOut _ -> pr "char *"
7776    | RStringList _ | RHashtable _ -> pr "char **"
7777    | RStruct (_, typ) ->
7778        if not in_daemon then pr "struct guestfs_%s *" typ
7779        else pr "guestfs_int_%s *" typ
7780    | RStructList (_, typ) ->
7781        if not in_daemon then pr "struct guestfs_%s_list *" typ
7782        else pr "guestfs_int_%s_list *" typ
7783   );
7784   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7785   pr "%s%s (" prefix name;
7786   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7787     pr "void"
7788   else (
7789     let comma = ref false in
7790     (match handle with
7791      | None -> ()
7792      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7793     );
7794     let next () =
7795       if !comma then (
7796         if single_line then pr ", " else pr ",\n\t\t"
7797       );
7798       comma := true
7799     in
7800     List.iter (
7801       function
7802       | Pathname n
7803       | Device n | Dev_or_Path n
7804       | String n
7805       | OptString n ->
7806           next ();
7807           pr "const char *%s" n
7808       | StringList n | DeviceList n ->
7809           next ();
7810           pr "char *const *%s" n
7811       | Bool n -> next (); pr "int %s" n
7812       | Int n -> next (); pr "int %s" n
7813       | Int64 n -> next (); pr "int64_t %s" n
7814       | FileIn n
7815       | FileOut n ->
7816           if not in_daemon then (next (); pr "const char *%s" n)
7817     ) (snd style);
7818     if is_RBufferOut then (next (); pr "size_t *size_r");
7819   );
7820   pr ")";
7821   if semicolon then pr ";";
7822   if newline then pr "\n"
7823
7824 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7825 and generate_c_call_args ?handle ?(decl = false) style =
7826   pr "(";
7827   let comma = ref false in
7828   let next () =
7829     if !comma then pr ", ";
7830     comma := true
7831   in
7832   (match handle with
7833    | None -> ()
7834    | Some handle -> pr "%s" handle; comma := true
7835   );
7836   List.iter (
7837     fun arg ->
7838       next ();
7839       pr "%s" (name_of_argt arg)
7840   ) (snd style);
7841   (* For RBufferOut calls, add implicit &size parameter. *)
7842   if not decl then (
7843     match fst style with
7844     | RBufferOut _ ->
7845         next ();
7846         pr "&size"
7847     | _ -> ()
7848   );
7849   pr ")"
7850
7851 (* Generate the OCaml bindings interface. *)
7852 and generate_ocaml_mli () =
7853   generate_header OCamlStyle LGPLv2plus;
7854
7855   pr "\
7856 (** For API documentation you should refer to the C API
7857     in the guestfs(3) manual page.  The OCaml API uses almost
7858     exactly the same calls. *)
7859
7860 type t
7861 (** A [guestfs_h] handle. *)
7862
7863 exception Error of string
7864 (** This exception is raised when there is an error. *)
7865
7866 exception Handle_closed of string
7867 (** This exception is raised if you use a {!Guestfs.t} handle
7868     after calling {!close} on it.  The string is the name of
7869     the function. *)
7870
7871 val create : unit -> t
7872 (** Create a {!Guestfs.t} handle. *)
7873
7874 val close : t -> unit
7875 (** Close the {!Guestfs.t} handle and free up all resources used
7876     by it immediately.
7877
7878     Handles are closed by the garbage collector when they become
7879     unreferenced, but callers can call this in order to provide
7880     predictable cleanup. *)
7881
7882 ";
7883   generate_ocaml_structure_decls ();
7884
7885   (* The actions. *)
7886   List.iter (
7887     fun (name, style, _, _, _, shortdesc, _) ->
7888       generate_ocaml_prototype name style;
7889       pr "(** %s *)\n" shortdesc;
7890       pr "\n"
7891   ) all_functions_sorted
7892
7893 (* Generate the OCaml bindings implementation. *)
7894 and generate_ocaml_ml () =
7895   generate_header OCamlStyle LGPLv2plus;
7896
7897   pr "\
7898 type t
7899
7900 exception Error of string
7901 exception Handle_closed of string
7902
7903 external create : unit -> t = \"ocaml_guestfs_create\"
7904 external close : t -> unit = \"ocaml_guestfs_close\"
7905
7906 (* Give the exceptions names, so they can be raised from the C code. *)
7907 let () =
7908   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7909   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7910
7911 ";
7912
7913   generate_ocaml_structure_decls ();
7914
7915   (* The actions. *)
7916   List.iter (
7917     fun (name, style, _, _, _, shortdesc, _) ->
7918       generate_ocaml_prototype ~is_external:true name style;
7919   ) all_functions_sorted
7920
7921 (* Generate the OCaml bindings C implementation. *)
7922 and generate_ocaml_c () =
7923   generate_header CStyle LGPLv2plus;
7924
7925   pr "\
7926 #include <stdio.h>
7927 #include <stdlib.h>
7928 #include <string.h>
7929
7930 #include <caml/config.h>
7931 #include <caml/alloc.h>
7932 #include <caml/callback.h>
7933 #include <caml/fail.h>
7934 #include <caml/memory.h>
7935 #include <caml/mlvalues.h>
7936 #include <caml/signals.h>
7937
7938 #include <guestfs.h>
7939
7940 #include \"guestfs_c.h\"
7941
7942 /* Copy a hashtable of string pairs into an assoc-list.  We return
7943  * the list in reverse order, but hashtables aren't supposed to be
7944  * ordered anyway.
7945  */
7946 static CAMLprim value
7947 copy_table (char * const * argv)
7948 {
7949   CAMLparam0 ();
7950   CAMLlocal5 (rv, pairv, kv, vv, cons);
7951   int i;
7952
7953   rv = Val_int (0);
7954   for (i = 0; argv[i] != NULL; i += 2) {
7955     kv = caml_copy_string (argv[i]);
7956     vv = caml_copy_string (argv[i+1]);
7957     pairv = caml_alloc (2, 0);
7958     Store_field (pairv, 0, kv);
7959     Store_field (pairv, 1, vv);
7960     cons = caml_alloc (2, 0);
7961     Store_field (cons, 1, rv);
7962     rv = cons;
7963     Store_field (cons, 0, pairv);
7964   }
7965
7966   CAMLreturn (rv);
7967 }
7968
7969 ";
7970
7971   (* Struct copy functions. *)
7972
7973   let emit_ocaml_copy_list_function typ =
7974     pr "static CAMLprim value\n";
7975     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7976     pr "{\n";
7977     pr "  CAMLparam0 ();\n";
7978     pr "  CAMLlocal2 (rv, v);\n";
7979     pr "  unsigned int i;\n";
7980     pr "\n";
7981     pr "  if (%ss->len == 0)\n" typ;
7982     pr "    CAMLreturn (Atom (0));\n";
7983     pr "  else {\n";
7984     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7985     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7986     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7987     pr "      caml_modify (&Field (rv, i), v);\n";
7988     pr "    }\n";
7989     pr "    CAMLreturn (rv);\n";
7990     pr "  }\n";
7991     pr "}\n";
7992     pr "\n";
7993   in
7994
7995   List.iter (
7996     fun (typ, cols) ->
7997       let has_optpercent_col =
7998         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7999
8000       pr "static CAMLprim value\n";
8001       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8002       pr "{\n";
8003       pr "  CAMLparam0 ();\n";
8004       if has_optpercent_col then
8005         pr "  CAMLlocal3 (rv, v, v2);\n"
8006       else
8007         pr "  CAMLlocal2 (rv, v);\n";
8008       pr "\n";
8009       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8010       iteri (
8011         fun i col ->
8012           (match col with
8013            | name, FString ->
8014                pr "  v = caml_copy_string (%s->%s);\n" typ name
8015            | name, FBuffer ->
8016                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8017                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8018                  typ name typ name
8019            | name, FUUID ->
8020                pr "  v = caml_alloc_string (32);\n";
8021                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8022            | name, (FBytes|FInt64|FUInt64) ->
8023                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8024            | name, (FInt32|FUInt32) ->
8025                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8026            | name, FOptPercent ->
8027                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8028                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8029                pr "    v = caml_alloc (1, 0);\n";
8030                pr "    Store_field (v, 0, v2);\n";
8031                pr "  } else /* None */\n";
8032                pr "    v = Val_int (0);\n";
8033            | name, FChar ->
8034                pr "  v = Val_int (%s->%s);\n" typ name
8035           );
8036           pr "  Store_field (rv, %d, v);\n" i
8037       ) cols;
8038       pr "  CAMLreturn (rv);\n";
8039       pr "}\n";
8040       pr "\n";
8041   ) structs;
8042
8043   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8044   List.iter (
8045     function
8046     | typ, (RStructListOnly | RStructAndList) ->
8047         (* generate the function for typ *)
8048         emit_ocaml_copy_list_function typ
8049     | typ, _ -> () (* empty *)
8050   ) (rstructs_used_by all_functions);
8051
8052   (* The wrappers. *)
8053   List.iter (
8054     fun (name, style, _, _, _, _, _) ->
8055       pr "/* Automatically generated wrapper for function\n";
8056       pr " * ";
8057       generate_ocaml_prototype name style;
8058       pr " */\n";
8059       pr "\n";
8060
8061       let params =
8062         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8063
8064       let needs_extra_vs =
8065         match fst style with RConstOptString _ -> true | _ -> false in
8066
8067       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8068       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8069       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8070       pr "\n";
8071
8072       pr "CAMLprim value\n";
8073       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8074       List.iter (pr ", value %s") (List.tl params);
8075       pr ")\n";
8076       pr "{\n";
8077
8078       (match params with
8079        | [p1; p2; p3; p4; p5] ->
8080            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8081        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8082            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8083            pr "  CAMLxparam%d (%s);\n"
8084              (List.length rest) (String.concat ", " rest)
8085        | ps ->
8086            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8087       );
8088       if not needs_extra_vs then
8089         pr "  CAMLlocal1 (rv);\n"
8090       else
8091         pr "  CAMLlocal3 (rv, v, v2);\n";
8092       pr "\n";
8093
8094       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8095       pr "  if (g == NULL)\n";
8096       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8097       pr "\n";
8098
8099       List.iter (
8100         function
8101         | Pathname n
8102         | Device n | Dev_or_Path n
8103         | String n
8104         | FileIn n
8105         | FileOut n ->
8106             pr "  const char *%s = String_val (%sv);\n" n n
8107         | OptString n ->
8108             pr "  const char *%s =\n" n;
8109             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8110               n n
8111         | StringList n | DeviceList n ->
8112             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8113         | Bool n ->
8114             pr "  int %s = Bool_val (%sv);\n" n n
8115         | Int n ->
8116             pr "  int %s = Int_val (%sv);\n" n n
8117         | Int64 n ->
8118             pr "  int64_t %s = Int64_val (%sv);\n" n n
8119       ) (snd style);
8120       let error_code =
8121         match fst style with
8122         | RErr -> pr "  int r;\n"; "-1"
8123         | RInt _ -> pr "  int r;\n"; "-1"
8124         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8125         | RBool _ -> pr "  int r;\n"; "-1"
8126         | RConstString _ | RConstOptString _ ->
8127             pr "  const char *r;\n"; "NULL"
8128         | RString _ -> pr "  char *r;\n"; "NULL"
8129         | RStringList _ ->
8130             pr "  int i;\n";
8131             pr "  char **r;\n";
8132             "NULL"
8133         | RStruct (_, typ) ->
8134             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8135         | RStructList (_, typ) ->
8136             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8137         | RHashtable _ ->
8138             pr "  int i;\n";
8139             pr "  char **r;\n";
8140             "NULL"
8141         | RBufferOut _ ->
8142             pr "  char *r;\n";
8143             pr "  size_t size;\n";
8144             "NULL" in
8145       pr "\n";
8146
8147       pr "  caml_enter_blocking_section ();\n";
8148       pr "  r = guestfs_%s " name;
8149       generate_c_call_args ~handle:"g" style;
8150       pr ";\n";
8151       pr "  caml_leave_blocking_section ();\n";
8152
8153       List.iter (
8154         function
8155         | StringList n | DeviceList n ->
8156             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8157         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8158         | Bool _ | Int _ | Int64 _
8159         | FileIn _ | FileOut _ -> ()
8160       ) (snd style);
8161
8162       pr "  if (r == %s)\n" error_code;
8163       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8164       pr "\n";
8165
8166       (match fst style with
8167        | RErr -> pr "  rv = Val_unit;\n"
8168        | RInt _ -> pr "  rv = Val_int (r);\n"
8169        | RInt64 _ ->
8170            pr "  rv = caml_copy_int64 (r);\n"
8171        | RBool _ -> pr "  rv = Val_bool (r);\n"
8172        | RConstString _ ->
8173            pr "  rv = caml_copy_string (r);\n"
8174        | RConstOptString _ ->
8175            pr "  if (r) { /* Some string */\n";
8176            pr "    v = caml_alloc (1, 0);\n";
8177            pr "    v2 = caml_copy_string (r);\n";
8178            pr "    Store_field (v, 0, v2);\n";
8179            pr "  } else /* None */\n";
8180            pr "    v = Val_int (0);\n";
8181        | RString _ ->
8182            pr "  rv = caml_copy_string (r);\n";
8183            pr "  free (r);\n"
8184        | RStringList _ ->
8185            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8186            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8187            pr "  free (r);\n"
8188        | RStruct (_, typ) ->
8189            pr "  rv = copy_%s (r);\n" typ;
8190            pr "  guestfs_free_%s (r);\n" typ;
8191        | RStructList (_, typ) ->
8192            pr "  rv = copy_%s_list (r);\n" typ;
8193            pr "  guestfs_free_%s_list (r);\n" typ;
8194        | RHashtable _ ->
8195            pr "  rv = copy_table (r);\n";
8196            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8197            pr "  free (r);\n";
8198        | RBufferOut _ ->
8199            pr "  rv = caml_alloc_string (size);\n";
8200            pr "  memcpy (String_val (rv), r, size);\n";
8201       );
8202
8203       pr "  CAMLreturn (rv);\n";
8204       pr "}\n";
8205       pr "\n";
8206
8207       if List.length params > 5 then (
8208         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8209         pr "CAMLprim value ";
8210         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8211         pr "CAMLprim value\n";
8212         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8213         pr "{\n";
8214         pr "  return ocaml_guestfs_%s (argv[0]" name;
8215         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8216         pr ");\n";
8217         pr "}\n";
8218         pr "\n"
8219       )
8220   ) all_functions_sorted
8221
8222 and generate_ocaml_structure_decls () =
8223   List.iter (
8224     fun (typ, cols) ->
8225       pr "type %s = {\n" typ;
8226       List.iter (
8227         function
8228         | name, FString -> pr "  %s : string;\n" name
8229         | name, FBuffer -> pr "  %s : string;\n" name
8230         | name, FUUID -> pr "  %s : string;\n" name
8231         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8232         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8233         | name, FChar -> pr "  %s : char;\n" name
8234         | name, FOptPercent -> pr "  %s : float option;\n" name
8235       ) cols;
8236       pr "}\n";
8237       pr "\n"
8238   ) structs
8239
8240 and generate_ocaml_prototype ?(is_external = false) name style =
8241   if is_external then pr "external " else pr "val ";
8242   pr "%s : t -> " name;
8243   List.iter (
8244     function
8245     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8246     | OptString _ -> pr "string option -> "
8247     | StringList _ | DeviceList _ -> pr "string array -> "
8248     | Bool _ -> pr "bool -> "
8249     | Int _ -> pr "int -> "
8250     | Int64 _ -> pr "int64 -> "
8251   ) (snd style);
8252   (match fst style with
8253    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8254    | RInt _ -> pr "int"
8255    | RInt64 _ -> pr "int64"
8256    | RBool _ -> pr "bool"
8257    | RConstString _ -> pr "string"
8258    | RConstOptString _ -> pr "string option"
8259    | RString _ | RBufferOut _ -> pr "string"
8260    | RStringList _ -> pr "string array"
8261    | RStruct (_, typ) -> pr "%s" typ
8262    | RStructList (_, typ) -> pr "%s array" typ
8263    | RHashtable _ -> pr "(string * string) list"
8264   );
8265   if is_external then (
8266     pr " = ";
8267     if List.length (snd style) + 1 > 5 then
8268       pr "\"ocaml_guestfs_%s_byte\" " name;
8269     pr "\"ocaml_guestfs_%s\"" name
8270   );
8271   pr "\n"
8272
8273 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8274 and generate_perl_xs () =
8275   generate_header CStyle LGPLv2plus;
8276
8277   pr "\
8278 #include \"EXTERN.h\"
8279 #include \"perl.h\"
8280 #include \"XSUB.h\"
8281
8282 #include <guestfs.h>
8283
8284 #ifndef PRId64
8285 #define PRId64 \"lld\"
8286 #endif
8287
8288 static SV *
8289 my_newSVll(long long val) {
8290 #ifdef USE_64_BIT_ALL
8291   return newSViv(val);
8292 #else
8293   char buf[100];
8294   int len;
8295   len = snprintf(buf, 100, \"%%\" PRId64, val);
8296   return newSVpv(buf, len);
8297 #endif
8298 }
8299
8300 #ifndef PRIu64
8301 #define PRIu64 \"llu\"
8302 #endif
8303
8304 static SV *
8305 my_newSVull(unsigned long long val) {
8306 #ifdef USE_64_BIT_ALL
8307   return newSVuv(val);
8308 #else
8309   char buf[100];
8310   int len;
8311   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8312   return newSVpv(buf, len);
8313 #endif
8314 }
8315
8316 /* http://www.perlmonks.org/?node_id=680842 */
8317 static char **
8318 XS_unpack_charPtrPtr (SV *arg) {
8319   char **ret;
8320   AV *av;
8321   I32 i;
8322
8323   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8324     croak (\"array reference expected\");
8325
8326   av = (AV *)SvRV (arg);
8327   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8328   if (!ret)
8329     croak (\"malloc failed\");
8330
8331   for (i = 0; i <= av_len (av); i++) {
8332     SV **elem = av_fetch (av, i, 0);
8333
8334     if (!elem || !*elem)
8335       croak (\"missing element in list\");
8336
8337     ret[i] = SvPV_nolen (*elem);
8338   }
8339
8340   ret[i] = NULL;
8341
8342   return ret;
8343 }
8344
8345 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8346
8347 PROTOTYPES: ENABLE
8348
8349 guestfs_h *
8350 _create ()
8351    CODE:
8352       RETVAL = guestfs_create ();
8353       if (!RETVAL)
8354         croak (\"could not create guestfs handle\");
8355       guestfs_set_error_handler (RETVAL, NULL, NULL);
8356  OUTPUT:
8357       RETVAL
8358
8359 void
8360 DESTROY (g)
8361       guestfs_h *g;
8362  PPCODE:
8363       guestfs_close (g);
8364
8365 ";
8366
8367   List.iter (
8368     fun (name, style, _, _, _, _, _) ->
8369       (match fst style with
8370        | RErr -> pr "void\n"
8371        | RInt _ -> pr "SV *\n"
8372        | RInt64 _ -> pr "SV *\n"
8373        | RBool _ -> pr "SV *\n"
8374        | RConstString _ -> pr "SV *\n"
8375        | RConstOptString _ -> pr "SV *\n"
8376        | RString _ -> pr "SV *\n"
8377        | RBufferOut _ -> pr "SV *\n"
8378        | RStringList _
8379        | RStruct _ | RStructList _
8380        | RHashtable _ ->
8381            pr "void\n" (* all lists returned implictly on the stack *)
8382       );
8383       (* Call and arguments. *)
8384       pr "%s " name;
8385       generate_c_call_args ~handle:"g" ~decl:true style;
8386       pr "\n";
8387       pr "      guestfs_h *g;\n";
8388       iteri (
8389         fun i ->
8390           function
8391           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8392               pr "      char *%s;\n" n
8393           | OptString n ->
8394               (* http://www.perlmonks.org/?node_id=554277
8395                * Note that the implicit handle argument means we have
8396                * to add 1 to the ST(x) operator.
8397                *)
8398               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8399           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8400           | Bool n -> pr "      int %s;\n" n
8401           | Int n -> pr "      int %s;\n" n
8402           | Int64 n -> pr "      int64_t %s;\n" n
8403       ) (snd style);
8404
8405       let do_cleanups () =
8406         List.iter (
8407           function
8408           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8409           | Bool _ | Int _ | Int64 _
8410           | FileIn _ | FileOut _ -> ()
8411           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8412         ) (snd style)
8413       in
8414
8415       (* Code. *)
8416       (match fst style with
8417        | RErr ->
8418            pr "PREINIT:\n";
8419            pr "      int r;\n";
8420            pr " PPCODE:\n";
8421            pr "      r = guestfs_%s " name;
8422            generate_c_call_args ~handle:"g" style;
8423            pr ";\n";
8424            do_cleanups ();
8425            pr "      if (r == -1)\n";
8426            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8427        | RInt n
8428        | RBool n ->
8429            pr "PREINIT:\n";
8430            pr "      int %s;\n" n;
8431            pr "   CODE:\n";
8432            pr "      %s = guestfs_%s " n name;
8433            generate_c_call_args ~handle:"g" style;
8434            pr ";\n";
8435            do_cleanups ();
8436            pr "      if (%s == -1)\n" n;
8437            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8438            pr "      RETVAL = newSViv (%s);\n" n;
8439            pr " OUTPUT:\n";
8440            pr "      RETVAL\n"
8441        | RInt64 n ->
8442            pr "PREINIT:\n";
8443            pr "      int64_t %s;\n" n;
8444            pr "   CODE:\n";
8445            pr "      %s = guestfs_%s " n name;
8446            generate_c_call_args ~handle:"g" style;
8447            pr ";\n";
8448            do_cleanups ();
8449            pr "      if (%s == -1)\n" n;
8450            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8451            pr "      RETVAL = my_newSVll (%s);\n" n;
8452            pr " OUTPUT:\n";
8453            pr "      RETVAL\n"
8454        | RConstString n ->
8455            pr "PREINIT:\n";
8456            pr "      const char *%s;\n" n;
8457            pr "   CODE:\n";
8458            pr "      %s = guestfs_%s " n name;
8459            generate_c_call_args ~handle:"g" style;
8460            pr ";\n";
8461            do_cleanups ();
8462            pr "      if (%s == NULL)\n" n;
8463            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8464            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8465            pr " OUTPUT:\n";
8466            pr "      RETVAL\n"
8467        | RConstOptString n ->
8468            pr "PREINIT:\n";
8469            pr "      const char *%s;\n" n;
8470            pr "   CODE:\n";
8471            pr "      %s = guestfs_%s " n name;
8472            generate_c_call_args ~handle:"g" style;
8473            pr ";\n";
8474            do_cleanups ();
8475            pr "      if (%s == NULL)\n" n;
8476            pr "        RETVAL = &PL_sv_undef;\n";
8477            pr "      else\n";
8478            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8479            pr " OUTPUT:\n";
8480            pr "      RETVAL\n"
8481        | RString n ->
8482            pr "PREINIT:\n";
8483            pr "      char *%s;\n" n;
8484            pr "   CODE:\n";
8485            pr "      %s = guestfs_%s " n name;
8486            generate_c_call_args ~handle:"g" style;
8487            pr ";\n";
8488            do_cleanups ();
8489            pr "      if (%s == NULL)\n" n;
8490            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8491            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8492            pr "      free (%s);\n" n;
8493            pr " OUTPUT:\n";
8494            pr "      RETVAL\n"
8495        | RStringList n | RHashtable n ->
8496            pr "PREINIT:\n";
8497            pr "      char **%s;\n" n;
8498            pr "      int i, n;\n";
8499            pr " PPCODE:\n";
8500            pr "      %s = guestfs_%s " n name;
8501            generate_c_call_args ~handle:"g" style;
8502            pr ";\n";
8503            do_cleanups ();
8504            pr "      if (%s == NULL)\n" n;
8505            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8506            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8507            pr "      EXTEND (SP, n);\n";
8508            pr "      for (i = 0; i < n; ++i) {\n";
8509            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8510            pr "        free (%s[i]);\n" n;
8511            pr "      }\n";
8512            pr "      free (%s);\n" n;
8513        | RStruct (n, typ) ->
8514            let cols = cols_of_struct typ in
8515            generate_perl_struct_code typ cols name style n do_cleanups
8516        | RStructList (n, typ) ->
8517            let cols = cols_of_struct typ in
8518            generate_perl_struct_list_code typ cols name style n do_cleanups
8519        | RBufferOut n ->
8520            pr "PREINIT:\n";
8521            pr "      char *%s;\n" n;
8522            pr "      size_t size;\n";
8523            pr "   CODE:\n";
8524            pr "      %s = guestfs_%s " n name;
8525            generate_c_call_args ~handle:"g" style;
8526            pr ";\n";
8527            do_cleanups ();
8528            pr "      if (%s == NULL)\n" n;
8529            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8530            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8531            pr "      free (%s);\n" n;
8532            pr " OUTPUT:\n";
8533            pr "      RETVAL\n"
8534       );
8535
8536       pr "\n"
8537   ) all_functions
8538
8539 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8540   pr "PREINIT:\n";
8541   pr "      struct guestfs_%s_list *%s;\n" typ n;
8542   pr "      int i;\n";
8543   pr "      HV *hv;\n";
8544   pr " PPCODE:\n";
8545   pr "      %s = guestfs_%s " n name;
8546   generate_c_call_args ~handle:"g" style;
8547   pr ";\n";
8548   do_cleanups ();
8549   pr "      if (%s == NULL)\n" n;
8550   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8551   pr "      EXTEND (SP, %s->len);\n" n;
8552   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8553   pr "        hv = newHV ();\n";
8554   List.iter (
8555     function
8556     | name, FString ->
8557         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8558           name (String.length name) n name
8559     | name, FUUID ->
8560         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8561           name (String.length name) n name
8562     | name, FBuffer ->
8563         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8564           name (String.length name) n name n name
8565     | name, (FBytes|FUInt64) ->
8566         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8567           name (String.length name) n name
8568     | name, FInt64 ->
8569         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8570           name (String.length name) n name
8571     | name, (FInt32|FUInt32) ->
8572         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8573           name (String.length name) n name
8574     | name, FChar ->
8575         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8576           name (String.length name) n name
8577     | name, FOptPercent ->
8578         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8579           name (String.length name) n name
8580   ) cols;
8581   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8582   pr "      }\n";
8583   pr "      guestfs_free_%s_list (%s);\n" typ n
8584
8585 and generate_perl_struct_code typ cols name style n do_cleanups =
8586   pr "PREINIT:\n";
8587   pr "      struct guestfs_%s *%s;\n" typ n;
8588   pr " PPCODE:\n";
8589   pr "      %s = guestfs_%s " n name;
8590   generate_c_call_args ~handle:"g" style;
8591   pr ";\n";
8592   do_cleanups ();
8593   pr "      if (%s == NULL)\n" n;
8594   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8595   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8596   List.iter (
8597     fun ((name, _) as col) ->
8598       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8599
8600       match col with
8601       | name, FString ->
8602           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8603             n name
8604       | name, FBuffer ->
8605           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8606             n name n name
8607       | name, FUUID ->
8608           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8609             n name
8610       | name, (FBytes|FUInt64) ->
8611           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8612             n name
8613       | name, FInt64 ->
8614           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8615             n name
8616       | name, (FInt32|FUInt32) ->
8617           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8618             n name
8619       | name, FChar ->
8620           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8621             n name
8622       | name, FOptPercent ->
8623           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8624             n name
8625   ) cols;
8626   pr "      free (%s);\n" n
8627
8628 (* Generate Sys/Guestfs.pm. *)
8629 and generate_perl_pm () =
8630   generate_header HashStyle LGPLv2plus;
8631
8632   pr "\
8633 =pod
8634
8635 =head1 NAME
8636
8637 Sys::Guestfs - Perl bindings for libguestfs
8638
8639 =head1 SYNOPSIS
8640
8641  use Sys::Guestfs;
8642
8643  my $h = Sys::Guestfs->new ();
8644  $h->add_drive ('guest.img');
8645  $h->launch ();
8646  $h->mount ('/dev/sda1', '/');
8647  $h->touch ('/hello');
8648  $h->sync ();
8649
8650 =head1 DESCRIPTION
8651
8652 The C<Sys::Guestfs> module provides a Perl XS binding to the
8653 libguestfs API for examining and modifying virtual machine
8654 disk images.
8655
8656 Amongst the things this is good for: making batch configuration
8657 changes to guests, getting disk used/free statistics (see also:
8658 virt-df), migrating between virtualization systems (see also:
8659 virt-p2v), performing partial backups, performing partial guest
8660 clones, cloning guests and changing registry/UUID/hostname info, and
8661 much else besides.
8662
8663 Libguestfs uses Linux kernel and qemu code, and can access any type of
8664 guest filesystem that Linux and qemu can, including but not limited
8665 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8666 schemes, qcow, qcow2, vmdk.
8667
8668 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8669 LVs, what filesystem is in each LV, etc.).  It can also run commands
8670 in the context of the guest.  Also you can access filesystems over
8671 FUSE.
8672
8673 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8674 functions for using libguestfs from Perl, including integration
8675 with libvirt.
8676
8677 =head1 ERRORS
8678
8679 All errors turn into calls to C<croak> (see L<Carp(3)>).
8680
8681 =head1 METHODS
8682
8683 =over 4
8684
8685 =cut
8686
8687 package Sys::Guestfs;
8688
8689 use strict;
8690 use warnings;
8691
8692 require XSLoader;
8693 XSLoader::load ('Sys::Guestfs');
8694
8695 =item $h = Sys::Guestfs->new ();
8696
8697 Create a new guestfs handle.
8698
8699 =cut
8700
8701 sub new {
8702   my $proto = shift;
8703   my $class = ref ($proto) || $proto;
8704
8705   my $self = Sys::Guestfs::_create ();
8706   bless $self, $class;
8707   return $self;
8708 }
8709
8710 ";
8711
8712   (* Actions.  We only need to print documentation for these as
8713    * they are pulled in from the XS code automatically.
8714    *)
8715   List.iter (
8716     fun (name, style, _, flags, _, _, longdesc) ->
8717       if not (List.mem NotInDocs flags) then (
8718         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8719         pr "=item ";
8720         generate_perl_prototype name style;
8721         pr "\n\n";
8722         pr "%s\n\n" longdesc;
8723         if List.mem ProtocolLimitWarning flags then
8724           pr "%s\n\n" protocol_limit_warning;
8725         if List.mem DangerWillRobinson flags then
8726           pr "%s\n\n" danger_will_robinson;
8727         match deprecation_notice flags with
8728         | None -> ()
8729         | Some txt -> pr "%s\n\n" txt
8730       )
8731   ) all_functions_sorted;
8732
8733   (* End of file. *)
8734   pr "\
8735 =cut
8736
8737 1;
8738
8739 =back
8740
8741 =head1 COPYRIGHT
8742
8743 Copyright (C) %s Red Hat Inc.
8744
8745 =head1 LICENSE
8746
8747 Please see the file COPYING.LIB for the full license.
8748
8749 =head1 SEE ALSO
8750
8751 L<guestfs(3)>,
8752 L<guestfish(1)>,
8753 L<http://libguestfs.org>,
8754 L<Sys::Guestfs::Lib(3)>.
8755
8756 =cut
8757 " copyright_years
8758
8759 and generate_perl_prototype name style =
8760   (match fst style with
8761    | RErr -> ()
8762    | RBool n
8763    | RInt n
8764    | RInt64 n
8765    | RConstString n
8766    | RConstOptString n
8767    | RString n
8768    | RBufferOut n -> pr "$%s = " n
8769    | RStruct (n,_)
8770    | RHashtable n -> pr "%%%s = " n
8771    | RStringList n
8772    | RStructList (n,_) -> pr "@%s = " n
8773   );
8774   pr "$h->%s (" name;
8775   let comma = ref false in
8776   List.iter (
8777     fun arg ->
8778       if !comma then pr ", ";
8779       comma := true;
8780       match arg with
8781       | Pathname n | Device n | Dev_or_Path n | String n
8782       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8783           pr "$%s" n
8784       | StringList n | DeviceList n ->
8785           pr "\\@%s" n
8786   ) (snd style);
8787   pr ");"
8788
8789 (* Generate Python C module. *)
8790 and generate_python_c () =
8791   generate_header CStyle LGPLv2plus;
8792
8793   pr "\
8794 #include <Python.h>
8795
8796 #include <stdio.h>
8797 #include <stdlib.h>
8798 #include <assert.h>
8799
8800 #include \"guestfs.h\"
8801
8802 typedef struct {
8803   PyObject_HEAD
8804   guestfs_h *g;
8805 } Pyguestfs_Object;
8806
8807 static guestfs_h *
8808 get_handle (PyObject *obj)
8809 {
8810   assert (obj);
8811   assert (obj != Py_None);
8812   return ((Pyguestfs_Object *) obj)->g;
8813 }
8814
8815 static PyObject *
8816 put_handle (guestfs_h *g)
8817 {
8818   assert (g);
8819   return
8820     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8821 }
8822
8823 /* This list should be freed (but not the strings) after use. */
8824 static char **
8825 get_string_list (PyObject *obj)
8826 {
8827   int i, len;
8828   char **r;
8829
8830   assert (obj);
8831
8832   if (!PyList_Check (obj)) {
8833     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8834     return NULL;
8835   }
8836
8837   len = PyList_Size (obj);
8838   r = malloc (sizeof (char *) * (len+1));
8839   if (r == NULL) {
8840     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8841     return NULL;
8842   }
8843
8844   for (i = 0; i < len; ++i)
8845     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8846   r[len] = NULL;
8847
8848   return r;
8849 }
8850
8851 static PyObject *
8852 put_string_list (char * const * const argv)
8853 {
8854   PyObject *list;
8855   int argc, i;
8856
8857   for (argc = 0; argv[argc] != NULL; ++argc)
8858     ;
8859
8860   list = PyList_New (argc);
8861   for (i = 0; i < argc; ++i)
8862     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8863
8864   return list;
8865 }
8866
8867 static PyObject *
8868 put_table (char * const * const argv)
8869 {
8870   PyObject *list, *item;
8871   int argc, i;
8872
8873   for (argc = 0; argv[argc] != NULL; ++argc)
8874     ;
8875
8876   list = PyList_New (argc >> 1);
8877   for (i = 0; i < argc; i += 2) {
8878     item = PyTuple_New (2);
8879     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8880     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8881     PyList_SetItem (list, i >> 1, item);
8882   }
8883
8884   return list;
8885 }
8886
8887 static void
8888 free_strings (char **argv)
8889 {
8890   int argc;
8891
8892   for (argc = 0; argv[argc] != NULL; ++argc)
8893     free (argv[argc]);
8894   free (argv);
8895 }
8896
8897 static PyObject *
8898 py_guestfs_create (PyObject *self, PyObject *args)
8899 {
8900   guestfs_h *g;
8901
8902   g = guestfs_create ();
8903   if (g == NULL) {
8904     PyErr_SetString (PyExc_RuntimeError,
8905                      \"guestfs.create: failed to allocate handle\");
8906     return NULL;
8907   }
8908   guestfs_set_error_handler (g, NULL, NULL);
8909   return put_handle (g);
8910 }
8911
8912 static PyObject *
8913 py_guestfs_close (PyObject *self, PyObject *args)
8914 {
8915   PyObject *py_g;
8916   guestfs_h *g;
8917
8918   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8919     return NULL;
8920   g = get_handle (py_g);
8921
8922   guestfs_close (g);
8923
8924   Py_INCREF (Py_None);
8925   return Py_None;
8926 }
8927
8928 ";
8929
8930   let emit_put_list_function typ =
8931     pr "static PyObject *\n";
8932     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8933     pr "{\n";
8934     pr "  PyObject *list;\n";
8935     pr "  int i;\n";
8936     pr "\n";
8937     pr "  list = PyList_New (%ss->len);\n" typ;
8938     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8939     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8940     pr "  return list;\n";
8941     pr "};\n";
8942     pr "\n"
8943   in
8944
8945   (* Structures, turned into Python dictionaries. *)
8946   List.iter (
8947     fun (typ, cols) ->
8948       pr "static PyObject *\n";
8949       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8950       pr "{\n";
8951       pr "  PyObject *dict;\n";
8952       pr "\n";
8953       pr "  dict = PyDict_New ();\n";
8954       List.iter (
8955         function
8956         | name, FString ->
8957             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8958             pr "                        PyString_FromString (%s->%s));\n"
8959               typ name
8960         | name, FBuffer ->
8961             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8962             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8963               typ name typ name
8964         | name, FUUID ->
8965             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8966             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8967               typ name
8968         | name, (FBytes|FUInt64) ->
8969             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8970             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8971               typ name
8972         | name, FInt64 ->
8973             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8974             pr "                        PyLong_FromLongLong (%s->%s));\n"
8975               typ name
8976         | name, FUInt32 ->
8977             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8978             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8979               typ name
8980         | name, FInt32 ->
8981             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8982             pr "                        PyLong_FromLong (%s->%s));\n"
8983               typ name
8984         | name, FOptPercent ->
8985             pr "  if (%s->%s >= 0)\n" typ name;
8986             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8987             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8988               typ name;
8989             pr "  else {\n";
8990             pr "    Py_INCREF (Py_None);\n";
8991             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8992             pr "  }\n"
8993         | name, FChar ->
8994             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8995             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8996       ) cols;
8997       pr "  return dict;\n";
8998       pr "};\n";
8999       pr "\n";
9000
9001   ) structs;
9002
9003   (* Emit a put_TYPE_list function definition only if that function is used. *)
9004   List.iter (
9005     function
9006     | typ, (RStructListOnly | RStructAndList) ->
9007         (* generate the function for typ *)
9008         emit_put_list_function typ
9009     | typ, _ -> () (* empty *)
9010   ) (rstructs_used_by all_functions);
9011
9012   (* Python wrapper functions. *)
9013   List.iter (
9014     fun (name, style, _, _, _, _, _) ->
9015       pr "static PyObject *\n";
9016       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9017       pr "{\n";
9018
9019       pr "  PyObject *py_g;\n";
9020       pr "  guestfs_h *g;\n";
9021       pr "  PyObject *py_r;\n";
9022
9023       let error_code =
9024         match fst style with
9025         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9026         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9027         | RConstString _ | RConstOptString _ ->
9028             pr "  const char *r;\n"; "NULL"
9029         | RString _ -> pr "  char *r;\n"; "NULL"
9030         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9031         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9032         | RStructList (_, typ) ->
9033             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9034         | RBufferOut _ ->
9035             pr "  char *r;\n";
9036             pr "  size_t size;\n";
9037             "NULL" in
9038
9039       List.iter (
9040         function
9041         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9042             pr "  const char *%s;\n" n
9043         | OptString n -> pr "  const char *%s;\n" n
9044         | StringList n | DeviceList n ->
9045             pr "  PyObject *py_%s;\n" n;
9046             pr "  char **%s;\n" n
9047         | Bool n -> pr "  int %s;\n" n
9048         | Int n -> pr "  int %s;\n" n
9049         | Int64 n -> pr "  long long %s;\n" n
9050       ) (snd style);
9051
9052       pr "\n";
9053
9054       (* Convert the parameters. *)
9055       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9056       List.iter (
9057         function
9058         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9059         | OptString _ -> pr "z"
9060         | StringList _ | DeviceList _ -> pr "O"
9061         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9062         | Int _ -> pr "i"
9063         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9064                              * emulate C's int/long/long long in Python?
9065                              *)
9066       ) (snd style);
9067       pr ":guestfs_%s\",\n" name;
9068       pr "                         &py_g";
9069       List.iter (
9070         function
9071         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9072         | OptString n -> pr ", &%s" n
9073         | StringList n | DeviceList n -> pr ", &py_%s" n
9074         | Bool n -> pr ", &%s" n
9075         | Int n -> pr ", &%s" n
9076         | Int64 n -> pr ", &%s" n
9077       ) (snd style);
9078
9079       pr "))\n";
9080       pr "    return NULL;\n";
9081
9082       pr "  g = get_handle (py_g);\n";
9083       List.iter (
9084         function
9085         | Pathname _ | Device _ | Dev_or_Path _ | String _
9086         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9087         | StringList n | DeviceList n ->
9088             pr "  %s = get_string_list (py_%s);\n" n n;
9089             pr "  if (!%s) return NULL;\n" n
9090       ) (snd style);
9091
9092       pr "\n";
9093
9094       pr "  r = guestfs_%s " name;
9095       generate_c_call_args ~handle:"g" style;
9096       pr ";\n";
9097
9098       List.iter (
9099         function
9100         | Pathname _ | Device _ | Dev_or_Path _ | String _
9101         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9102         | StringList n | DeviceList n ->
9103             pr "  free (%s);\n" n
9104       ) (snd style);
9105
9106       pr "  if (r == %s) {\n" error_code;
9107       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9108       pr "    return NULL;\n";
9109       pr "  }\n";
9110       pr "\n";
9111
9112       (match fst style with
9113        | RErr ->
9114            pr "  Py_INCREF (Py_None);\n";
9115            pr "  py_r = Py_None;\n"
9116        | RInt _
9117        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9118        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9119        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9120        | RConstOptString _ ->
9121            pr "  if (r)\n";
9122            pr "    py_r = PyString_FromString (r);\n";
9123            pr "  else {\n";
9124            pr "    Py_INCREF (Py_None);\n";
9125            pr "    py_r = Py_None;\n";
9126            pr "  }\n"
9127        | RString _ ->
9128            pr "  py_r = PyString_FromString (r);\n";
9129            pr "  free (r);\n"
9130        | RStringList _ ->
9131            pr "  py_r = put_string_list (r);\n";
9132            pr "  free_strings (r);\n"
9133        | RStruct (_, typ) ->
9134            pr "  py_r = put_%s (r);\n" typ;
9135            pr "  guestfs_free_%s (r);\n" typ
9136        | RStructList (_, typ) ->
9137            pr "  py_r = put_%s_list (r);\n" typ;
9138            pr "  guestfs_free_%s_list (r);\n" typ
9139        | RHashtable n ->
9140            pr "  py_r = put_table (r);\n";
9141            pr "  free_strings (r);\n"
9142        | RBufferOut _ ->
9143            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9144            pr "  free (r);\n"
9145       );
9146
9147       pr "  return py_r;\n";
9148       pr "}\n";
9149       pr "\n"
9150   ) all_functions;
9151
9152   (* Table of functions. *)
9153   pr "static PyMethodDef methods[] = {\n";
9154   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9155   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9156   List.iter (
9157     fun (name, _, _, _, _, _, _) ->
9158       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9159         name name
9160   ) all_functions;
9161   pr "  { NULL, NULL, 0, NULL }\n";
9162   pr "};\n";
9163   pr "\n";
9164
9165   (* Init function. *)
9166   pr "\
9167 void
9168 initlibguestfsmod (void)
9169 {
9170   static int initialized = 0;
9171
9172   if (initialized) return;
9173   Py_InitModule ((char *) \"libguestfsmod\", methods);
9174   initialized = 1;
9175 }
9176 "
9177
9178 (* Generate Python module. *)
9179 and generate_python_py () =
9180   generate_header HashStyle LGPLv2plus;
9181
9182   pr "\
9183 u\"\"\"Python bindings for libguestfs
9184
9185 import guestfs
9186 g = guestfs.GuestFS ()
9187 g.add_drive (\"guest.img\")
9188 g.launch ()
9189 parts = g.list_partitions ()
9190
9191 The guestfs module provides a Python binding to the libguestfs API
9192 for examining and modifying virtual machine disk images.
9193
9194 Amongst the things this is good for: making batch configuration
9195 changes to guests, getting disk used/free statistics (see also:
9196 virt-df), migrating between virtualization systems (see also:
9197 virt-p2v), performing partial backups, performing partial guest
9198 clones, cloning guests and changing registry/UUID/hostname info, and
9199 much else besides.
9200
9201 Libguestfs uses Linux kernel and qemu code, and can access any type of
9202 guest filesystem that Linux and qemu can, including but not limited
9203 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9204 schemes, qcow, qcow2, vmdk.
9205
9206 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9207 LVs, what filesystem is in each LV, etc.).  It can also run commands
9208 in the context of the guest.  Also you can access filesystems over
9209 FUSE.
9210
9211 Errors which happen while using the API are turned into Python
9212 RuntimeError exceptions.
9213
9214 To create a guestfs handle you usually have to perform the following
9215 sequence of calls:
9216
9217 # Create the handle, call add_drive at least once, and possibly
9218 # several times if the guest has multiple block devices:
9219 g = guestfs.GuestFS ()
9220 g.add_drive (\"guest.img\")
9221
9222 # Launch the qemu subprocess and wait for it to become ready:
9223 g.launch ()
9224
9225 # Now you can issue commands, for example:
9226 logvols = g.lvs ()
9227
9228 \"\"\"
9229
9230 import libguestfsmod
9231
9232 class GuestFS:
9233     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9234
9235     def __init__ (self):
9236         \"\"\"Create a new libguestfs handle.\"\"\"
9237         self._o = libguestfsmod.create ()
9238
9239     def __del__ (self):
9240         libguestfsmod.close (self._o)
9241
9242 ";
9243
9244   List.iter (
9245     fun (name, style, _, flags, _, _, longdesc) ->
9246       pr "    def %s " name;
9247       generate_py_call_args ~handle:"self" (snd style);
9248       pr ":\n";
9249
9250       if not (List.mem NotInDocs flags) then (
9251         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9252         let doc =
9253           match fst style with
9254           | RErr | RInt _ | RInt64 _ | RBool _
9255           | RConstOptString _ | RConstString _
9256           | RString _ | RBufferOut _ -> doc
9257           | RStringList _ ->
9258               doc ^ "\n\nThis function returns a list of strings."
9259           | RStruct (_, typ) ->
9260               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9261           | RStructList (_, typ) ->
9262               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9263           | RHashtable _ ->
9264               doc ^ "\n\nThis function returns a dictionary." in
9265         let doc =
9266           if List.mem ProtocolLimitWarning flags then
9267             doc ^ "\n\n" ^ protocol_limit_warning
9268           else doc in
9269         let doc =
9270           if List.mem DangerWillRobinson flags then
9271             doc ^ "\n\n" ^ danger_will_robinson
9272           else doc in
9273         let doc =
9274           match deprecation_notice flags with
9275           | None -> doc
9276           | Some txt -> doc ^ "\n\n" ^ txt in
9277         let doc = pod2text ~width:60 name doc in
9278         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9279         let doc = String.concat "\n        " doc in
9280         pr "        u\"\"\"%s\"\"\"\n" doc;
9281       );
9282       pr "        return libguestfsmod.%s " name;
9283       generate_py_call_args ~handle:"self._o" (snd style);
9284       pr "\n";
9285       pr "\n";
9286   ) all_functions
9287
9288 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9289 and generate_py_call_args ~handle args =
9290   pr "(%s" handle;
9291   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9292   pr ")"
9293
9294 (* Useful if you need the longdesc POD text as plain text.  Returns a
9295  * list of lines.
9296  *
9297  * Because this is very slow (the slowest part of autogeneration),
9298  * we memoize the results.
9299  *)
9300 and pod2text ~width name longdesc =
9301   let key = width, name, longdesc in
9302   try Hashtbl.find pod2text_memo key
9303   with Not_found ->
9304     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9305     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9306     close_out chan;
9307     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9308     let chan = open_process_in cmd in
9309     let lines = ref [] in
9310     let rec loop i =
9311       let line = input_line chan in
9312       if i = 1 then             (* discard the first line of output *)
9313         loop (i+1)
9314       else (
9315         let line = triml line in
9316         lines := line :: !lines;
9317         loop (i+1)
9318       ) in
9319     let lines = try loop 1 with End_of_file -> List.rev !lines in
9320     unlink filename;
9321     (match close_process_in chan with
9322      | WEXITED 0 -> ()
9323      | WEXITED i ->
9324          failwithf "pod2text: process exited with non-zero status (%d)" i
9325      | WSIGNALED i | WSTOPPED i ->
9326          failwithf "pod2text: process signalled or stopped by signal %d" i
9327     );
9328     Hashtbl.add pod2text_memo key lines;
9329     pod2text_memo_updated ();
9330     lines
9331
9332 (* Generate ruby bindings. *)
9333 and generate_ruby_c () =
9334   generate_header CStyle LGPLv2plus;
9335
9336   pr "\
9337 #include <stdio.h>
9338 #include <stdlib.h>
9339
9340 #include <ruby.h>
9341
9342 #include \"guestfs.h\"
9343
9344 #include \"extconf.h\"
9345
9346 /* For Ruby < 1.9 */
9347 #ifndef RARRAY_LEN
9348 #define RARRAY_LEN(r) (RARRAY((r))->len)
9349 #endif
9350
9351 static VALUE m_guestfs;                 /* guestfs module */
9352 static VALUE c_guestfs;                 /* guestfs_h handle */
9353 static VALUE e_Error;                   /* used for all errors */
9354
9355 static void ruby_guestfs_free (void *p)
9356 {
9357   if (!p) return;
9358   guestfs_close ((guestfs_h *) p);
9359 }
9360
9361 static VALUE ruby_guestfs_create (VALUE m)
9362 {
9363   guestfs_h *g;
9364
9365   g = guestfs_create ();
9366   if (!g)
9367     rb_raise (e_Error, \"failed to create guestfs handle\");
9368
9369   /* Don't print error messages to stderr by default. */
9370   guestfs_set_error_handler (g, NULL, NULL);
9371
9372   /* Wrap it, and make sure the close function is called when the
9373    * handle goes away.
9374    */
9375   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9376 }
9377
9378 static VALUE ruby_guestfs_close (VALUE gv)
9379 {
9380   guestfs_h *g;
9381   Data_Get_Struct (gv, guestfs_h, g);
9382
9383   ruby_guestfs_free (g);
9384   DATA_PTR (gv) = NULL;
9385
9386   return Qnil;
9387 }
9388
9389 ";
9390
9391   List.iter (
9392     fun (name, style, _, _, _, _, _) ->
9393       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9394       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9395       pr ")\n";
9396       pr "{\n";
9397       pr "  guestfs_h *g;\n";
9398       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9399       pr "  if (!g)\n";
9400       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9401         name;
9402       pr "\n";
9403
9404       List.iter (
9405         function
9406         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9407             pr "  Check_Type (%sv, T_STRING);\n" n;
9408             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9409             pr "  if (!%s)\n" n;
9410             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9411             pr "              \"%s\", \"%s\");\n" n name
9412         | OptString n ->
9413             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9414         | StringList n | DeviceList n ->
9415             pr "  char **%s;\n" n;
9416             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9417             pr "  {\n";
9418             pr "    int i, len;\n";
9419             pr "    len = RARRAY_LEN (%sv);\n" n;
9420             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9421               n;
9422             pr "    for (i = 0; i < len; ++i) {\n";
9423             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9424             pr "      %s[i] = StringValueCStr (v);\n" n;
9425             pr "    }\n";
9426             pr "    %s[len] = NULL;\n" n;
9427             pr "  }\n";
9428         | Bool n ->
9429             pr "  int %s = RTEST (%sv);\n" n n
9430         | Int n ->
9431             pr "  int %s = NUM2INT (%sv);\n" n n
9432         | Int64 n ->
9433             pr "  long long %s = NUM2LL (%sv);\n" n n
9434       ) (snd style);
9435       pr "\n";
9436
9437       let error_code =
9438         match fst style with
9439         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9440         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9441         | RConstString _ | RConstOptString _ ->
9442             pr "  const char *r;\n"; "NULL"
9443         | RString _ -> pr "  char *r;\n"; "NULL"
9444         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9445         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9446         | RStructList (_, typ) ->
9447             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9448         | RBufferOut _ ->
9449             pr "  char *r;\n";
9450             pr "  size_t size;\n";
9451             "NULL" in
9452       pr "\n";
9453
9454       pr "  r = guestfs_%s " name;
9455       generate_c_call_args ~handle:"g" style;
9456       pr ";\n";
9457
9458       List.iter (
9459         function
9460         | Pathname _ | Device _ | Dev_or_Path _ | String _
9461         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9462         | StringList n | DeviceList n ->
9463             pr "  free (%s);\n" n
9464       ) (snd style);
9465
9466       pr "  if (r == %s)\n" error_code;
9467       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9468       pr "\n";
9469
9470       (match fst style with
9471        | RErr ->
9472            pr "  return Qnil;\n"
9473        | RInt _ | RBool _ ->
9474            pr "  return INT2NUM (r);\n"
9475        | RInt64 _ ->
9476            pr "  return ULL2NUM (r);\n"
9477        | RConstString _ ->
9478            pr "  return rb_str_new2 (r);\n";
9479        | RConstOptString _ ->
9480            pr "  if (r)\n";
9481            pr "    return rb_str_new2 (r);\n";
9482            pr "  else\n";
9483            pr "    return Qnil;\n";
9484        | RString _ ->
9485            pr "  VALUE rv = rb_str_new2 (r);\n";
9486            pr "  free (r);\n";
9487            pr "  return rv;\n";
9488        | RStringList _ ->
9489            pr "  int i, len = 0;\n";
9490            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9491            pr "  VALUE rv = rb_ary_new2 (len);\n";
9492            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9493            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9494            pr "    free (r[i]);\n";
9495            pr "  }\n";
9496            pr "  free (r);\n";
9497            pr "  return rv;\n"
9498        | RStruct (_, typ) ->
9499            let cols = cols_of_struct typ in
9500            generate_ruby_struct_code typ cols
9501        | RStructList (_, typ) ->
9502            let cols = cols_of_struct typ in
9503            generate_ruby_struct_list_code typ cols
9504        | RHashtable _ ->
9505            pr "  VALUE rv = rb_hash_new ();\n";
9506            pr "  int i;\n";
9507            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9508            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9509            pr "    free (r[i]);\n";
9510            pr "    free (r[i+1]);\n";
9511            pr "  }\n";
9512            pr "  free (r);\n";
9513            pr "  return rv;\n"
9514        | RBufferOut _ ->
9515            pr "  VALUE rv = rb_str_new (r, size);\n";
9516            pr "  free (r);\n";
9517            pr "  return rv;\n";
9518       );
9519
9520       pr "}\n";
9521       pr "\n"
9522   ) all_functions;
9523
9524   pr "\
9525 /* Initialize the module. */
9526 void Init__guestfs ()
9527 {
9528   m_guestfs = rb_define_module (\"Guestfs\");
9529   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9530   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9531
9532   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9533   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9534
9535 ";
9536   (* Define the rest of the methods. *)
9537   List.iter (
9538     fun (name, style, _, _, _, _, _) ->
9539       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9540       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9541   ) all_functions;
9542
9543   pr "}\n"
9544
9545 (* Ruby code to return a struct. *)
9546 and generate_ruby_struct_code typ cols =
9547   pr "  VALUE rv = rb_hash_new ();\n";
9548   List.iter (
9549     function
9550     | name, FString ->
9551         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9552     | name, FBuffer ->
9553         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9554     | name, FUUID ->
9555         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9556     | name, (FBytes|FUInt64) ->
9557         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9558     | name, FInt64 ->
9559         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9560     | name, FUInt32 ->
9561         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9562     | name, FInt32 ->
9563         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9564     | name, FOptPercent ->
9565         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9566     | name, FChar -> (* XXX wrong? *)
9567         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9568   ) cols;
9569   pr "  guestfs_free_%s (r);\n" typ;
9570   pr "  return rv;\n"
9571
9572 (* Ruby code to return a struct list. *)
9573 and generate_ruby_struct_list_code typ cols =
9574   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9575   pr "  int i;\n";
9576   pr "  for (i = 0; i < r->len; ++i) {\n";
9577   pr "    VALUE hv = rb_hash_new ();\n";
9578   List.iter (
9579     function
9580     | name, FString ->
9581         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9582     | name, FBuffer ->
9583         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
9584     | name, FUUID ->
9585         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9586     | name, (FBytes|FUInt64) ->
9587         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9588     | name, FInt64 ->
9589         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9590     | name, FUInt32 ->
9591         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9592     | name, FInt32 ->
9593         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9594     | name, FOptPercent ->
9595         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9596     | name, FChar -> (* XXX wrong? *)
9597         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9598   ) cols;
9599   pr "    rb_ary_push (rv, hv);\n";
9600   pr "  }\n";
9601   pr "  guestfs_free_%s_list (r);\n" typ;
9602   pr "  return rv;\n"
9603
9604 (* Generate Java bindings GuestFS.java file. *)
9605 and generate_java_java () =
9606   generate_header CStyle LGPLv2plus;
9607
9608   pr "\
9609 package com.redhat.et.libguestfs;
9610
9611 import java.util.HashMap;
9612 import com.redhat.et.libguestfs.LibGuestFSException;
9613 import com.redhat.et.libguestfs.PV;
9614 import com.redhat.et.libguestfs.VG;
9615 import com.redhat.et.libguestfs.LV;
9616 import com.redhat.et.libguestfs.Stat;
9617 import com.redhat.et.libguestfs.StatVFS;
9618 import com.redhat.et.libguestfs.IntBool;
9619 import com.redhat.et.libguestfs.Dirent;
9620
9621 /**
9622  * The GuestFS object is a libguestfs handle.
9623  *
9624  * @author rjones
9625  */
9626 public class GuestFS {
9627   // Load the native code.
9628   static {
9629     System.loadLibrary (\"guestfs_jni\");
9630   }
9631
9632   /**
9633    * The native guestfs_h pointer.
9634    */
9635   long g;
9636
9637   /**
9638    * Create a libguestfs handle.
9639    *
9640    * @throws LibGuestFSException
9641    */
9642   public GuestFS () throws LibGuestFSException
9643   {
9644     g = _create ();
9645   }
9646   private native long _create () throws LibGuestFSException;
9647
9648   /**
9649    * Close a libguestfs handle.
9650    *
9651    * You can also leave handles to be collected by the garbage
9652    * collector, but this method ensures that the resources used
9653    * by the handle are freed up immediately.  If you call any
9654    * other methods after closing the handle, you will get an
9655    * exception.
9656    *
9657    * @throws LibGuestFSException
9658    */
9659   public void close () throws LibGuestFSException
9660   {
9661     if (g != 0)
9662       _close (g);
9663     g = 0;
9664   }
9665   private native void _close (long g) throws LibGuestFSException;
9666
9667   public void finalize () throws LibGuestFSException
9668   {
9669     close ();
9670   }
9671
9672 ";
9673
9674   List.iter (
9675     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9676       if not (List.mem NotInDocs flags); then (
9677         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9678         let doc =
9679           if List.mem ProtocolLimitWarning flags then
9680             doc ^ "\n\n" ^ protocol_limit_warning
9681           else doc in
9682         let doc =
9683           if List.mem DangerWillRobinson flags then
9684             doc ^ "\n\n" ^ danger_will_robinson
9685           else doc in
9686         let doc =
9687           match deprecation_notice flags with
9688           | None -> doc
9689           | Some txt -> doc ^ "\n\n" ^ txt in
9690         let doc = pod2text ~width:60 name doc in
9691         let doc = List.map (            (* RHBZ#501883 *)
9692           function
9693           | "" -> "<p>"
9694           | nonempty -> nonempty
9695         ) doc in
9696         let doc = String.concat "\n   * " doc in
9697
9698         pr "  /**\n";
9699         pr "   * %s\n" shortdesc;
9700         pr "   * <p>\n";
9701         pr "   * %s\n" doc;
9702         pr "   * @throws LibGuestFSException\n";
9703         pr "   */\n";
9704         pr "  ";
9705       );
9706       generate_java_prototype ~public:true ~semicolon:false name style;
9707       pr "\n";
9708       pr "  {\n";
9709       pr "    if (g == 0)\n";
9710       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9711         name;
9712       pr "    ";
9713       if fst style <> RErr then pr "return ";
9714       pr "_%s " name;
9715       generate_java_call_args ~handle:"g" (snd style);
9716       pr ";\n";
9717       pr "  }\n";
9718       pr "  ";
9719       generate_java_prototype ~privat:true ~native:true name style;
9720       pr "\n";
9721       pr "\n";
9722   ) all_functions;
9723
9724   pr "}\n"
9725
9726 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9727 and generate_java_call_args ~handle args =
9728   pr "(%s" handle;
9729   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9730   pr ")"
9731
9732 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9733     ?(semicolon=true) name style =
9734   if privat then pr "private ";
9735   if public then pr "public ";
9736   if native then pr "native ";
9737
9738   (* return type *)
9739   (match fst style with
9740    | RErr -> pr "void ";
9741    | RInt _ -> pr "int ";
9742    | RInt64 _ -> pr "long ";
9743    | RBool _ -> pr "boolean ";
9744    | RConstString _ | RConstOptString _ | RString _
9745    | RBufferOut _ -> pr "String ";
9746    | RStringList _ -> pr "String[] ";
9747    | RStruct (_, typ) ->
9748        let name = java_name_of_struct typ in
9749        pr "%s " name;
9750    | RStructList (_, typ) ->
9751        let name = java_name_of_struct typ in
9752        pr "%s[] " name;
9753    | RHashtable _ -> pr "HashMap<String,String> ";
9754   );
9755
9756   if native then pr "_%s " name else pr "%s " name;
9757   pr "(";
9758   let needs_comma = ref false in
9759   if native then (
9760     pr "long g";
9761     needs_comma := true
9762   );
9763
9764   (* args *)
9765   List.iter (
9766     fun arg ->
9767       if !needs_comma then pr ", ";
9768       needs_comma := true;
9769
9770       match arg with
9771       | Pathname n
9772       | Device n | Dev_or_Path n
9773       | String n
9774       | OptString n
9775       | FileIn n
9776       | FileOut n ->
9777           pr "String %s" n
9778       | StringList n | DeviceList n ->
9779           pr "String[] %s" n
9780       | Bool n ->
9781           pr "boolean %s" n
9782       | Int n ->
9783           pr "int %s" n
9784       | Int64 n ->
9785           pr "long %s" n
9786   ) (snd style);
9787
9788   pr ")\n";
9789   pr "    throws LibGuestFSException";
9790   if semicolon then pr ";"
9791
9792 and generate_java_struct jtyp cols () =
9793   generate_header CStyle LGPLv2plus;
9794
9795   pr "\
9796 package com.redhat.et.libguestfs;
9797
9798 /**
9799  * Libguestfs %s structure.
9800  *
9801  * @author rjones
9802  * @see GuestFS
9803  */
9804 public class %s {
9805 " jtyp jtyp;
9806
9807   List.iter (
9808     function
9809     | name, FString
9810     | name, FUUID
9811     | name, FBuffer -> pr "  public String %s;\n" name
9812     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9813     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9814     | name, FChar -> pr "  public char %s;\n" name
9815     | name, FOptPercent ->
9816         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9817         pr "  public float %s;\n" name
9818   ) cols;
9819
9820   pr "}\n"
9821
9822 and generate_java_c () =
9823   generate_header CStyle LGPLv2plus;
9824
9825   pr "\
9826 #include <stdio.h>
9827 #include <stdlib.h>
9828 #include <string.h>
9829
9830 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9831 #include \"guestfs.h\"
9832
9833 /* Note that this function returns.  The exception is not thrown
9834  * until after the wrapper function returns.
9835  */
9836 static void
9837 throw_exception (JNIEnv *env, const char *msg)
9838 {
9839   jclass cl;
9840   cl = (*env)->FindClass (env,
9841                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9842   (*env)->ThrowNew (env, cl, msg);
9843 }
9844
9845 JNIEXPORT jlong JNICALL
9846 Java_com_redhat_et_libguestfs_GuestFS__1create
9847   (JNIEnv *env, jobject obj)
9848 {
9849   guestfs_h *g;
9850
9851   g = guestfs_create ();
9852   if (g == NULL) {
9853     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9854     return 0;
9855   }
9856   guestfs_set_error_handler (g, NULL, NULL);
9857   return (jlong) (long) g;
9858 }
9859
9860 JNIEXPORT void JNICALL
9861 Java_com_redhat_et_libguestfs_GuestFS__1close
9862   (JNIEnv *env, jobject obj, jlong jg)
9863 {
9864   guestfs_h *g = (guestfs_h *) (long) jg;
9865   guestfs_close (g);
9866 }
9867
9868 ";
9869
9870   List.iter (
9871     fun (name, style, _, _, _, _, _) ->
9872       pr "JNIEXPORT ";
9873       (match fst style with
9874        | RErr -> pr "void ";
9875        | RInt _ -> pr "jint ";
9876        | RInt64 _ -> pr "jlong ";
9877        | RBool _ -> pr "jboolean ";
9878        | RConstString _ | RConstOptString _ | RString _
9879        | RBufferOut _ -> pr "jstring ";
9880        | RStruct _ | RHashtable _ ->
9881            pr "jobject ";
9882        | RStringList _ | RStructList _ ->
9883            pr "jobjectArray ";
9884       );
9885       pr "JNICALL\n";
9886       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9887       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9888       pr "\n";
9889       pr "  (JNIEnv *env, jobject obj, jlong jg";
9890       List.iter (
9891         function
9892         | Pathname n
9893         | Device n | Dev_or_Path n
9894         | String n
9895         | OptString n
9896         | FileIn n
9897         | FileOut n ->
9898             pr ", jstring j%s" n
9899         | StringList n | DeviceList n ->
9900             pr ", jobjectArray j%s" n
9901         | Bool n ->
9902             pr ", jboolean j%s" n
9903         | Int n ->
9904             pr ", jint j%s" n
9905         | Int64 n ->
9906             pr ", jlong j%s" n
9907       ) (snd style);
9908       pr ")\n";
9909       pr "{\n";
9910       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9911       let error_code, no_ret =
9912         match fst style with
9913         | RErr -> pr "  int r;\n"; "-1", ""
9914         | RBool _
9915         | RInt _ -> pr "  int r;\n"; "-1", "0"
9916         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9917         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9918         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9919         | RString _ ->
9920             pr "  jstring jr;\n";
9921             pr "  char *r;\n"; "NULL", "NULL"
9922         | RStringList _ ->
9923             pr "  jobjectArray jr;\n";
9924             pr "  int r_len;\n";
9925             pr "  jclass cl;\n";
9926             pr "  jstring jstr;\n";
9927             pr "  char **r;\n"; "NULL", "NULL"
9928         | RStruct (_, typ) ->
9929             pr "  jobject jr;\n";
9930             pr "  jclass cl;\n";
9931             pr "  jfieldID fl;\n";
9932             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9933         | RStructList (_, typ) ->
9934             pr "  jobjectArray jr;\n";
9935             pr "  jclass cl;\n";
9936             pr "  jfieldID fl;\n";
9937             pr "  jobject jfl;\n";
9938             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9939         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9940         | RBufferOut _ ->
9941             pr "  jstring jr;\n";
9942             pr "  char *r;\n";
9943             pr "  size_t size;\n";
9944             "NULL", "NULL" in
9945       List.iter (
9946         function
9947         | Pathname n
9948         | Device n | Dev_or_Path n
9949         | String n
9950         | OptString n
9951         | FileIn n
9952         | FileOut n ->
9953             pr "  const char *%s;\n" n
9954         | StringList n | DeviceList n ->
9955             pr "  int %s_len;\n" n;
9956             pr "  const char **%s;\n" n
9957         | Bool n
9958         | Int n ->
9959             pr "  int %s;\n" n
9960         | Int64 n ->
9961             pr "  int64_t %s;\n" n
9962       ) (snd style);
9963
9964       let needs_i =
9965         (match fst style with
9966          | RStringList _ | RStructList _ -> true
9967          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9968          | RConstOptString _
9969          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9970           List.exists (function
9971                        | StringList _ -> true
9972                        | DeviceList _ -> true
9973                        | _ -> false) (snd style) in
9974       if needs_i then
9975         pr "  int i;\n";
9976
9977       pr "\n";
9978
9979       (* Get the parameters. *)
9980       List.iter (
9981         function
9982         | Pathname n
9983         | Device n | Dev_or_Path n
9984         | String n
9985         | FileIn n
9986         | FileOut n ->
9987             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9988         | OptString n ->
9989             (* This is completely undocumented, but Java null becomes
9990              * a NULL parameter.
9991              *)
9992             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9993         | StringList n | DeviceList n ->
9994             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9995             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9996             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9997             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9998               n;
9999             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10000             pr "  }\n";
10001             pr "  %s[%s_len] = NULL;\n" n n;
10002         | Bool n
10003         | Int n
10004         | Int64 n ->
10005             pr "  %s = j%s;\n" n n
10006       ) (snd style);
10007
10008       (* Make the call. *)
10009       pr "  r = guestfs_%s " name;
10010       generate_c_call_args ~handle:"g" style;
10011       pr ";\n";
10012
10013       (* Release the parameters. *)
10014       List.iter (
10015         function
10016         | Pathname n
10017         | Device n | Dev_or_Path n
10018         | String n
10019         | FileIn n
10020         | FileOut n ->
10021             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10022         | OptString n ->
10023             pr "  if (j%s)\n" n;
10024             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10025         | StringList n | DeviceList n ->
10026             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10027             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10028               n;
10029             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10030             pr "  }\n";
10031             pr "  free (%s);\n" n
10032         | Bool n
10033         | Int n
10034         | Int64 n -> ()
10035       ) (snd style);
10036
10037       (* Check for errors. *)
10038       pr "  if (r == %s) {\n" error_code;
10039       pr "    throw_exception (env, guestfs_last_error (g));\n";
10040       pr "    return %s;\n" no_ret;
10041       pr "  }\n";
10042
10043       (* Return value. *)
10044       (match fst style with
10045        | RErr -> ()
10046        | RInt _ -> pr "  return (jint) r;\n"
10047        | RBool _ -> pr "  return (jboolean) r;\n"
10048        | RInt64 _ -> pr "  return (jlong) r;\n"
10049        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10050        | RConstOptString _ ->
10051            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10052        | RString _ ->
10053            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10054            pr "  free (r);\n";
10055            pr "  return jr;\n"
10056        | RStringList _ ->
10057            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10058            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10059            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10060            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10061            pr "  for (i = 0; i < r_len; ++i) {\n";
10062            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10063            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10064            pr "    free (r[i]);\n";
10065            pr "  }\n";
10066            pr "  free (r);\n";
10067            pr "  return jr;\n"
10068        | RStruct (_, typ) ->
10069            let jtyp = java_name_of_struct typ in
10070            let cols = cols_of_struct typ in
10071            generate_java_struct_return typ jtyp cols
10072        | RStructList (_, typ) ->
10073            let jtyp = java_name_of_struct typ in
10074            let cols = cols_of_struct typ in
10075            generate_java_struct_list_return typ jtyp cols
10076        | RHashtable _ ->
10077            (* XXX *)
10078            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10079            pr "  return NULL;\n"
10080        | RBufferOut _ ->
10081            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10082            pr "  free (r);\n";
10083            pr "  return jr;\n"
10084       );
10085
10086       pr "}\n";
10087       pr "\n"
10088   ) all_functions
10089
10090 and generate_java_struct_return typ jtyp cols =
10091   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10092   pr "  jr = (*env)->AllocObject (env, cl);\n";
10093   List.iter (
10094     function
10095     | name, FString ->
10096         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10097         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10098     | name, FUUID ->
10099         pr "  {\n";
10100         pr "    char s[33];\n";
10101         pr "    memcpy (s, r->%s, 32);\n" name;
10102         pr "    s[32] = 0;\n";
10103         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10104         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10105         pr "  }\n";
10106     | name, FBuffer ->
10107         pr "  {\n";
10108         pr "    int len = r->%s_len;\n" name;
10109         pr "    char s[len+1];\n";
10110         pr "    memcpy (s, r->%s, len);\n" name;
10111         pr "    s[len] = 0;\n";
10112         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10113         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10114         pr "  }\n";
10115     | name, (FBytes|FUInt64|FInt64) ->
10116         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10117         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10118     | name, (FUInt32|FInt32) ->
10119         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10120         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10121     | name, FOptPercent ->
10122         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10123         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10124     | name, FChar ->
10125         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10126         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10127   ) cols;
10128   pr "  free (r);\n";
10129   pr "  return jr;\n"
10130
10131 and generate_java_struct_list_return typ jtyp cols =
10132   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10133   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10134   pr "  for (i = 0; i < r->len; ++i) {\n";
10135   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10136   List.iter (
10137     function
10138     | name, FString ->
10139         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10140         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10141     | name, FUUID ->
10142         pr "    {\n";
10143         pr "      char s[33];\n";
10144         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10145         pr "      s[32] = 0;\n";
10146         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10147         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10148         pr "    }\n";
10149     | name, FBuffer ->
10150         pr "    {\n";
10151         pr "      int len = r->val[i].%s_len;\n" name;
10152         pr "      char s[len+1];\n";
10153         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10154         pr "      s[len] = 0;\n";
10155         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10156         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10157         pr "    }\n";
10158     | name, (FBytes|FUInt64|FInt64) ->
10159         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10160         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10161     | name, (FUInt32|FInt32) ->
10162         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10163         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10164     | name, FOptPercent ->
10165         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10166         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10167     | name, FChar ->
10168         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10169         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10170   ) cols;
10171   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10172   pr "  }\n";
10173   pr "  guestfs_free_%s_list (r);\n" typ;
10174   pr "  return jr;\n"
10175
10176 and generate_java_makefile_inc () =
10177   generate_header HashStyle GPLv2plus;
10178
10179   pr "java_built_sources = \\\n";
10180   List.iter (
10181     fun (typ, jtyp) ->
10182         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10183   ) java_structs;
10184   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10185
10186 and generate_haskell_hs () =
10187   generate_header HaskellStyle LGPLv2plus;
10188
10189   (* XXX We only know how to generate partial FFI for Haskell
10190    * at the moment.  Please help out!
10191    *)
10192   let can_generate style =
10193     match style with
10194     | RErr, _
10195     | RInt _, _
10196     | RInt64 _, _ -> true
10197     | RBool _, _
10198     | RConstString _, _
10199     | RConstOptString _, _
10200     | RString _, _
10201     | RStringList _, _
10202     | RStruct _, _
10203     | RStructList _, _
10204     | RHashtable _, _
10205     | RBufferOut _, _ -> false in
10206
10207   pr "\
10208 {-# INCLUDE <guestfs.h> #-}
10209 {-# LANGUAGE ForeignFunctionInterface #-}
10210
10211 module Guestfs (
10212   create";
10213
10214   (* List out the names of the actions we want to export. *)
10215   List.iter (
10216     fun (name, style, _, _, _, _, _) ->
10217       if can_generate style then pr ",\n  %s" name
10218   ) all_functions;
10219
10220   pr "
10221   ) where
10222
10223 -- Unfortunately some symbols duplicate ones already present
10224 -- in Prelude.  We don't know which, so we hard-code a list
10225 -- here.
10226 import Prelude hiding (truncate)
10227
10228 import Foreign
10229 import Foreign.C
10230 import Foreign.C.Types
10231 import IO
10232 import Control.Exception
10233 import Data.Typeable
10234
10235 data GuestfsS = GuestfsS            -- represents the opaque C struct
10236 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10237 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10238
10239 -- XXX define properly later XXX
10240 data PV = PV
10241 data VG = VG
10242 data LV = LV
10243 data IntBool = IntBool
10244 data Stat = Stat
10245 data StatVFS = StatVFS
10246 data Hashtable = Hashtable
10247
10248 foreign import ccall unsafe \"guestfs_create\" c_create
10249   :: IO GuestfsP
10250 foreign import ccall unsafe \"&guestfs_close\" c_close
10251   :: FunPtr (GuestfsP -> IO ())
10252 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10253   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10254
10255 create :: IO GuestfsH
10256 create = do
10257   p <- c_create
10258   c_set_error_handler p nullPtr nullPtr
10259   h <- newForeignPtr c_close p
10260   return h
10261
10262 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10263   :: GuestfsP -> IO CString
10264
10265 -- last_error :: GuestfsH -> IO (Maybe String)
10266 -- last_error h = do
10267 --   str <- withForeignPtr h (\\p -> c_last_error p)
10268 --   maybePeek peekCString str
10269
10270 last_error :: GuestfsH -> IO (String)
10271 last_error h = do
10272   str <- withForeignPtr h (\\p -> c_last_error p)
10273   if (str == nullPtr)
10274     then return \"no error\"
10275     else peekCString str
10276
10277 ";
10278
10279   (* Generate wrappers for each foreign function. *)
10280   List.iter (
10281     fun (name, style, _, _, _, _, _) ->
10282       if can_generate style then (
10283         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10284         pr "  :: ";
10285         generate_haskell_prototype ~handle:"GuestfsP" style;
10286         pr "\n";
10287         pr "\n";
10288         pr "%s :: " name;
10289         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10290         pr "\n";
10291         pr "%s %s = do\n" name
10292           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10293         pr "  r <- ";
10294         (* Convert pointer arguments using with* functions. *)
10295         List.iter (
10296           function
10297           | FileIn n
10298           | FileOut n
10299           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10300           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10301           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10302           | Bool _ | Int _ | Int64 _ -> ()
10303         ) (snd style);
10304         (* Convert integer arguments. *)
10305         let args =
10306           List.map (
10307             function
10308             | Bool n -> sprintf "(fromBool %s)" n
10309             | Int n -> sprintf "(fromIntegral %s)" n
10310             | Int64 n -> sprintf "(fromIntegral %s)" n
10311             | FileIn n | FileOut n
10312             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10313           ) (snd style) in
10314         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10315           (String.concat " " ("p" :: args));
10316         (match fst style with
10317          | RErr | RInt _ | RInt64 _ | RBool _ ->
10318              pr "  if (r == -1)\n";
10319              pr "    then do\n";
10320              pr "      err <- last_error h\n";
10321              pr "      fail err\n";
10322          | RConstString _ | RConstOptString _ | RString _
10323          | RStringList _ | RStruct _
10324          | RStructList _ | RHashtable _ | RBufferOut _ ->
10325              pr "  if (r == nullPtr)\n";
10326              pr "    then do\n";
10327              pr "      err <- last_error h\n";
10328              pr "      fail err\n";
10329         );
10330         (match fst style with
10331          | RErr ->
10332              pr "    else return ()\n"
10333          | RInt _ ->
10334              pr "    else return (fromIntegral r)\n"
10335          | RInt64 _ ->
10336              pr "    else return (fromIntegral r)\n"
10337          | RBool _ ->
10338              pr "    else return (toBool r)\n"
10339          | RConstString _
10340          | RConstOptString _
10341          | RString _
10342          | RStringList _
10343          | RStruct _
10344          | RStructList _
10345          | RHashtable _
10346          | RBufferOut _ ->
10347              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10348         );
10349         pr "\n";
10350       )
10351   ) all_functions
10352
10353 and generate_haskell_prototype ~handle ?(hs = false) style =
10354   pr "%s -> " handle;
10355   let string = if hs then "String" else "CString" in
10356   let int = if hs then "Int" else "CInt" in
10357   let bool = if hs then "Bool" else "CInt" in
10358   let int64 = if hs then "Integer" else "Int64" in
10359   List.iter (
10360     fun arg ->
10361       (match arg with
10362        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10363        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10364        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10365        | Bool _ -> pr "%s" bool
10366        | Int _ -> pr "%s" int
10367        | Int64 _ -> pr "%s" int
10368        | FileIn _ -> pr "%s" string
10369        | FileOut _ -> pr "%s" string
10370       );
10371       pr " -> ";
10372   ) (snd style);
10373   pr "IO (";
10374   (match fst style with
10375    | RErr -> if not hs then pr "CInt"
10376    | RInt _ -> pr "%s" int
10377    | RInt64 _ -> pr "%s" int64
10378    | RBool _ -> pr "%s" bool
10379    | RConstString _ -> pr "%s" string
10380    | RConstOptString _ -> pr "Maybe %s" string
10381    | RString _ -> pr "%s" string
10382    | RStringList _ -> pr "[%s]" string
10383    | RStruct (_, typ) ->
10384        let name = java_name_of_struct typ in
10385        pr "%s" name
10386    | RStructList (_, typ) ->
10387        let name = java_name_of_struct typ in
10388        pr "[%s]" name
10389    | RHashtable _ -> pr "Hashtable"
10390    | RBufferOut _ -> pr "%s" string
10391   );
10392   pr ")"
10393
10394 and generate_csharp () =
10395   generate_header CPlusPlusStyle LGPLv2plus;
10396
10397   (* XXX Make this configurable by the C# assembly users. *)
10398   let library = "libguestfs.so.0" in
10399
10400   pr "\
10401 // These C# bindings are highly experimental at present.
10402 //
10403 // Firstly they only work on Linux (ie. Mono).  In order to get them
10404 // to work on Windows (ie. .Net) you would need to port the library
10405 // itself to Windows first.
10406 //
10407 // The second issue is that some calls are known to be incorrect and
10408 // can cause Mono to segfault.  Particularly: calls which pass or
10409 // return string[], or return any structure value.  This is because
10410 // we haven't worked out the correct way to do this from C#.
10411 //
10412 // The third issue is that when compiling you get a lot of warnings.
10413 // We are not sure whether the warnings are important or not.
10414 //
10415 // Fourthly we do not routinely build or test these bindings as part
10416 // of the make && make check cycle, which means that regressions might
10417 // go unnoticed.
10418 //
10419 // Suggestions and patches are welcome.
10420
10421 // To compile:
10422 //
10423 // gmcs Libguestfs.cs
10424 // mono Libguestfs.exe
10425 //
10426 // (You'll probably want to add a Test class / static main function
10427 // otherwise this won't do anything useful).
10428
10429 using System;
10430 using System.IO;
10431 using System.Runtime.InteropServices;
10432 using System.Runtime.Serialization;
10433 using System.Collections;
10434
10435 namespace Guestfs
10436 {
10437   class Error : System.ApplicationException
10438   {
10439     public Error (string message) : base (message) {}
10440     protected Error (SerializationInfo info, StreamingContext context) {}
10441   }
10442
10443   class Guestfs
10444   {
10445     IntPtr _handle;
10446
10447     [DllImport (\"%s\")]
10448     static extern IntPtr guestfs_create ();
10449
10450     public Guestfs ()
10451     {
10452       _handle = guestfs_create ();
10453       if (_handle == IntPtr.Zero)
10454         throw new Error (\"could not create guestfs handle\");
10455     }
10456
10457     [DllImport (\"%s\")]
10458     static extern void guestfs_close (IntPtr h);
10459
10460     ~Guestfs ()
10461     {
10462       guestfs_close (_handle);
10463     }
10464
10465     [DllImport (\"%s\")]
10466     static extern string guestfs_last_error (IntPtr h);
10467
10468 " library library library;
10469
10470   (* Generate C# structure bindings.  We prefix struct names with
10471    * underscore because C# cannot have conflicting struct names and
10472    * method names (eg. "class stat" and "stat").
10473    *)
10474   List.iter (
10475     fun (typ, cols) ->
10476       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10477       pr "    public class _%s {\n" typ;
10478       List.iter (
10479         function
10480         | name, FChar -> pr "      char %s;\n" name
10481         | name, FString -> pr "      string %s;\n" name
10482         | name, FBuffer ->
10483             pr "      uint %s_len;\n" name;
10484             pr "      string %s;\n" name
10485         | name, FUUID ->
10486             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10487             pr "      string %s;\n" name
10488         | name, FUInt32 -> pr "      uint %s;\n" name
10489         | name, FInt32 -> pr "      int %s;\n" name
10490         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10491         | name, FInt64 -> pr "      long %s;\n" name
10492         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10493       ) cols;
10494       pr "    }\n";
10495       pr "\n"
10496   ) structs;
10497
10498   (* Generate C# function bindings. *)
10499   List.iter (
10500     fun (name, style, _, _, _, shortdesc, _) ->
10501       let rec csharp_return_type () =
10502         match fst style with
10503         | RErr -> "void"
10504         | RBool n -> "bool"
10505         | RInt n -> "int"
10506         | RInt64 n -> "long"
10507         | RConstString n
10508         | RConstOptString n
10509         | RString n
10510         | RBufferOut n -> "string"
10511         | RStruct (_,n) -> "_" ^ n
10512         | RHashtable n -> "Hashtable"
10513         | RStringList n -> "string[]"
10514         | RStructList (_,n) -> sprintf "_%s[]" n
10515
10516       and c_return_type () =
10517         match fst style with
10518         | RErr
10519         | RBool _
10520         | RInt _ -> "int"
10521         | RInt64 _ -> "long"
10522         | RConstString _
10523         | RConstOptString _
10524         | RString _
10525         | RBufferOut _ -> "string"
10526         | RStruct (_,n) -> "_" ^ n
10527         | RHashtable _
10528         | RStringList _ -> "string[]"
10529         | RStructList (_,n) -> sprintf "_%s[]" n
10530
10531       and c_error_comparison () =
10532         match fst style with
10533         | RErr
10534         | RBool _
10535         | RInt _
10536         | RInt64 _ -> "== -1"
10537         | RConstString _
10538         | RConstOptString _
10539         | RString _
10540         | RBufferOut _
10541         | RStruct (_,_)
10542         | RHashtable _
10543         | RStringList _
10544         | RStructList (_,_) -> "== null"
10545
10546       and generate_extern_prototype () =
10547         pr "    static extern %s guestfs_%s (IntPtr h"
10548           (c_return_type ()) name;
10549         List.iter (
10550           function
10551           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10552           | FileIn n | FileOut n ->
10553               pr ", [In] string %s" n
10554           | StringList n | DeviceList n ->
10555               pr ", [In] string[] %s" n
10556           | Bool n ->
10557               pr ", bool %s" n
10558           | Int n ->
10559               pr ", int %s" n
10560           | Int64 n ->
10561               pr ", long %s" n
10562         ) (snd style);
10563         pr ");\n"
10564
10565       and generate_public_prototype () =
10566         pr "    public %s %s (" (csharp_return_type ()) name;
10567         let comma = ref false in
10568         let next () =
10569           if !comma then pr ", ";
10570           comma := true
10571         in
10572         List.iter (
10573           function
10574           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10575           | FileIn n | FileOut n ->
10576               next (); pr "string %s" n
10577           | StringList n | DeviceList n ->
10578               next (); pr "string[] %s" n
10579           | Bool n ->
10580               next (); pr "bool %s" n
10581           | Int n ->
10582               next (); pr "int %s" n
10583           | Int64 n ->
10584               next (); pr "long %s" n
10585         ) (snd style);
10586         pr ")\n"
10587
10588       and generate_call () =
10589         pr "guestfs_%s (_handle" name;
10590         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10591         pr ");\n";
10592       in
10593
10594       pr "    [DllImport (\"%s\")]\n" library;
10595       generate_extern_prototype ();
10596       pr "\n";
10597       pr "    /// <summary>\n";
10598       pr "    /// %s\n" shortdesc;
10599       pr "    /// </summary>\n";
10600       generate_public_prototype ();
10601       pr "    {\n";
10602       pr "      %s r;\n" (c_return_type ());
10603       pr "      r = ";
10604       generate_call ();
10605       pr "      if (r %s)\n" (c_error_comparison ());
10606       pr "        throw new Error (guestfs_last_error (_handle));\n";
10607       (match fst style with
10608        | RErr -> ()
10609        | RBool _ ->
10610            pr "      return r != 0 ? true : false;\n"
10611        | RHashtable _ ->
10612            pr "      Hashtable rr = new Hashtable ();\n";
10613            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10614            pr "        rr.Add (r[i], r[i+1]);\n";
10615            pr "      return rr;\n"
10616        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10617        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10618        | RStructList _ ->
10619            pr "      return r;\n"
10620       );
10621       pr "    }\n";
10622       pr "\n";
10623   ) all_functions_sorted;
10624
10625   pr "  }
10626 }
10627 "
10628
10629 and generate_bindtests () =
10630   generate_header CStyle LGPLv2plus;
10631
10632   pr "\
10633 #include <stdio.h>
10634 #include <stdlib.h>
10635 #include <inttypes.h>
10636 #include <string.h>
10637
10638 #include \"guestfs.h\"
10639 #include \"guestfs-internal.h\"
10640 #include \"guestfs-internal-actions.h\"
10641 #include \"guestfs_protocol.h\"
10642
10643 #define error guestfs_error
10644 #define safe_calloc guestfs_safe_calloc
10645 #define safe_malloc guestfs_safe_malloc
10646
10647 static void
10648 print_strings (char *const *argv)
10649 {
10650   int argc;
10651
10652   printf (\"[\");
10653   for (argc = 0; argv[argc] != NULL; ++argc) {
10654     if (argc > 0) printf (\", \");
10655     printf (\"\\\"%%s\\\"\", argv[argc]);
10656   }
10657   printf (\"]\\n\");
10658 }
10659
10660 /* The test0 function prints its parameters to stdout. */
10661 ";
10662
10663   let test0, tests =
10664     match test_functions with
10665     | [] -> assert false
10666     | test0 :: tests -> test0, tests in
10667
10668   let () =
10669     let (name, style, _, _, _, _, _) = test0 in
10670     generate_prototype ~extern:false ~semicolon:false ~newline:true
10671       ~handle:"g" ~prefix:"guestfs__" name style;
10672     pr "{\n";
10673     List.iter (
10674       function
10675       | Pathname n
10676       | Device n | Dev_or_Path n
10677       | String n
10678       | FileIn n
10679       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10680       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10681       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10682       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10683       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10684       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10685     ) (snd style);
10686     pr "  /* Java changes stdout line buffering so we need this: */\n";
10687     pr "  fflush (stdout);\n";
10688     pr "  return 0;\n";
10689     pr "}\n";
10690     pr "\n" in
10691
10692   List.iter (
10693     fun (name, style, _, _, _, _, _) ->
10694       if String.sub name (String.length name - 3) 3 <> "err" then (
10695         pr "/* Test normal return. */\n";
10696         generate_prototype ~extern:false ~semicolon:false ~newline:true
10697           ~handle:"g" ~prefix:"guestfs__" name style;
10698         pr "{\n";
10699         (match fst style with
10700          | RErr ->
10701              pr "  return 0;\n"
10702          | RInt _ ->
10703              pr "  int r;\n";
10704              pr "  sscanf (val, \"%%d\", &r);\n";
10705              pr "  return r;\n"
10706          | RInt64 _ ->
10707              pr "  int64_t r;\n";
10708              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10709              pr "  return r;\n"
10710          | RBool _ ->
10711              pr "  return STREQ (val, \"true\");\n"
10712          | RConstString _
10713          | RConstOptString _ ->
10714              (* Can't return the input string here.  Return a static
10715               * string so we ensure we get a segfault if the caller
10716               * tries to free it.
10717               *)
10718              pr "  return \"static string\";\n"
10719          | RString _ ->
10720              pr "  return strdup (val);\n"
10721          | RStringList _ ->
10722              pr "  char **strs;\n";
10723              pr "  int n, i;\n";
10724              pr "  sscanf (val, \"%%d\", &n);\n";
10725              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10726              pr "  for (i = 0; i < n; ++i) {\n";
10727              pr "    strs[i] = safe_malloc (g, 16);\n";
10728              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10729              pr "  }\n";
10730              pr "  strs[n] = NULL;\n";
10731              pr "  return strs;\n"
10732          | RStruct (_, typ) ->
10733              pr "  struct guestfs_%s *r;\n" typ;
10734              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10735              pr "  return r;\n"
10736          | RStructList (_, typ) ->
10737              pr "  struct guestfs_%s_list *r;\n" typ;
10738              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10739              pr "  sscanf (val, \"%%d\", &r->len);\n";
10740              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10741              pr "  return r;\n"
10742          | RHashtable _ ->
10743              pr "  char **strs;\n";
10744              pr "  int n, i;\n";
10745              pr "  sscanf (val, \"%%d\", &n);\n";
10746              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10747              pr "  for (i = 0; i < n; ++i) {\n";
10748              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10749              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10750              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10751              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10752              pr "  }\n";
10753              pr "  strs[n*2] = NULL;\n";
10754              pr "  return strs;\n"
10755          | RBufferOut _ ->
10756              pr "  return strdup (val);\n"
10757         );
10758         pr "}\n";
10759         pr "\n"
10760       ) else (
10761         pr "/* Test error return. */\n";
10762         generate_prototype ~extern:false ~semicolon:false ~newline:true
10763           ~handle:"g" ~prefix:"guestfs__" name style;
10764         pr "{\n";
10765         pr "  error (g, \"error\");\n";
10766         (match fst style with
10767          | RErr | RInt _ | RInt64 _ | RBool _ ->
10768              pr "  return -1;\n"
10769          | RConstString _ | RConstOptString _
10770          | RString _ | RStringList _ | RStruct _
10771          | RStructList _
10772          | RHashtable _
10773          | RBufferOut _ ->
10774              pr "  return NULL;\n"
10775         );
10776         pr "}\n";
10777         pr "\n"
10778       )
10779   ) tests
10780
10781 and generate_ocaml_bindtests () =
10782   generate_header OCamlStyle GPLv2plus;
10783
10784   pr "\
10785 let () =
10786   let g = Guestfs.create () in
10787 ";
10788
10789   let mkargs args =
10790     String.concat " " (
10791       List.map (
10792         function
10793         | CallString s -> "\"" ^ s ^ "\""
10794         | CallOptString None -> "None"
10795         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10796         | CallStringList xs ->
10797             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10798         | CallInt i when i >= 0 -> string_of_int i
10799         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10800         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10801         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10802         | CallBool b -> string_of_bool b
10803       ) args
10804     )
10805   in
10806
10807   generate_lang_bindtests (
10808     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10809   );
10810
10811   pr "print_endline \"EOF\"\n"
10812
10813 and generate_perl_bindtests () =
10814   pr "#!/usr/bin/perl -w\n";
10815   generate_header HashStyle GPLv2plus;
10816
10817   pr "\
10818 use strict;
10819
10820 use Sys::Guestfs;
10821
10822 my $g = Sys::Guestfs->new ();
10823 ";
10824
10825   let mkargs args =
10826     String.concat ", " (
10827       List.map (
10828         function
10829         | CallString s -> "\"" ^ s ^ "\""
10830         | CallOptString None -> "undef"
10831         | CallOptString (Some s) -> sprintf "\"%s\"" s
10832         | CallStringList xs ->
10833             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10834         | CallInt i -> string_of_int i
10835         | CallInt64 i -> Int64.to_string i
10836         | CallBool b -> if b then "1" else "0"
10837       ) args
10838     )
10839   in
10840
10841   generate_lang_bindtests (
10842     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10843   );
10844
10845   pr "print \"EOF\\n\"\n"
10846
10847 and generate_python_bindtests () =
10848   generate_header HashStyle GPLv2plus;
10849
10850   pr "\
10851 import guestfs
10852
10853 g = guestfs.GuestFS ()
10854 ";
10855
10856   let mkargs args =
10857     String.concat ", " (
10858       List.map (
10859         function
10860         | CallString s -> "\"" ^ s ^ "\""
10861         | CallOptString None -> "None"
10862         | CallOptString (Some s) -> sprintf "\"%s\"" s
10863         | CallStringList xs ->
10864             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10865         | CallInt i -> string_of_int i
10866         | CallInt64 i -> Int64.to_string i
10867         | CallBool b -> if b then "1" else "0"
10868       ) args
10869     )
10870   in
10871
10872   generate_lang_bindtests (
10873     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10874   );
10875
10876   pr "print \"EOF\"\n"
10877
10878 and generate_ruby_bindtests () =
10879   generate_header HashStyle GPLv2plus;
10880
10881   pr "\
10882 require 'guestfs'
10883
10884 g = Guestfs::create()
10885 ";
10886
10887   let mkargs args =
10888     String.concat ", " (
10889       List.map (
10890         function
10891         | CallString s -> "\"" ^ s ^ "\""
10892         | CallOptString None -> "nil"
10893         | CallOptString (Some s) -> sprintf "\"%s\"" s
10894         | CallStringList xs ->
10895             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10896         | CallInt i -> string_of_int i
10897         | CallInt64 i -> Int64.to_string i
10898         | CallBool b -> string_of_bool b
10899       ) args
10900     )
10901   in
10902
10903   generate_lang_bindtests (
10904     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10905   );
10906
10907   pr "print \"EOF\\n\"\n"
10908
10909 and generate_java_bindtests () =
10910   generate_header CStyle GPLv2plus;
10911
10912   pr "\
10913 import com.redhat.et.libguestfs.*;
10914
10915 public class Bindtests {
10916     public static void main (String[] argv)
10917     {
10918         try {
10919             GuestFS g = new GuestFS ();
10920 ";
10921
10922   let mkargs args =
10923     String.concat ", " (
10924       List.map (
10925         function
10926         | CallString s -> "\"" ^ s ^ "\""
10927         | CallOptString None -> "null"
10928         | CallOptString (Some s) -> sprintf "\"%s\"" s
10929         | CallStringList xs ->
10930             "new String[]{" ^
10931               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10932         | CallInt i -> string_of_int i
10933         | CallInt64 i -> Int64.to_string i
10934         | CallBool b -> string_of_bool b
10935       ) args
10936     )
10937   in
10938
10939   generate_lang_bindtests (
10940     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10941   );
10942
10943   pr "
10944             System.out.println (\"EOF\");
10945         }
10946         catch (Exception exn) {
10947             System.err.println (exn);
10948             System.exit (1);
10949         }
10950     }
10951 }
10952 "
10953
10954 and generate_haskell_bindtests () =
10955   generate_header HaskellStyle GPLv2plus;
10956
10957   pr "\
10958 module Bindtests where
10959 import qualified Guestfs
10960
10961 main = do
10962   g <- Guestfs.create
10963 ";
10964
10965   let mkargs args =
10966     String.concat " " (
10967       List.map (
10968         function
10969         | CallString s -> "\"" ^ s ^ "\""
10970         | CallOptString None -> "Nothing"
10971         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10972         | CallStringList xs ->
10973             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10974         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10975         | CallInt i -> string_of_int i
10976         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10977         | CallInt64 i -> Int64.to_string i
10978         | CallBool true -> "True"
10979         | CallBool false -> "False"
10980       ) args
10981     )
10982   in
10983
10984   generate_lang_bindtests (
10985     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10986   );
10987
10988   pr "  putStrLn \"EOF\"\n"
10989
10990 (* Language-independent bindings tests - we do it this way to
10991  * ensure there is parity in testing bindings across all languages.
10992  *)
10993 and generate_lang_bindtests call =
10994   call "test0" [CallString "abc"; CallOptString (Some "def");
10995                 CallStringList []; CallBool false;
10996                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10997   call "test0" [CallString "abc"; CallOptString None;
10998                 CallStringList []; CallBool false;
10999                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11000   call "test0" [CallString ""; CallOptString (Some "def");
11001                 CallStringList []; CallBool false;
11002                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11003   call "test0" [CallString ""; CallOptString (Some "");
11004                 CallStringList []; CallBool false;
11005                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11006   call "test0" [CallString "abc"; CallOptString (Some "def");
11007                 CallStringList ["1"]; CallBool false;
11008                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11009   call "test0" [CallString "abc"; CallOptString (Some "def");
11010                 CallStringList ["1"; "2"]; CallBool false;
11011                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11012   call "test0" [CallString "abc"; CallOptString (Some "def");
11013                 CallStringList ["1"]; CallBool true;
11014                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11015   call "test0" [CallString "abc"; CallOptString (Some "def");
11016                 CallStringList ["1"]; CallBool false;
11017                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11018   call "test0" [CallString "abc"; CallOptString (Some "def");
11019                 CallStringList ["1"]; CallBool false;
11020                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11021   call "test0" [CallString "abc"; CallOptString (Some "def");
11022                 CallStringList ["1"]; CallBool false;
11023                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11024   call "test0" [CallString "abc"; CallOptString (Some "def");
11025                 CallStringList ["1"]; CallBool false;
11026                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11027   call "test0" [CallString "abc"; CallOptString (Some "def");
11028                 CallStringList ["1"]; CallBool false;
11029                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11030   call "test0" [CallString "abc"; CallOptString (Some "def");
11031                 CallStringList ["1"]; CallBool false;
11032                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11033
11034 (* XXX Add here tests of the return and error functions. *)
11035
11036 (* Code to generator bindings for virt-inspector.  Currently only
11037  * implemented for OCaml code (for virt-p2v 2.0).
11038  *)
11039 let rng_input = "inspector/virt-inspector.rng"
11040
11041 (* Read the input file and parse it into internal structures.  This is
11042  * by no means a complete RELAX NG parser, but is just enough to be
11043  * able to parse the specific input file.
11044  *)
11045 type rng =
11046   | Element of string * rng list        (* <element name=name/> *)
11047   | Attribute of string * rng list        (* <attribute name=name/> *)
11048   | Interleave of rng list                (* <interleave/> *)
11049   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11050   | OneOrMore of rng                        (* <oneOrMore/> *)
11051   | Optional of rng                        (* <optional/> *)
11052   | Choice of string list                (* <choice><value/>*</choice> *)
11053   | Value of string                        (* <value>str</value> *)
11054   | Text                                (* <text/> *)
11055
11056 let rec string_of_rng = function
11057   | Element (name, xs) ->
11058       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11059   | Attribute (name, xs) ->
11060       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11061   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11062   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11063   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11064   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11065   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11066   | Value value -> "Value \"" ^ value ^ "\""
11067   | Text -> "Text"
11068
11069 and string_of_rng_list xs =
11070   String.concat ", " (List.map string_of_rng xs)
11071
11072 let rec parse_rng ?defines context = function
11073   | [] -> []
11074   | Xml.Element ("element", ["name", name], children) :: rest ->
11075       Element (name, parse_rng ?defines context children)
11076       :: parse_rng ?defines context rest
11077   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11078       Attribute (name, parse_rng ?defines context children)
11079       :: parse_rng ?defines context rest
11080   | Xml.Element ("interleave", [], children) :: rest ->
11081       Interleave (parse_rng ?defines context children)
11082       :: parse_rng ?defines context rest
11083   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11084       let rng = parse_rng ?defines context [child] in
11085       (match rng with
11086        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11087        | _ ->
11088            failwithf "%s: <zeroOrMore> contains more than one child element"
11089              context
11090       )
11091   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11092       let rng = parse_rng ?defines context [child] in
11093       (match rng with
11094        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11095        | _ ->
11096            failwithf "%s: <oneOrMore> contains more than one child element"
11097              context
11098       )
11099   | Xml.Element ("optional", [], [child]) :: rest ->
11100       let rng = parse_rng ?defines context [child] in
11101       (match rng with
11102        | [child] -> Optional child :: parse_rng ?defines context rest
11103        | _ ->
11104            failwithf "%s: <optional> contains more than one child element"
11105              context
11106       )
11107   | Xml.Element ("choice", [], children) :: rest ->
11108       let values = List.map (
11109         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11110         | _ ->
11111             failwithf "%s: can't handle anything except <value> in <choice>"
11112               context
11113       ) children in
11114       Choice values
11115       :: parse_rng ?defines context rest
11116   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11117       Value value :: parse_rng ?defines context rest
11118   | Xml.Element ("text", [], []) :: rest ->
11119       Text :: parse_rng ?defines context rest
11120   | Xml.Element ("ref", ["name", name], []) :: rest ->
11121       (* Look up the reference.  Because of limitations in this parser,
11122        * we can't handle arbitrarily nested <ref> yet.  You can only
11123        * use <ref> from inside <start>.
11124        *)
11125       (match defines with
11126        | None ->
11127            failwithf "%s: contains <ref>, but no refs are defined yet" context
11128        | Some map ->
11129            let rng = StringMap.find name map in
11130            rng @ parse_rng ?defines context rest
11131       )
11132   | x :: _ ->
11133       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11134
11135 let grammar =
11136   let xml = Xml.parse_file rng_input in
11137   match xml with
11138   | Xml.Element ("grammar", _,
11139                  Xml.Element ("start", _, gram) :: defines) ->
11140       (* The <define/> elements are referenced in the <start> section,
11141        * so build a map of those first.
11142        *)
11143       let defines = List.fold_left (
11144         fun map ->
11145           function Xml.Element ("define", ["name", name], defn) ->
11146             StringMap.add name defn map
11147           | _ ->
11148               failwithf "%s: expected <define name=name/>" rng_input
11149       ) StringMap.empty defines in
11150       let defines = StringMap.mapi parse_rng defines in
11151
11152       (* Parse the <start> clause, passing the defines. *)
11153       parse_rng ~defines "<start>" gram
11154   | _ ->
11155       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11156         rng_input
11157
11158 let name_of_field = function
11159   | Element (name, _) | Attribute (name, _)
11160   | ZeroOrMore (Element (name, _))
11161   | OneOrMore (Element (name, _))
11162   | Optional (Element (name, _)) -> name
11163   | Optional (Attribute (name, _)) -> name
11164   | Text -> (* an unnamed field in an element *)
11165       "data"
11166   | rng ->
11167       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11168
11169 (* At the moment this function only generates OCaml types.  However we
11170  * should parameterize it later so it can generate types/structs in a
11171  * variety of languages.
11172  *)
11173 let generate_types xs =
11174   (* A simple type is one that can be printed out directly, eg.
11175    * "string option".  A complex type is one which has a name and has
11176    * to be defined via another toplevel definition, eg. a struct.
11177    *
11178    * generate_type generates code for either simple or complex types.
11179    * In the simple case, it returns the string ("string option").  In
11180    * the complex case, it returns the name ("mountpoint").  In the
11181    * complex case it has to print out the definition before returning,
11182    * so it should only be called when we are at the beginning of a
11183    * new line (BOL context).
11184    *)
11185   let rec generate_type = function
11186     | Text ->                                (* string *)
11187         "string", true
11188     | Choice values ->                        (* [`val1|`val2|...] *)
11189         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11190     | ZeroOrMore rng ->                        (* <rng> list *)
11191         let t, is_simple = generate_type rng in
11192         t ^ " list (* 0 or more *)", is_simple
11193     | OneOrMore rng ->                        (* <rng> list *)
11194         let t, is_simple = generate_type rng in
11195         t ^ " list (* 1 or more *)", is_simple
11196                                         (* virt-inspector hack: bool *)
11197     | Optional (Attribute (name, [Value "1"])) ->
11198         "bool", true
11199     | Optional rng ->                        (* <rng> list *)
11200         let t, is_simple = generate_type rng in
11201         t ^ " option", is_simple
11202                                         (* type name = { fields ... } *)
11203     | Element (name, fields) when is_attrs_interleave fields ->
11204         generate_type_struct name (get_attrs_interleave fields)
11205     | Element (name, [field])                (* type name = field *)
11206     | Attribute (name, [field]) ->
11207         let t, is_simple = generate_type field in
11208         if is_simple then (t, true)
11209         else (
11210           pr "type %s = %s\n" name t;
11211           name, false
11212         )
11213     | Element (name, fields) ->              (* type name = { fields ... } *)
11214         generate_type_struct name fields
11215     | rng ->
11216         failwithf "generate_type failed at: %s" (string_of_rng rng)
11217
11218   and is_attrs_interleave = function
11219     | [Interleave _] -> true
11220     | Attribute _ :: fields -> is_attrs_interleave fields
11221     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11222     | _ -> false
11223
11224   and get_attrs_interleave = function
11225     | [Interleave fields] -> fields
11226     | ((Attribute _) as field) :: fields
11227     | ((Optional (Attribute _)) as field) :: fields ->
11228         field :: get_attrs_interleave fields
11229     | _ -> assert false
11230
11231   and generate_types xs =
11232     List.iter (fun x -> ignore (generate_type x)) xs
11233
11234   and generate_type_struct name fields =
11235     (* Calculate the types of the fields first.  We have to do this
11236      * before printing anything so we are still in BOL context.
11237      *)
11238     let types = List.map fst (List.map generate_type fields) in
11239
11240     (* Special case of a struct containing just a string and another
11241      * field.  Turn it into an assoc list.
11242      *)
11243     match types with
11244     | ["string"; other] ->
11245         let fname1, fname2 =
11246           match fields with
11247           | [f1; f2] -> name_of_field f1, name_of_field f2
11248           | _ -> assert false in
11249         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11250         name, false
11251
11252     | types ->
11253         pr "type %s = {\n" name;
11254         List.iter (
11255           fun (field, ftype) ->
11256             let fname = name_of_field field in
11257             pr "  %s_%s : %s;\n" name fname ftype
11258         ) (List.combine fields types);
11259         pr "}\n";
11260         (* Return the name of this type, and
11261          * false because it's not a simple type.
11262          *)
11263         name, false
11264   in
11265
11266   generate_types xs
11267
11268 let generate_parsers xs =
11269   (* As for generate_type above, generate_parser makes a parser for
11270    * some type, and returns the name of the parser it has generated.
11271    * Because it (may) need to print something, it should always be
11272    * called in BOL context.
11273    *)
11274   let rec generate_parser = function
11275     | Text ->                                (* string *)
11276         "string_child_or_empty"
11277     | Choice values ->                        (* [`val1|`val2|...] *)
11278         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11279           (String.concat "|"
11280              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11281     | ZeroOrMore rng ->                        (* <rng> list *)
11282         let pa = generate_parser rng in
11283         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11284     | OneOrMore rng ->                        (* <rng> list *)
11285         let pa = generate_parser rng in
11286         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11287                                         (* virt-inspector hack: bool *)
11288     | Optional (Attribute (name, [Value "1"])) ->
11289         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11290     | Optional rng ->                        (* <rng> list *)
11291         let pa = generate_parser rng in
11292         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11293                                         (* type name = { fields ... } *)
11294     | Element (name, fields) when is_attrs_interleave fields ->
11295         generate_parser_struct name (get_attrs_interleave fields)
11296     | Element (name, [field]) ->        (* type name = field *)
11297         let pa = generate_parser field in
11298         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11299         pr "let %s =\n" parser_name;
11300         pr "  %s\n" pa;
11301         pr "let parse_%s = %s\n" name parser_name;
11302         parser_name
11303     | Attribute (name, [field]) ->
11304         let pa = generate_parser field in
11305         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11306         pr "let %s =\n" parser_name;
11307         pr "  %s\n" pa;
11308         pr "let parse_%s = %s\n" name parser_name;
11309         parser_name
11310     | Element (name, fields) ->              (* type name = { fields ... } *)
11311         generate_parser_struct name ([], fields)
11312     | rng ->
11313         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11314
11315   and is_attrs_interleave = function
11316     | [Interleave _] -> true
11317     | Attribute _ :: fields -> is_attrs_interleave fields
11318     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11319     | _ -> false
11320
11321   and get_attrs_interleave = function
11322     | [Interleave fields] -> [], fields
11323     | ((Attribute _) as field) :: fields
11324     | ((Optional (Attribute _)) as field) :: fields ->
11325         let attrs, interleaves = get_attrs_interleave fields in
11326         (field :: attrs), interleaves
11327     | _ -> assert false
11328
11329   and generate_parsers xs =
11330     List.iter (fun x -> ignore (generate_parser x)) xs
11331
11332   and generate_parser_struct name (attrs, interleaves) =
11333     (* Generate parsers for the fields first.  We have to do this
11334      * before printing anything so we are still in BOL context.
11335      *)
11336     let fields = attrs @ interleaves in
11337     let pas = List.map generate_parser fields in
11338
11339     (* Generate an intermediate tuple from all the fields first.
11340      * If the type is just a string + another field, then we will
11341      * return this directly, otherwise it is turned into a record.
11342      *
11343      * RELAX NG note: This code treats <interleave> and plain lists of
11344      * fields the same.  In other words, it doesn't bother enforcing
11345      * any ordering of fields in the XML.
11346      *)
11347     pr "let parse_%s x =\n" name;
11348     pr "  let t = (\n    ";
11349     let comma = ref false in
11350     List.iter (
11351       fun x ->
11352         if !comma then pr ",\n    ";
11353         comma := true;
11354         match x with
11355         | Optional (Attribute (fname, [field])), pa ->
11356             pr "%s x" pa
11357         | Optional (Element (fname, [field])), pa ->
11358             pr "%s (optional_child %S x)" pa fname
11359         | Attribute (fname, [Text]), _ ->
11360             pr "attribute %S x" fname
11361         | (ZeroOrMore _ | OneOrMore _), pa ->
11362             pr "%s x" pa
11363         | Text, pa ->
11364             pr "%s x" pa
11365         | (field, pa) ->
11366             let fname = name_of_field field in
11367             pr "%s (child %S x)" pa fname
11368     ) (List.combine fields pas);
11369     pr "\n  ) in\n";
11370
11371     (match fields with
11372      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11373          pr "  t\n"
11374
11375      | _ ->
11376          pr "  (Obj.magic t : %s)\n" name
11377 (*
11378          List.iter (
11379            function
11380            | (Optional (Attribute (fname, [field])), pa) ->
11381                pr "  %s_%s =\n" name fname;
11382                pr "    %s x;\n" pa
11383            | (Optional (Element (fname, [field])), pa) ->
11384                pr "  %s_%s =\n" name fname;
11385                pr "    (let x = optional_child %S x in\n" fname;
11386                pr "     %s x);\n" pa
11387            | (field, pa) ->
11388                let fname = name_of_field field in
11389                pr "  %s_%s =\n" name fname;
11390                pr "    (let x = child %S x in\n" fname;
11391                pr "     %s x);\n" pa
11392          ) (List.combine fields pas);
11393          pr "}\n"
11394 *)
11395     );
11396     sprintf "parse_%s" name
11397   in
11398
11399   generate_parsers xs
11400
11401 (* Generate ocaml/guestfs_inspector.mli. *)
11402 let generate_ocaml_inspector_mli () =
11403   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11404
11405   pr "\
11406 (** This is an OCaml language binding to the external [virt-inspector]
11407     program.
11408
11409     For more information, please read the man page [virt-inspector(1)].
11410 *)
11411
11412 ";
11413
11414   generate_types grammar;
11415   pr "(** The nested information returned from the {!inspect} function. *)\n";
11416   pr "\n";
11417
11418   pr "\
11419 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11420 (** To inspect a libvirt domain called [name], pass a singleton
11421     list: [inspect [name]].  When using libvirt only, you may
11422     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11423
11424     To inspect a disk image or images, pass a list of the filenames
11425     of the disk images: [inspect filenames]
11426
11427     This function inspects the given guest or disk images and
11428     returns a list of operating system(s) found and a large amount
11429     of information about them.  In the vast majority of cases,
11430     a virtual machine only contains a single operating system.
11431
11432     If the optional [~xml] parameter is given, then this function
11433     skips running the external virt-inspector program and just
11434     parses the given XML directly (which is expected to be XML
11435     produced from a previous run of virt-inspector).  The list of
11436     names and connect URI are ignored in this case.
11437
11438     This function can throw a wide variety of exceptions, for example
11439     if the external virt-inspector program cannot be found, or if
11440     it doesn't generate valid XML.
11441 *)
11442 "
11443
11444 (* Generate ocaml/guestfs_inspector.ml. *)
11445 let generate_ocaml_inspector_ml () =
11446   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11447
11448   pr "open Unix\n";
11449   pr "\n";
11450
11451   generate_types grammar;
11452   pr "\n";
11453
11454   pr "\
11455 (* Misc functions which are used by the parser code below. *)
11456 let first_child = function
11457   | Xml.Element (_, _, c::_) -> c
11458   | Xml.Element (name, _, []) ->
11459       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11460   | Xml.PCData str ->
11461       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11462
11463 let string_child_or_empty = function
11464   | Xml.Element (_, _, [Xml.PCData s]) -> s
11465   | Xml.Element (_, _, []) -> \"\"
11466   | Xml.Element (x, _, _) ->
11467       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11468                 x ^ \" instead\")
11469   | Xml.PCData str ->
11470       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11471
11472 let optional_child name xml =
11473   let children = Xml.children xml in
11474   try
11475     Some (List.find (function
11476                      | Xml.Element (n, _, _) when n = name -> true
11477                      | _ -> false) children)
11478   with
11479     Not_found -> None
11480
11481 let child name xml =
11482   match optional_child name xml with
11483   | Some c -> c
11484   | None ->
11485       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11486
11487 let attribute name xml =
11488   try Xml.attrib xml name
11489   with Xml.No_attribute _ ->
11490     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11491
11492 ";
11493
11494   generate_parsers grammar;
11495   pr "\n";
11496
11497   pr "\
11498 (* Run external virt-inspector, then use parser to parse the XML. *)
11499 let inspect ?connect ?xml names =
11500   let xml =
11501     match xml with
11502     | None ->
11503         if names = [] then invalid_arg \"inspect: no names given\";
11504         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11505           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11506           names in
11507         let cmd = List.map Filename.quote cmd in
11508         let cmd = String.concat \" \" cmd in
11509         let chan = open_process_in cmd in
11510         let xml = Xml.parse_in chan in
11511         (match close_process_in chan with
11512          | WEXITED 0 -> ()
11513          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11514          | WSIGNALED i | WSTOPPED i ->
11515              failwith (\"external virt-inspector command died or stopped on sig \" ^
11516                        string_of_int i)
11517         );
11518         xml
11519     | Some doc ->
11520         Xml.parse_string doc in
11521   parse_operatingsystems xml
11522 "
11523
11524 (* This is used to generate the src/MAX_PROC_NR file which
11525  * contains the maximum procedure number, a surrogate for the
11526  * ABI version number.  See src/Makefile.am for the details.
11527  *)
11528 and generate_max_proc_nr () =
11529   let proc_nrs = List.map (
11530     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11531   ) daemon_functions in
11532
11533   let max_proc_nr = List.fold_left max 0 proc_nrs in
11534
11535   pr "%d\n" max_proc_nr
11536
11537 let output_to filename k =
11538   let filename_new = filename ^ ".new" in
11539   chan := open_out filename_new;
11540   k ();
11541   close_out !chan;
11542   chan := Pervasives.stdout;
11543
11544   (* Is the new file different from the current file? *)
11545   if Sys.file_exists filename && files_equal filename filename_new then
11546     unlink filename_new                 (* same, so skip it *)
11547   else (
11548     (* different, overwrite old one *)
11549     (try chmod filename 0o644 with Unix_error _ -> ());
11550     rename filename_new filename;
11551     chmod filename 0o444;
11552     printf "written %s\n%!" filename;
11553   )
11554
11555 let perror msg = function
11556   | Unix_error (err, _, _) ->
11557       eprintf "%s: %s\n" msg (error_message err)
11558   | exn ->
11559       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11560
11561 (* Main program. *)
11562 let () =
11563   let lock_fd =
11564     try openfile "HACKING" [O_RDWR] 0
11565     with
11566     | Unix_error (ENOENT, _, _) ->
11567         eprintf "\
11568 You are probably running this from the wrong directory.
11569 Run it from the top source directory using the command
11570   src/generator.ml
11571 ";
11572         exit 1
11573     | exn ->
11574         perror "open: HACKING" exn;
11575         exit 1 in
11576
11577   (* Acquire a lock so parallel builds won't try to run the generator
11578    * twice at the same time.  Subsequent builds will wait for the first
11579    * one to finish.  Note the lock is released implicitly when the
11580    * program exits.
11581    *)
11582   (try lockf lock_fd F_LOCK 1
11583    with exn ->
11584      perror "lock: HACKING" exn;
11585      exit 1);
11586
11587   check_functions ();
11588
11589   output_to "src/guestfs_protocol.x" generate_xdr;
11590   output_to "src/guestfs-structs.h" generate_structs_h;
11591   output_to "src/guestfs-actions.h" generate_actions_h;
11592   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11593   output_to "src/guestfs-actions.c" generate_client_actions;
11594   output_to "src/guestfs-bindtests.c" generate_bindtests;
11595   output_to "src/guestfs-structs.pod" generate_structs_pod;
11596   output_to "src/guestfs-actions.pod" generate_actions_pod;
11597   output_to "src/guestfs-availability.pod" generate_availability_pod;
11598   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11599   output_to "src/libguestfs.syms" generate_linker_script;
11600   output_to "daemon/actions.h" generate_daemon_actions_h;
11601   output_to "daemon/stubs.c" generate_daemon_actions;
11602   output_to "daemon/names.c" generate_daemon_names;
11603   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11604   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11605   output_to "capitests/tests.c" generate_tests;
11606   output_to "fish/cmds.c" generate_fish_cmds;
11607   output_to "fish/completion.c" generate_fish_completion;
11608   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11609   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11610   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11611   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11612   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11613   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11614   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11615   output_to "perl/Guestfs.xs" generate_perl_xs;
11616   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11617   output_to "perl/bindtests.pl" generate_perl_bindtests;
11618   output_to "python/guestfs-py.c" generate_python_c;
11619   output_to "python/guestfs.py" generate_python_py;
11620   output_to "python/bindtests.py" generate_python_bindtests;
11621   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11622   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11623   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11624
11625   List.iter (
11626     fun (typ, jtyp) ->
11627       let cols = cols_of_struct typ in
11628       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11629       output_to filename (generate_java_struct jtyp cols);
11630   ) java_structs;
11631
11632   output_to "java/Makefile.inc" generate_java_makefile_inc;
11633   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11634   output_to "java/Bindtests.java" generate_java_bindtests;
11635   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11636   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11637   output_to "csharp/Libguestfs.cs" generate_csharp;
11638
11639   (* Always generate this file last, and unconditionally.  It's used
11640    * by the Makefile to know when we must re-run the generator.
11641    *)
11642   let chan = open_out "src/stamp-generator" in
11643   fprintf chan "1\n";
11644   close_out chan;
11645
11646   printf "generated %d lines of code\n" !lines