daemon: Fix hexdump to work on absolute symbolic links (RHBZ#579608).
[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 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1995    "compute MD5, SHAx or CRC checksum of file",
1996    "\
1997 This call computes the MD5, SHAx or CRC checksum of the
1998 file named C<path>.
1999
2000 The type of checksum to compute is given by the C<csumtype>
2001 parameter which must have one of the following values:
2002
2003 =over 4
2004
2005 =item C<crc>
2006
2007 Compute the cyclic redundancy check (CRC) specified by POSIX
2008 for the C<cksum> command.
2009
2010 =item C<md5>
2011
2012 Compute the MD5 hash (using the C<md5sum> program).
2013
2014 =item C<sha1>
2015
2016 Compute the SHA1 hash (using the C<sha1sum> program).
2017
2018 =item C<sha224>
2019
2020 Compute the SHA224 hash (using the C<sha224sum> program).
2021
2022 =item C<sha256>
2023
2024 Compute the SHA256 hash (using the C<sha256sum> program).
2025
2026 =item C<sha384>
2027
2028 Compute the SHA384 hash (using the C<sha384sum> program).
2029
2030 =item C<sha512>
2031
2032 Compute the SHA512 hash (using the C<sha512sum> program).
2033
2034 =back
2035
2036 The checksum is returned as a printable string.
2037
2038 To get the checksum for a device, use C<guestfs_checksum_device>.
2039
2040 To get the checksums for many files, use C<guestfs_checksums_out>.");
2041
2042   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2043    [InitBasicFS, Always, TestOutput (
2044       [["tar_in"; "../images/helloworld.tar"; "/"];
2045        ["cat"; "/hello"]], "hello\n")],
2046    "unpack tarfile to directory",
2047    "\
2048 This command uploads and unpacks local file C<tarfile> (an
2049 I<uncompressed> tar file) into C<directory>.
2050
2051 To upload a compressed tarball, use C<guestfs_tgz_in>
2052 or C<guestfs_txz_in>.");
2053
2054   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2055    [],
2056    "pack directory into tarfile",
2057    "\
2058 This command packs the contents of C<directory> and downloads
2059 it to local file C<tarfile>.
2060
2061 To download a compressed tarball, use C<guestfs_tgz_out>
2062 or C<guestfs_txz_out>.");
2063
2064   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2065    [InitBasicFS, Always, TestOutput (
2066       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2067        ["cat"; "/hello"]], "hello\n")],
2068    "unpack compressed tarball to directory",
2069    "\
2070 This command uploads and unpacks local file C<tarball> (a
2071 I<gzip compressed> tar file) into C<directory>.
2072
2073 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2074
2075   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2076    [],
2077    "pack directory into compressed tarball",
2078    "\
2079 This command packs the contents of C<directory> and downloads
2080 it to local file C<tarball>.
2081
2082 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2083
2084   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2085    [InitBasicFS, Always, TestLastFail (
2086       [["umount"; "/"];
2087        ["mount_ro"; "/dev/sda1"; "/"];
2088        ["touch"; "/new"]]);
2089     InitBasicFS, Always, TestOutput (
2090       [["write_file"; "/new"; "data"; "0"];
2091        ["umount"; "/"];
2092        ["mount_ro"; "/dev/sda1"; "/"];
2093        ["cat"; "/new"]], "data")],
2094    "mount a guest disk, read-only",
2095    "\
2096 This is the same as the C<guestfs_mount> command, but it
2097 mounts the filesystem with the read-only (I<-o ro>) flag.");
2098
2099   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2100    [],
2101    "mount a guest disk with mount options",
2102    "\
2103 This is the same as the C<guestfs_mount> command, but it
2104 allows you to set the mount options as for the
2105 L<mount(8)> I<-o> flag.
2106
2107 If the C<options> parameter is an empty string, then
2108 no options are passed (all options default to whatever
2109 the filesystem uses).");
2110
2111   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2112    [],
2113    "mount a guest disk with mount options and vfstype",
2114    "\
2115 This is the same as the C<guestfs_mount> command, but it
2116 allows you to set both the mount options and the vfstype
2117 as for the L<mount(8)> I<-o> and I<-t> flags.");
2118
2119   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2120    [],
2121    "debugging and internals",
2122    "\
2123 The C<guestfs_debug> command exposes some internals of
2124 C<guestfsd> (the guestfs daemon) that runs inside the
2125 qemu subprocess.
2126
2127 There is no comprehensive help for this command.  You have
2128 to look at the file C<daemon/debug.c> in the libguestfs source
2129 to find out what you can do.");
2130
2131   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2132    [InitEmpty, Always, TestOutputList (
2133       [["part_disk"; "/dev/sda"; "mbr"];
2134        ["pvcreate"; "/dev/sda1"];
2135        ["vgcreate"; "VG"; "/dev/sda1"];
2136        ["lvcreate"; "LV1"; "VG"; "50"];
2137        ["lvcreate"; "LV2"; "VG"; "50"];
2138        ["lvremove"; "/dev/VG/LV1"];
2139        ["lvs"]], ["/dev/VG/LV2"]);
2140     InitEmpty, Always, TestOutputList (
2141       [["part_disk"; "/dev/sda"; "mbr"];
2142        ["pvcreate"; "/dev/sda1"];
2143        ["vgcreate"; "VG"; "/dev/sda1"];
2144        ["lvcreate"; "LV1"; "VG"; "50"];
2145        ["lvcreate"; "LV2"; "VG"; "50"];
2146        ["lvremove"; "/dev/VG"];
2147        ["lvs"]], []);
2148     InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["lvremove"; "/dev/VG"];
2155        ["vgs"]], ["VG"])],
2156    "remove an LVM logical volume",
2157    "\
2158 Remove an LVM logical volume C<device>, where C<device> is
2159 the path to the LV, such as C</dev/VG/LV>.
2160
2161 You can also remove all LVs in a volume group by specifying
2162 the VG name, C</dev/VG>.");
2163
2164   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2165    [InitEmpty, Always, TestOutputList (
2166       [["part_disk"; "/dev/sda"; "mbr"];
2167        ["pvcreate"; "/dev/sda1"];
2168        ["vgcreate"; "VG"; "/dev/sda1"];
2169        ["lvcreate"; "LV1"; "VG"; "50"];
2170        ["lvcreate"; "LV2"; "VG"; "50"];
2171        ["vgremove"; "VG"];
2172        ["lvs"]], []);
2173     InitEmpty, Always, TestOutputList (
2174       [["part_disk"; "/dev/sda"; "mbr"];
2175        ["pvcreate"; "/dev/sda1"];
2176        ["vgcreate"; "VG"; "/dev/sda1"];
2177        ["lvcreate"; "LV1"; "VG"; "50"];
2178        ["lvcreate"; "LV2"; "VG"; "50"];
2179        ["vgremove"; "VG"];
2180        ["vgs"]], [])],
2181    "remove an LVM volume group",
2182    "\
2183 Remove an LVM volume group C<vgname>, (for example C<VG>).
2184
2185 This also forcibly removes all logical volumes in the volume
2186 group (if any).");
2187
2188   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2189    [InitEmpty, Always, TestOutputListOfDevices (
2190       [["part_disk"; "/dev/sda"; "mbr"];
2191        ["pvcreate"; "/dev/sda1"];
2192        ["vgcreate"; "VG"; "/dev/sda1"];
2193        ["lvcreate"; "LV1"; "VG"; "50"];
2194        ["lvcreate"; "LV2"; "VG"; "50"];
2195        ["vgremove"; "VG"];
2196        ["pvremove"; "/dev/sda1"];
2197        ["lvs"]], []);
2198     InitEmpty, Always, TestOutputListOfDevices (
2199       [["part_disk"; "/dev/sda"; "mbr"];
2200        ["pvcreate"; "/dev/sda1"];
2201        ["vgcreate"; "VG"; "/dev/sda1"];
2202        ["lvcreate"; "LV1"; "VG"; "50"];
2203        ["lvcreate"; "LV2"; "VG"; "50"];
2204        ["vgremove"; "VG"];
2205        ["pvremove"; "/dev/sda1"];
2206        ["vgs"]], []);
2207     InitEmpty, Always, TestOutputListOfDevices (
2208       [["part_disk"; "/dev/sda"; "mbr"];
2209        ["pvcreate"; "/dev/sda1"];
2210        ["vgcreate"; "VG"; "/dev/sda1"];
2211        ["lvcreate"; "LV1"; "VG"; "50"];
2212        ["lvcreate"; "LV2"; "VG"; "50"];
2213        ["vgremove"; "VG"];
2214        ["pvremove"; "/dev/sda1"];
2215        ["pvs"]], [])],
2216    "remove an LVM physical volume",
2217    "\
2218 This wipes a physical volume C<device> so that LVM will no longer
2219 recognise it.
2220
2221 The implementation uses the C<pvremove> command which refuses to
2222 wipe physical volumes that contain any volume groups, so you have
2223 to remove those first.");
2224
2225   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2226    [InitBasicFS, Always, TestOutput (
2227       [["set_e2label"; "/dev/sda1"; "testlabel"];
2228        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2229    "set the ext2/3/4 filesystem label",
2230    "\
2231 This sets the ext2/3/4 filesystem label of the filesystem on
2232 C<device> to C<label>.  Filesystem labels are limited to
2233 16 characters.
2234
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2236 to return the existing label on a filesystem.");
2237
2238   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2239    [],
2240    "get the ext2/3/4 filesystem label",
2241    "\
2242 This returns the ext2/3/4 filesystem label of the filesystem on
2243 C<device>.");
2244
2245   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2246    (let uuid = uuidgen () in
2247     [InitBasicFS, Always, TestOutput (
2248        [["set_e2uuid"; "/dev/sda1"; uuid];
2249         ["get_e2uuid"; "/dev/sda1"]], uuid);
2250      InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; "clear"];
2252         ["get_e2uuid"; "/dev/sda1"]], "");
2253      (* We can't predict what UUIDs will be, so just check the commands run. *)
2254      InitBasicFS, Always, TestRun (
2255        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2256      InitBasicFS, Always, TestRun (
2257        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2258    "set the ext2/3/4 filesystem UUID",
2259    "\
2260 This sets the ext2/3/4 filesystem UUID of the filesystem on
2261 C<device> to C<uuid>.  The format of the UUID and alternatives
2262 such as C<clear>, C<random> and C<time> are described in the
2263 L<tune2fs(8)> manpage.
2264
2265 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2266 to return the existing UUID of a filesystem.");
2267
2268   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2269    [],
2270    "get the ext2/3/4 filesystem UUID",
2271    "\
2272 This returns the ext2/3/4 filesystem UUID of the filesystem on
2273 C<device>.");
2274
2275   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2276    [InitBasicFS, Always, TestOutputInt (
2277       [["umount"; "/dev/sda1"];
2278        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2279     InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["zero"; "/dev/sda1"];
2282        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2283    "run the filesystem checker",
2284    "\
2285 This runs the filesystem checker (fsck) on C<device> which
2286 should have filesystem type C<fstype>.
2287
2288 The returned integer is the status.  See L<fsck(8)> for the
2289 list of status codes from C<fsck>.
2290
2291 Notes:
2292
2293 =over 4
2294
2295 =item *
2296
2297 Multiple status codes can be summed together.
2298
2299 =item *
2300
2301 A non-zero return code can mean \"success\", for example if
2302 errors have been corrected on the filesystem.
2303
2304 =item *
2305
2306 Checking or repairing NTFS volumes is not supported
2307 (by linux-ntfs).
2308
2309 =back
2310
2311 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2312
2313   ("zero", (RErr, [Device "device"]), 85, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["umount"; "/dev/sda1"];
2316        ["zero"; "/dev/sda1"];
2317        ["file"; "/dev/sda1"]], "data")],
2318    "write zeroes to the device",
2319    "\
2320 This command writes zeroes over the first few blocks of C<device>.
2321
2322 How many blocks are zeroed isn't specified (but it's I<not> enough
2323 to securely wipe the device).  It should be sufficient to remove
2324 any partition tables, filesystem superblocks and so on.
2325
2326 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2327
2328   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2329    (* Test disabled because grub-install incompatible with virtio-blk driver.
2330     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2331     *)
2332    [InitBasicFS, Disabled, TestOutputTrue (
2333       [["grub_install"; "/"; "/dev/sda1"];
2334        ["is_dir"; "/boot"]])],
2335    "install GRUB",
2336    "\
2337 This command installs GRUB (the Grand Unified Bootloader) on
2338 C<device>, with the root directory being C<root>.");
2339
2340   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2341    [InitBasicFS, Always, TestOutput (
2342       [["write_file"; "/old"; "file content"; "0"];
2343        ["cp"; "/old"; "/new"];
2344        ["cat"; "/new"]], "file content");
2345     InitBasicFS, Always, TestOutputTrue (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["cp"; "/old"; "/new"];
2348        ["is_file"; "/old"]]);
2349     InitBasicFS, Always, TestOutput (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mkdir"; "/dir"];
2352        ["cp"; "/old"; "/dir/new"];
2353        ["cat"; "/dir/new"]], "file content")],
2354    "copy a file",
2355    "\
2356 This copies a file from C<src> to C<dest> where C<dest> is
2357 either a destination filename or destination directory.");
2358
2359   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2360    [InitBasicFS, Always, TestOutput (
2361       [["mkdir"; "/olddir"];
2362        ["mkdir"; "/newdir"];
2363        ["write_file"; "/olddir/file"; "file content"; "0"];
2364        ["cp_a"; "/olddir"; "/newdir"];
2365        ["cat"; "/newdir/olddir/file"]], "file content")],
2366    "copy a file or directory recursively",
2367    "\
2368 This copies a file or directory from C<src> to C<dest>
2369 recursively using the C<cp -a> command.");
2370
2371   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2372    [InitBasicFS, Always, TestOutput (
2373       [["write_file"; "/old"; "file content"; "0"];
2374        ["mv"; "/old"; "/new"];
2375        ["cat"; "/new"]], "file content");
2376     InitBasicFS, Always, TestOutputFalse (
2377       [["write_file"; "/old"; "file content"; "0"];
2378        ["mv"; "/old"; "/new"];
2379        ["is_file"; "/old"]])],
2380    "move a file",
2381    "\
2382 This moves a file from C<src> to C<dest> where C<dest> is
2383 either a destination filename or destination directory.");
2384
2385   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2386    [InitEmpty, Always, TestRun (
2387       [["drop_caches"; "3"]])],
2388    "drop kernel page cache, dentries and inodes",
2389    "\
2390 This instructs the guest kernel to drop its page cache,
2391 and/or dentries and inode caches.  The parameter C<whattodrop>
2392 tells the kernel what precisely to drop, see
2393 L<http://linux-mm.org/Drop_Caches>
2394
2395 Setting C<whattodrop> to 3 should drop everything.
2396
2397 This automatically calls L<sync(2)> before the operation,
2398 so that the maximum guest memory is freed.");
2399
2400   ("dmesg", (RString "kmsgs", []), 91, [],
2401    [InitEmpty, Always, TestRun (
2402       [["dmesg"]])],
2403    "return kernel messages",
2404    "\
2405 This returns the kernel messages (C<dmesg> output) from
2406 the guest kernel.  This is sometimes useful for extended
2407 debugging of problems.
2408
2409 Another way to get the same information is to enable
2410 verbose messages with C<guestfs_set_verbose> or by setting
2411 the environment variable C<LIBGUESTFS_DEBUG=1> before
2412 running the program.");
2413
2414   ("ping_daemon", (RErr, []), 92, [],
2415    [InitEmpty, Always, TestRun (
2416       [["ping_daemon"]])],
2417    "ping the guest daemon",
2418    "\
2419 This is a test probe into the guestfs daemon running inside
2420 the qemu subprocess.  Calling this function checks that the
2421 daemon responds to the ping message, without affecting the daemon
2422 or attached block device(s) in any other way.");
2423
2424   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2425    [InitBasicFS, Always, TestOutputTrue (
2426       [["write_file"; "/file1"; "contents of a file"; "0"];
2427        ["cp"; "/file1"; "/file2"];
2428        ["equal"; "/file1"; "/file2"]]);
2429     InitBasicFS, Always, TestOutputFalse (
2430       [["write_file"; "/file1"; "contents of a file"; "0"];
2431        ["write_file"; "/file2"; "contents of another file"; "0"];
2432        ["equal"; "/file1"; "/file2"]]);
2433     InitBasicFS, Always, TestLastFail (
2434       [["equal"; "/file1"; "/file2"]])],
2435    "test if two files have equal contents",
2436    "\
2437 This compares the two files C<file1> and C<file2> and returns
2438 true if their content is exactly equal, or false otherwise.
2439
2440 The external L<cmp(1)> program is used for the comparison.");
2441
2442   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2443    [InitISOFS, Always, TestOutputList (
2444       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2445     InitISOFS, Always, TestOutputList (
2446       [["strings"; "/empty"]], [])],
2447    "print the printable strings in a file",
2448    "\
2449 This runs the L<strings(1)> command on a file and returns
2450 the list of printable strings found.");
2451
2452   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2453    [InitISOFS, Always, TestOutputList (
2454       [["strings_e"; "b"; "/known-5"]], []);
2455     InitBasicFS, Disabled, TestOutputList (
2456       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2457        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2458    "print the printable strings in a file",
2459    "\
2460 This is like the C<guestfs_strings> command, but allows you to
2461 specify the encoding.
2462
2463 See the L<strings(1)> manpage for the full list of encodings.
2464
2465 Commonly useful encodings are C<l> (lower case L) which will
2466 show strings inside Windows/x86 files.
2467
2468 The returned strings are transcoded to UTF-8.");
2469
2470   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2471    [InitISOFS, Always, TestOutput (
2472       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2473     (* Test for RHBZ#501888c2 regression which caused large hexdump
2474      * commands to segfault.
2475      *)
2476     InitISOFS, Always, TestRun (
2477       [["hexdump"; "/100krandom"]]);
2478     (* Test for RHBZ#579608, absolute symbolic links. *)
2479     InitISOFS, Always, TestRun (
2480       [["hexdump"; "/abssymlink"]])],
2481    "dump a file in hexadecimal",
2482    "\
2483 This runs C<hexdump -C> on the given C<path>.  The result is
2484 the human-readable, canonical hex dump of the file.");
2485
2486   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2487    [InitNone, Always, TestOutput (
2488       [["part_disk"; "/dev/sda"; "mbr"];
2489        ["mkfs"; "ext3"; "/dev/sda1"];
2490        ["mount_options"; ""; "/dev/sda1"; "/"];
2491        ["write_file"; "/new"; "test file"; "0"];
2492        ["umount"; "/dev/sda1"];
2493        ["zerofree"; "/dev/sda1"];
2494        ["mount_options"; ""; "/dev/sda1"; "/"];
2495        ["cat"; "/new"]], "test file")],
2496    "zero unused inodes and disk blocks on ext2/3 filesystem",
2497    "\
2498 This runs the I<zerofree> program on C<device>.  This program
2499 claims to zero unused inodes and disk blocks on an ext2/3
2500 filesystem, thus making it possible to compress the filesystem
2501 more effectively.
2502
2503 You should B<not> run this program if the filesystem is
2504 mounted.
2505
2506 It is possible that using this program can damage the filesystem
2507 or data on the filesystem.");
2508
2509   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2510    [],
2511    "resize an LVM physical volume",
2512    "\
2513 This resizes (expands or shrinks) an existing LVM physical
2514 volume to match the new size of the underlying device.");
2515
2516   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2517                        Int "cyls"; Int "heads"; Int "sectors";
2518                        String "line"]), 99, [DangerWillRobinson],
2519    [],
2520    "modify a single partition on a block device",
2521    "\
2522 This runs L<sfdisk(8)> option to modify just the single
2523 partition C<n> (note: C<n> counts from 1).
2524
2525 For other parameters, see C<guestfs_sfdisk>.  You should usually
2526 pass C<0> for the cyls/heads/sectors parameters.
2527
2528 See also: C<guestfs_part_add>");
2529
2530   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2531    [],
2532    "display the partition table",
2533    "\
2534 This displays the partition table on C<device>, in the
2535 human-readable output of the L<sfdisk(8)> command.  It is
2536 not intended to be parsed.
2537
2538 See also: C<guestfs_part_list>");
2539
2540   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2541    [],
2542    "display the kernel geometry",
2543    "\
2544 This displays the kernel's idea of the geometry of C<device>.
2545
2546 The result is in human-readable format, and not designed to
2547 be parsed.");
2548
2549   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2550    [],
2551    "display the disk geometry from the partition table",
2552    "\
2553 This displays the disk geometry of C<device> read from the
2554 partition table.  Especially in the case where the underlying
2555 block device has been resized, this can be different from the
2556 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2557
2558 The result is in human-readable format, and not designed to
2559 be parsed.");
2560
2561   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2562    [],
2563    "activate or deactivate all volume groups",
2564    "\
2565 This command activates or (if C<activate> is false) deactivates
2566 all logical volumes in all volume groups.
2567 If activated, then they are made known to the
2568 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2569 then those devices disappear.
2570
2571 This command is the same as running C<vgchange -a y|n>");
2572
2573   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2574    [],
2575    "activate or deactivate some volume groups",
2576    "\
2577 This command activates or (if C<activate> is false) deactivates
2578 all logical volumes in the listed volume groups C<volgroups>.
2579 If activated, then they are made known to the
2580 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2581 then those devices disappear.
2582
2583 This command is the same as running C<vgchange -a y|n volgroups...>
2584
2585 Note that if C<volgroups> is an empty list then B<all> volume groups
2586 are activated or deactivated.");
2587
2588   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2589    [InitNone, Always, TestOutput (
2590       [["part_disk"; "/dev/sda"; "mbr"];
2591        ["pvcreate"; "/dev/sda1"];
2592        ["vgcreate"; "VG"; "/dev/sda1"];
2593        ["lvcreate"; "LV"; "VG"; "10"];
2594        ["mkfs"; "ext2"; "/dev/VG/LV"];
2595        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2596        ["write_file"; "/new"; "test content"; "0"];
2597        ["umount"; "/"];
2598        ["lvresize"; "/dev/VG/LV"; "20"];
2599        ["e2fsck_f"; "/dev/VG/LV"];
2600        ["resize2fs"; "/dev/VG/LV"];
2601        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2602        ["cat"; "/new"]], "test content");
2603     InitNone, Always, TestRun (
2604       (* Make an LV smaller to test RHBZ#587484. *)
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "20"];
2609        ["lvresize"; "/dev/VG/LV"; "10"]])],
2610    "resize an LVM logical volume",
2611    "\
2612 This resizes (expands or shrinks) an existing LVM logical
2613 volume to C<mbytes>.  When reducing, data in the reduced part
2614 is lost.");
2615
2616   ("resize2fs", (RErr, [Device "device"]), 106, [],
2617    [], (* lvresize tests this *)
2618    "resize an ext2/ext3 filesystem",
2619    "\
2620 This resizes an ext2 or ext3 filesystem to match the size of
2621 the underlying device.
2622
2623 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2624 on the C<device> before calling this command.  For unknown reasons
2625 C<resize2fs> sometimes gives an error about this and sometimes not.
2626 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2627 calling this function.");
2628
2629   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2630    [InitBasicFS, Always, TestOutputList (
2631       [["find"; "/"]], ["lost+found"]);
2632     InitBasicFS, Always, TestOutputList (
2633       [["touch"; "/a"];
2634        ["mkdir"; "/b"];
2635        ["touch"; "/b/c"];
2636        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2637     InitBasicFS, Always, TestOutputList (
2638       [["mkdir_p"; "/a/b/c"];
2639        ["touch"; "/a/b/c/d"];
2640        ["find"; "/a/b/"]], ["c"; "c/d"])],
2641    "find all files and directories",
2642    "\
2643 This command lists out all files and directories, recursively,
2644 starting at C<directory>.  It is essentially equivalent to
2645 running the shell command C<find directory -print> but some
2646 post-processing happens on the output, described below.
2647
2648 This returns a list of strings I<without any prefix>.  Thus
2649 if the directory structure was:
2650
2651  /tmp/a
2652  /tmp/b
2653  /tmp/c/d
2654
2655 then the returned list from C<guestfs_find> C</tmp> would be
2656 4 elements:
2657
2658  a
2659  b
2660  c
2661  c/d
2662
2663 If C<directory> is not a directory, then this command returns
2664 an error.
2665
2666 The returned list is sorted.
2667
2668 See also C<guestfs_find0>.");
2669
2670   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2671    [], (* lvresize tests this *)
2672    "check an ext2/ext3 filesystem",
2673    "\
2674 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2675 filesystem checker on C<device>, noninteractively (C<-p>),
2676 even if the filesystem appears to be clean (C<-f>).
2677
2678 This command is only needed because of C<guestfs_resize2fs>
2679 (q.v.).  Normally you should use C<guestfs_fsck>.");
2680
2681   ("sleep", (RErr, [Int "secs"]), 109, [],
2682    [InitNone, Always, TestRun (
2683       [["sleep"; "1"]])],
2684    "sleep for some seconds",
2685    "\
2686 Sleep for C<secs> seconds.");
2687
2688   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2689    [InitNone, Always, TestOutputInt (
2690       [["part_disk"; "/dev/sda"; "mbr"];
2691        ["mkfs"; "ntfs"; "/dev/sda1"];
2692        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2693     InitNone, Always, TestOutputInt (
2694       [["part_disk"; "/dev/sda"; "mbr"];
2695        ["mkfs"; "ext2"; "/dev/sda1"];
2696        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2697    "probe NTFS volume",
2698    "\
2699 This command runs the L<ntfs-3g.probe(8)> command which probes
2700 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2701 be mounted read-write, and some cannot be mounted at all).
2702
2703 C<rw> is a boolean flag.  Set it to true if you want to test
2704 if the volume can be mounted read-write.  Set it to false if
2705 you want to test if the volume can be mounted read-only.
2706
2707 The return value is an integer which C<0> if the operation
2708 would succeed, or some non-zero value documented in the
2709 L<ntfs-3g.probe(8)> manual page.");
2710
2711   ("sh", (RString "output", [String "command"]), 111, [],
2712    [], (* XXX needs tests *)
2713    "run a command via the shell",
2714    "\
2715 This call runs a command from the guest filesystem via the
2716 guest's C</bin/sh>.
2717
2718 This is like C<guestfs_command>, but passes the command to:
2719
2720  /bin/sh -c \"command\"
2721
2722 Depending on the guest's shell, this usually results in
2723 wildcards being expanded, shell expressions being interpolated
2724 and so on.
2725
2726 All the provisos about C<guestfs_command> apply to this call.");
2727
2728   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2729    [], (* XXX needs tests *)
2730    "run a command via the shell returning lines",
2731    "\
2732 This is the same as C<guestfs_sh>, but splits the result
2733 into a list of lines.
2734
2735 See also: C<guestfs_command_lines>");
2736
2737   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2738    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2739     * code in stubs.c, since all valid glob patterns must start with "/".
2740     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2741     *)
2742    [InitBasicFS, Always, TestOutputList (
2743       [["mkdir_p"; "/a/b/c"];
2744        ["touch"; "/a/b/c/d"];
2745        ["touch"; "/a/b/c/e"];
2746        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2747     InitBasicFS, Always, TestOutputList (
2748       [["mkdir_p"; "/a/b/c"];
2749        ["touch"; "/a/b/c/d"];
2750        ["touch"; "/a/b/c/e"];
2751        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2752     InitBasicFS, Always, TestOutputList (
2753       [["mkdir_p"; "/a/b/c"];
2754        ["touch"; "/a/b/c/d"];
2755        ["touch"; "/a/b/c/e"];
2756        ["glob_expand"; "/a/*/x/*"]], [])],
2757    "expand a wildcard path",
2758    "\
2759 This command searches for all the pathnames matching
2760 C<pattern> according to the wildcard expansion rules
2761 used by the shell.
2762
2763 If no paths match, then this returns an empty list
2764 (note: not an error).
2765
2766 It is just a wrapper around the C L<glob(3)> function
2767 with flags C<GLOB_MARK|GLOB_BRACE>.
2768 See that manual page for more details.");
2769
2770   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2771    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2772       [["scrub_device"; "/dev/sdc"]])],
2773    "scrub (securely wipe) a device",
2774    "\
2775 This command writes patterns over C<device> to make data retrieval
2776 more difficult.
2777
2778 It is an interface to the L<scrub(1)> program.  See that
2779 manual page for more details.");
2780
2781   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2782    [InitBasicFS, Always, TestRun (
2783       [["write_file"; "/file"; "content"; "0"];
2784        ["scrub_file"; "/file"]])],
2785    "scrub (securely wipe) a file",
2786    "\
2787 This command writes patterns over a file to make data retrieval
2788 more difficult.
2789
2790 The file is I<removed> after scrubbing.
2791
2792 It is an interface to the L<scrub(1)> program.  See that
2793 manual page for more details.");
2794
2795   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2796    [], (* XXX needs testing *)
2797    "scrub (securely wipe) free space",
2798    "\
2799 This command creates the directory C<dir> and then fills it
2800 with files until the filesystem is full, and scrubs the files
2801 as for C<guestfs_scrub_file>, and deletes them.
2802 The intention is to scrub any free space on the partition
2803 containing C<dir>.
2804
2805 It is an interface to the L<scrub(1)> program.  See that
2806 manual page for more details.");
2807
2808   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2809    [InitBasicFS, Always, TestRun (
2810       [["mkdir"; "/tmp"];
2811        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2812    "create a temporary directory",
2813    "\
2814 This command creates a temporary directory.  The
2815 C<template> parameter should be a full pathname for the
2816 temporary directory name with the final six characters being
2817 \"XXXXXX\".
2818
2819 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2820 the second one being suitable for Windows filesystems.
2821
2822 The name of the temporary directory that was created
2823 is returned.
2824
2825 The temporary directory is created with mode 0700
2826 and is owned by root.
2827
2828 The caller is responsible for deleting the temporary
2829 directory and its contents after use.
2830
2831 See also: L<mkdtemp(3)>");
2832
2833   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2834    [InitISOFS, Always, TestOutputInt (
2835       [["wc_l"; "/10klines"]], 10000)],
2836    "count lines in a file",
2837    "\
2838 This command counts the lines in a file, using the
2839 C<wc -l> external command.");
2840
2841   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2842    [InitISOFS, Always, TestOutputInt (
2843       [["wc_w"; "/10klines"]], 10000)],
2844    "count words in a file",
2845    "\
2846 This command counts the words in a file, using the
2847 C<wc -w> external command.");
2848
2849   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2850    [InitISOFS, Always, TestOutputInt (
2851       [["wc_c"; "/100kallspaces"]], 102400)],
2852    "count characters in a file",
2853    "\
2854 This command counts the characters in a file, using the
2855 C<wc -c> external command.");
2856
2857   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2858    [InitISOFS, Always, TestOutputList (
2859       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2860    "return first 10 lines of a file",
2861    "\
2862 This command returns up to the first 10 lines of a file as
2863 a list of strings.");
2864
2865   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2866    [InitISOFS, Always, TestOutputList (
2867       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2868     InitISOFS, Always, TestOutputList (
2869       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2870     InitISOFS, Always, TestOutputList (
2871       [["head_n"; "0"; "/10klines"]], [])],
2872    "return first N lines of a file",
2873    "\
2874 If the parameter C<nrlines> is a positive number, this returns the first
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>, excluding the last C<nrlines> lines.
2879
2880 If the parameter C<nrlines> is zero, this returns an empty list.");
2881
2882   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2883    [InitISOFS, Always, TestOutputList (
2884       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2885    "return last 10 lines of a file",
2886    "\
2887 This command returns up to the last 10 lines of a file as
2888 a list of strings.");
2889
2890   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2891    [InitISOFS, Always, TestOutputList (
2892       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2893     InitISOFS, Always, TestOutputList (
2894       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2895     InitISOFS, Always, TestOutputList (
2896       [["tail_n"; "0"; "/10klines"]], [])],
2897    "return last N lines of a file",
2898    "\
2899 If the parameter C<nrlines> is a positive number, this returns the last
2900 C<nrlines> lines of the file C<path>.
2901
2902 If the parameter C<nrlines> is a negative number, this returns lines
2903 from the file C<path>, starting with the C<-nrlines>th line.
2904
2905 If the parameter C<nrlines> is zero, this returns an empty list.");
2906
2907   ("df", (RString "output", []), 125, [],
2908    [], (* XXX Tricky to test because it depends on the exact format
2909         * of the 'df' command and other imponderables.
2910         *)
2911    "report file system disk space usage",
2912    "\
2913 This command runs the C<df> command to report disk space used.
2914
2915 This command is mostly useful for interactive sessions.  It
2916 is I<not> intended that you try to parse the output string.
2917 Use C<statvfs> from programs.");
2918
2919   ("df_h", (RString "output", []), 126, [],
2920    [], (* XXX Tricky to test because it depends on the exact format
2921         * of the 'df' command and other imponderables.
2922         *)
2923    "report file system disk space usage (human readable)",
2924    "\
2925 This command runs the C<df -h> command to report disk space used
2926 in human-readable format.
2927
2928 This command is mostly useful for interactive sessions.  It
2929 is I<not> intended that you try to parse the output string.
2930 Use C<statvfs> from programs.");
2931
2932   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2933    [InitISOFS, Always, TestOutputInt (
2934       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2935    "estimate file space usage",
2936    "\
2937 This command runs the C<du -s> command to estimate file space
2938 usage for C<path>.
2939
2940 C<path> can be a file or a directory.  If C<path> is a directory
2941 then the estimate includes the contents of the directory and all
2942 subdirectories (recursively).
2943
2944 The result is the estimated size in I<kilobytes>
2945 (ie. units of 1024 bytes).");
2946
2947   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2948    [InitISOFS, Always, TestOutputList (
2949       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2950    "list files in an initrd",
2951    "\
2952 This command lists out files contained in an initrd.
2953
2954 The files are listed without any initial C</> character.  The
2955 files are listed in the order they appear (not necessarily
2956 alphabetical).  Directory names are listed as separate items.
2957
2958 Old Linux kernels (2.4 and earlier) used a compressed ext2
2959 filesystem as initrd.  We I<only> support the newer initramfs
2960 format (compressed cpio files).");
2961
2962   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2963    [],
2964    "mount a file using the loop device",
2965    "\
2966 This command lets you mount C<file> (a filesystem image
2967 in a file) on a mount point.  It is entirely equivalent to
2968 the command C<mount -o loop file mountpoint>.");
2969
2970   ("mkswap", (RErr, [Device "device"]), 130, [],
2971    [InitEmpty, Always, TestRun (
2972       [["part_disk"; "/dev/sda"; "mbr"];
2973        ["mkswap"; "/dev/sda1"]])],
2974    "create a swap partition",
2975    "\
2976 Create a swap partition on C<device>.");
2977
2978   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2979    [InitEmpty, Always, TestRun (
2980       [["part_disk"; "/dev/sda"; "mbr"];
2981        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2982    "create a swap partition with a label",
2983    "\
2984 Create a swap partition on C<device> with label C<label>.
2985
2986 Note that you cannot attach a swap label to a block device
2987 (eg. C</dev/sda>), just to a partition.  This appears to be
2988 a limitation of the kernel or swap tools.");
2989
2990   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2991    (let uuid = uuidgen () in
2992     [InitEmpty, Always, TestRun (
2993        [["part_disk"; "/dev/sda"; "mbr"];
2994         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2995    "create a swap partition with an explicit UUID",
2996    "\
2997 Create a swap partition on C<device> with UUID C<uuid>.");
2998
2999   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3000    [InitBasicFS, Always, TestOutputStruct (
3001       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3002        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3004     InitBasicFS, Always, TestOutputStruct (
3005       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3006        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3007    "make block, character or FIFO devices",
3008    "\
3009 This call creates block or character special devices, or
3010 named pipes (FIFOs).
3011
3012 The C<mode> parameter should be the mode, using the standard
3013 constants.  C<devmajor> and C<devminor> are the
3014 device major and minor numbers, only used when creating block
3015 and character special devices.
3016
3017 Note that, just like L<mknod(2)>, the mode must be bitwise
3018 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3019 just creates a regular file).  These constants are
3020 available in the standard Linux header files, or you can use
3021 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3022 which are wrappers around this command which bitwise OR
3023 in the appropriate constant for you.
3024
3025 The mode actually set is affected by the umask.");
3026
3027   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3028    [InitBasicFS, Always, TestOutputStruct (
3029       [["mkfifo"; "0o777"; "/node"];
3030        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3031    "make FIFO (named pipe)",
3032    "\
3033 This call creates a FIFO (named pipe) called C<path> with
3034 mode C<mode>.  It is just a convenient wrapper around
3035 C<guestfs_mknod>.
3036
3037 The mode actually set is affected by the umask.");
3038
3039   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3040    [InitBasicFS, Always, TestOutputStruct (
3041       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3042        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3043    "make block device node",
3044    "\
3045 This call creates a block device node called C<path> with
3046 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3047 It is just a convenient wrapper around C<guestfs_mknod>.
3048
3049 The mode actually set is affected by the umask.");
3050
3051   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3052    [InitBasicFS, Always, TestOutputStruct (
3053       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3054        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3055    "make char device node",
3056    "\
3057 This call creates a char device node called C<path> with
3058 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3059 It is just a convenient wrapper around C<guestfs_mknod>.
3060
3061 The mode actually set is affected by the umask.");
3062
3063   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3064    [InitEmpty, Always, TestOutputInt (
3065       [["umask"; "0o22"]], 0o22)],
3066    "set file mode creation mask (umask)",
3067    "\
3068 This function sets the mask used for creating new files and
3069 device nodes to C<mask & 0777>.
3070
3071 Typical umask values would be C<022> which creates new files
3072 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3073 C<002> which creates new files with permissions like
3074 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3075
3076 The default umask is C<022>.  This is important because it
3077 means that directories and device nodes will be created with
3078 C<0644> or C<0755> mode even if you specify C<0777>.
3079
3080 See also C<guestfs_get_umask>,
3081 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3082
3083 This call returns the previous umask.");
3084
3085   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3086    [],
3087    "read directories entries",
3088    "\
3089 This returns the list of directory entries in directory C<dir>.
3090
3091 All entries in the directory are returned, including C<.> and
3092 C<..>.  The entries are I<not> sorted, but returned in the same
3093 order as the underlying filesystem.
3094
3095 Also this call returns basic file type information about each
3096 file.  The C<ftyp> field will contain one of the following characters:
3097
3098 =over 4
3099
3100 =item 'b'
3101
3102 Block special
3103
3104 =item 'c'
3105
3106 Char special
3107
3108 =item 'd'
3109
3110 Directory
3111
3112 =item 'f'
3113
3114 FIFO (named pipe)
3115
3116 =item 'l'
3117
3118 Symbolic link
3119
3120 =item 'r'
3121
3122 Regular file
3123
3124 =item 's'
3125
3126 Socket
3127
3128 =item 'u'
3129
3130 Unknown file type
3131
3132 =item '?'
3133
3134 The L<readdir(3)> returned a C<d_type> field with an
3135 unexpected value
3136
3137 =back
3138
3139 This function is primarily intended for use by programs.  To
3140 get a simple list of names, use C<guestfs_ls>.  To get a printable
3141 directory for human consumption, use C<guestfs_ll>.");
3142
3143   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3144    [],
3145    "create partitions on a block device",
3146    "\
3147 This is a simplified interface to the C<guestfs_sfdisk>
3148 command, where partition sizes are specified in megabytes
3149 only (rounded to the nearest cylinder) and you don't need
3150 to specify the cyls, heads and sectors parameters which
3151 were rarely if ever used anyway.
3152
3153 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3154 and C<guestfs_part_disk>");
3155
3156   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3157    [],
3158    "determine file type inside a compressed file",
3159    "\
3160 This command runs C<file> after first decompressing C<path>
3161 using C<method>.
3162
3163 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3164
3165 Since 1.0.63, use C<guestfs_file> instead which can now
3166 process compressed files.");
3167
3168   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3169    [],
3170    "list extended attributes of a file or directory",
3171    "\
3172 This call lists the extended attributes of the file or directory
3173 C<path>.
3174
3175 At the system call level, this is a combination of the
3176 L<listxattr(2)> and L<getxattr(2)> calls.
3177
3178 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3179
3180   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3181    [],
3182    "list extended attributes of a file or directory",
3183    "\
3184 This is the same as C<guestfs_getxattrs>, but if C<path>
3185 is a symbolic link, then it returns the extended attributes
3186 of the link itself.");
3187
3188   ("setxattr", (RErr, [String "xattr";
3189                        String "val"; Int "vallen"; (* will be BufferIn *)
3190                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3191    [],
3192    "set extended attribute of a file or directory",
3193    "\
3194 This call sets the extended attribute named C<xattr>
3195 of the file C<path> to the value C<val> (of length C<vallen>).
3196 The value is arbitrary 8 bit data.
3197
3198 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3199
3200   ("lsetxattr", (RErr, [String "xattr";
3201                         String "val"; Int "vallen"; (* will be BufferIn *)
3202                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3203    [],
3204    "set extended attribute of a file or directory",
3205    "\
3206 This is the same as C<guestfs_setxattr>, but if C<path>
3207 is a symbolic link, then it sets an extended attribute
3208 of the link itself.");
3209
3210   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3211    [],
3212    "remove extended attribute of a file or directory",
3213    "\
3214 This call removes the extended attribute named C<xattr>
3215 of the file C<path>.
3216
3217 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3218
3219   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3220    [],
3221    "remove extended attribute of a file or directory",
3222    "\
3223 This is the same as C<guestfs_removexattr>, but if C<path>
3224 is a symbolic link, then it removes an extended attribute
3225 of the link itself.");
3226
3227   ("mountpoints", (RHashtable "mps", []), 147, [],
3228    [],
3229    "show mountpoints",
3230    "\
3231 This call is similar to C<guestfs_mounts>.  That call returns
3232 a list of devices.  This one returns a hash table (map) of
3233 device name to directory where the device is mounted.");
3234
3235   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3236    (* This is a special case: while you would expect a parameter
3237     * of type "Pathname", that doesn't work, because it implies
3238     * NEED_ROOT in the generated calling code in stubs.c, and
3239     * this function cannot use NEED_ROOT.
3240     *)
3241    [],
3242    "create a mountpoint",
3243    "\
3244 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3245 specialized calls that can be used to create extra mountpoints
3246 before mounting the first filesystem.
3247
3248 These calls are I<only> necessary in some very limited circumstances,
3249 mainly the case where you want to mount a mix of unrelated and/or
3250 read-only filesystems together.
3251
3252 For example, live CDs often contain a \"Russian doll\" nest of
3253 filesystems, an ISO outer layer, with a squashfs image inside, with
3254 an ext2/3 image inside that.  You can unpack this as follows
3255 in guestfish:
3256
3257  add-ro Fedora-11-i686-Live.iso
3258  run
3259  mkmountpoint /cd
3260  mkmountpoint /squash
3261  mkmountpoint /ext3
3262  mount /dev/sda /cd
3263  mount-loop /cd/LiveOS/squashfs.img /squash
3264  mount-loop /squash/LiveOS/ext3fs.img /ext3
3265
3266 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3267
3268   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3269    [],
3270    "remove a mountpoint",
3271    "\
3272 This calls removes a mountpoint that was previously created
3273 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3274 for full details.");
3275
3276   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3277    [InitISOFS, Always, TestOutputBuffer (
3278       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3279    "read a file",
3280    "\
3281 This calls returns the contents of the file C<path> as a
3282 buffer.
3283
3284 Unlike C<guestfs_cat>, this function can correctly
3285 handle files that contain embedded ASCII NUL characters.
3286 However unlike C<guestfs_download>, this function is limited
3287 in the total size of file that can be handled.");
3288
3289   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3290    [InitISOFS, Always, TestOutputList (
3291       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3292     InitISOFS, Always, TestOutputList (
3293       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3294    "return lines matching a pattern",
3295    "\
3296 This calls the external C<grep> program and returns the
3297 matching lines.");
3298
3299   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3300    [InitISOFS, Always, TestOutputList (
3301       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3302    "return lines matching a pattern",
3303    "\
3304 This calls the external C<egrep> program and returns the
3305 matching lines.");
3306
3307   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3308    [InitISOFS, Always, TestOutputList (
3309       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3310    "return lines matching a pattern",
3311    "\
3312 This calls the external C<fgrep> program and returns the
3313 matching lines.");
3314
3315   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3316    [InitISOFS, Always, TestOutputList (
3317       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3318    "return lines matching a pattern",
3319    "\
3320 This calls the external C<grep -i> program and returns the
3321 matching lines.");
3322
3323   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3326    "return lines matching a pattern",
3327    "\
3328 This calls the external C<egrep -i> program and returns the
3329 matching lines.");
3330
3331   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3332    [InitISOFS, Always, TestOutputList (
3333       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3334    "return lines matching a pattern",
3335    "\
3336 This calls the external C<fgrep -i> program and returns the
3337 matching lines.");
3338
3339   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3340    [InitISOFS, Always, TestOutputList (
3341       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3342    "return lines matching a pattern",
3343    "\
3344 This calls the external C<zgrep> program and returns the
3345 matching lines.");
3346
3347   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3348    [InitISOFS, Always, TestOutputList (
3349       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3350    "return lines matching a pattern",
3351    "\
3352 This calls the external C<zegrep> program and returns the
3353 matching lines.");
3354
3355   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3356    [InitISOFS, Always, TestOutputList (
3357       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3358    "return lines matching a pattern",
3359    "\
3360 This calls the external C<zfgrep> program and returns the
3361 matching lines.");
3362
3363   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3364    [InitISOFS, Always, TestOutputList (
3365       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3366    "return lines matching a pattern",
3367    "\
3368 This calls the external C<zgrep -i> program and returns the
3369 matching lines.");
3370
3371   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3372    [InitISOFS, Always, TestOutputList (
3373       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3374    "return lines matching a pattern",
3375    "\
3376 This calls the external C<zegrep -i> program and returns the
3377 matching lines.");
3378
3379   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3380    [InitISOFS, Always, TestOutputList (
3381       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3382    "return lines matching a pattern",
3383    "\
3384 This calls the external C<zfgrep -i> program and returns the
3385 matching lines.");
3386
3387   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3388    [InitISOFS, Always, TestOutput (
3389       [["realpath"; "/../directory"]], "/directory")],
3390    "canonicalized absolute pathname",
3391    "\
3392 Return the canonicalized absolute pathname of C<path>.  The
3393 returned path has no C<.>, C<..> or symbolic link path elements.");
3394
3395   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3396    [InitBasicFS, Always, TestOutputStruct (
3397       [["touch"; "/a"];
3398        ["ln"; "/a"; "/b"];
3399        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3400    "create a hard link",
3401    "\
3402 This command creates a hard link using the C<ln> command.");
3403
3404   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3405    [InitBasicFS, Always, TestOutputStruct (
3406       [["touch"; "/a"];
3407        ["touch"; "/b"];
3408        ["ln_f"; "/a"; "/b"];
3409        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3410    "create a hard link",
3411    "\
3412 This command creates a hard link using the C<ln -f> command.
3413 The C<-f> option removes the link (C<linkname>) if it exists already.");
3414
3415   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3416    [InitBasicFS, Always, TestOutputStruct (
3417       [["touch"; "/a"];
3418        ["ln_s"; "a"; "/b"];
3419        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3420    "create a symbolic link",
3421    "\
3422 This command creates a symbolic link using the C<ln -s> command.");
3423
3424   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3425    [InitBasicFS, Always, TestOutput (
3426       [["mkdir_p"; "/a/b"];
3427        ["touch"; "/a/b/c"];
3428        ["ln_sf"; "../d"; "/a/b/c"];
3429        ["readlink"; "/a/b/c"]], "../d")],
3430    "create a symbolic link",
3431    "\
3432 This command creates a symbolic link using the C<ln -sf> command,
3433 The C<-f> option removes the link (C<linkname>) if it exists already.");
3434
3435   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3436    [] (* XXX tested above *),
3437    "read the target of a symbolic link",
3438    "\
3439 This command reads the target of a symbolic link.");
3440
3441   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3442    [InitBasicFS, Always, TestOutputStruct (
3443       [["fallocate"; "/a"; "1000000"];
3444        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3445    "preallocate a file in the guest filesystem",
3446    "\
3447 This command preallocates a file (containing zero bytes) named
3448 C<path> of size C<len> bytes.  If the file exists already, it
3449 is overwritten.
3450
3451 Do not confuse this with the guestfish-specific
3452 C<alloc> command which allocates a file in the host and
3453 attaches it as a device.");
3454
3455   ("swapon_device", (RErr, [Device "device"]), 170, [],
3456    [InitPartition, Always, TestRun (
3457       [["mkswap"; "/dev/sda1"];
3458        ["swapon_device"; "/dev/sda1"];
3459        ["swapoff_device"; "/dev/sda1"]])],
3460    "enable swap on device",
3461    "\
3462 This command enables the libguestfs appliance to use the
3463 swap device or partition named C<device>.  The increased
3464 memory is made available for all commands, for example
3465 those run using C<guestfs_command> or C<guestfs_sh>.
3466
3467 Note that you should not swap to existing guest swap
3468 partitions unless you know what you are doing.  They may
3469 contain hibernation information, or other information that
3470 the guest doesn't want you to trash.  You also risk leaking
3471 information about the host to the guest this way.  Instead,
3472 attach a new host device to the guest and swap on that.");
3473
3474   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3475    [], (* XXX tested by swapon_device *)
3476    "disable swap on device",
3477    "\
3478 This command disables the libguestfs appliance swap
3479 device or partition named C<device>.
3480 See C<guestfs_swapon_device>.");
3481
3482   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3483    [InitBasicFS, Always, TestRun (
3484       [["fallocate"; "/swap"; "8388608"];
3485        ["mkswap_file"; "/swap"];
3486        ["swapon_file"; "/swap"];
3487        ["swapoff_file"; "/swap"]])],
3488    "enable swap on file",
3489    "\
3490 This command enables swap to a file.
3491 See C<guestfs_swapon_device> for other notes.");
3492
3493   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3494    [], (* XXX tested by swapon_file *)
3495    "disable swap on file",
3496    "\
3497 This command disables the libguestfs appliance swap on file.");
3498
3499   ("swapon_label", (RErr, [String "label"]), 174, [],
3500    [InitEmpty, Always, TestRun (
3501       [["part_disk"; "/dev/sdb"; "mbr"];
3502        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3503        ["swapon_label"; "swapit"];
3504        ["swapoff_label"; "swapit"];
3505        ["zero"; "/dev/sdb"];
3506        ["blockdev_rereadpt"; "/dev/sdb"]])],
3507    "enable swap on labeled swap partition",
3508    "\
3509 This command enables swap to a labeled swap partition.
3510 See C<guestfs_swapon_device> for other notes.");
3511
3512   ("swapoff_label", (RErr, [String "label"]), 175, [],
3513    [], (* XXX tested by swapon_label *)
3514    "disable swap on labeled swap partition",
3515    "\
3516 This command disables the libguestfs appliance swap on
3517 labeled swap partition.");
3518
3519   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3520    (let uuid = uuidgen () in
3521     [InitEmpty, Always, TestRun (
3522        [["mkswap_U"; uuid; "/dev/sdb"];
3523         ["swapon_uuid"; uuid];
3524         ["swapoff_uuid"; uuid]])]),
3525    "enable swap on swap partition by UUID",
3526    "\
3527 This command enables swap to a swap partition with the given UUID.
3528 See C<guestfs_swapon_device> for other notes.");
3529
3530   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3531    [], (* XXX tested by swapon_uuid *)
3532    "disable swap on swap partition by UUID",
3533    "\
3534 This command disables the libguestfs appliance swap partition
3535 with the given UUID.");
3536
3537   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3538    [InitBasicFS, Always, TestRun (
3539       [["fallocate"; "/swap"; "8388608"];
3540        ["mkswap_file"; "/swap"]])],
3541    "create a swap file",
3542    "\
3543 Create a swap file.
3544
3545 This command just writes a swap file signature to an existing
3546 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3547
3548   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3549    [InitISOFS, Always, TestRun (
3550       [["inotify_init"; "0"]])],
3551    "create an inotify handle",
3552    "\
3553 This command creates a new inotify handle.
3554 The inotify subsystem can be used to notify events which happen to
3555 objects in the guest filesystem.
3556
3557 C<maxevents> is the maximum number of events which will be
3558 queued up between calls to C<guestfs_inotify_read> or
3559 C<guestfs_inotify_files>.
3560 If this is passed as C<0>, then the kernel (or previously set)
3561 default is used.  For Linux 2.6.29 the default was 16384 events.
3562 Beyond this limit, the kernel throws away events, but records
3563 the fact that it threw them away by setting a flag
3564 C<IN_Q_OVERFLOW> in the returned structure list (see
3565 C<guestfs_inotify_read>).
3566
3567 Before any events are generated, you have to add some
3568 watches to the internal watch list.  See:
3569 C<guestfs_inotify_add_watch>,
3570 C<guestfs_inotify_rm_watch> and
3571 C<guestfs_inotify_watch_all>.
3572
3573 Queued up events should be read periodically by calling
3574 C<guestfs_inotify_read>
3575 (or C<guestfs_inotify_files> which is just a helpful
3576 wrapper around C<guestfs_inotify_read>).  If you don't
3577 read the events out often enough then you risk the internal
3578 queue overflowing.
3579
3580 The handle should be closed after use by calling
3581 C<guestfs_inotify_close>.  This also removes any
3582 watches automatically.
3583
3584 See also L<inotify(7)> for an overview of the inotify interface
3585 as exposed by the Linux kernel, which is roughly what we expose
3586 via libguestfs.  Note that there is one global inotify handle
3587 per libguestfs instance.");
3588
3589   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3590    [InitBasicFS, Always, TestOutputList (
3591       [["inotify_init"; "0"];
3592        ["inotify_add_watch"; "/"; "1073741823"];
3593        ["touch"; "/a"];
3594        ["touch"; "/b"];
3595        ["inotify_files"]], ["a"; "b"])],
3596    "add an inotify watch",
3597    "\
3598 Watch C<path> for the events listed in C<mask>.
3599
3600 Note that if C<path> is a directory then events within that
3601 directory are watched, but this does I<not> happen recursively
3602 (in subdirectories).
3603
3604 Note for non-C or non-Linux callers: the inotify events are
3605 defined by the Linux kernel ABI and are listed in
3606 C</usr/include/sys/inotify.h>.");
3607
3608   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3609    [],
3610    "remove an inotify watch",
3611    "\
3612 Remove a previously defined inotify watch.
3613 See C<guestfs_inotify_add_watch>.");
3614
3615   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3616    [],
3617    "return list of inotify events",
3618    "\
3619 Return the complete queue of events that have happened
3620 since the previous read call.
3621
3622 If no events have happened, this returns an empty list.
3623
3624 I<Note>: In order to make sure that all events have been
3625 read, you must call this function repeatedly until it
3626 returns an empty list.  The reason is that the call will
3627 read events up to the maximum appliance-to-host message
3628 size and leave remaining events in the queue.");
3629
3630   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3631    [],
3632    "return list of watched files that had events",
3633    "\
3634 This function is a helpful wrapper around C<guestfs_inotify_read>
3635 which just returns a list of pathnames of objects that were
3636 touched.  The returned pathnames are sorted and deduplicated.");
3637
3638   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3639    [],
3640    "close the inotify handle",
3641    "\
3642 This closes the inotify handle which was previously
3643 opened by inotify_init.  It removes all watches, throws
3644 away any pending events, and deallocates all resources.");
3645
3646   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3647    [],
3648    "set SELinux security context",
3649    "\
3650 This sets the SELinux security context of the daemon
3651 to the string C<context>.
3652
3653 See the documentation about SELINUX in L<guestfs(3)>.");
3654
3655   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3656    [],
3657    "get SELinux security context",
3658    "\
3659 This gets the SELinux security context of the daemon.
3660
3661 See the documentation about SELINUX in L<guestfs(3)>,
3662 and C<guestfs_setcon>");
3663
3664   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3665    [InitEmpty, Always, TestOutput (
3666       [["part_disk"; "/dev/sda"; "mbr"];
3667        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3668        ["mount_options"; ""; "/dev/sda1"; "/"];
3669        ["write_file"; "/new"; "new file contents"; "0"];
3670        ["cat"; "/new"]], "new file contents")],
3671    "make a filesystem with block size",
3672    "\
3673 This call is similar to C<guestfs_mkfs>, but it allows you to
3674 control the block size of the resulting filesystem.  Supported
3675 block sizes depend on the filesystem type, but typically they
3676 are C<1024>, C<2048> or C<4096> only.");
3677
3678   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3679    [InitEmpty, Always, TestOutput (
3680       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3681        ["mke2journal"; "4096"; "/dev/sda1"];
3682        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3683        ["mount_options"; ""; "/dev/sda2"; "/"];
3684        ["write_file"; "/new"; "new file contents"; "0"];
3685        ["cat"; "/new"]], "new file contents")],
3686    "make ext2/3/4 external journal",
3687    "\
3688 This creates an ext2 external journal on C<device>.  It is equivalent
3689 to the command:
3690
3691  mke2fs -O journal_dev -b blocksize device");
3692
3693   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3694    [InitEmpty, Always, TestOutput (
3695       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3696        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3697        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3698        ["mount_options"; ""; "/dev/sda2"; "/"];
3699        ["write_file"; "/new"; "new file contents"; "0"];
3700        ["cat"; "/new"]], "new file contents")],
3701    "make ext2/3/4 external journal with label",
3702    "\
3703 This creates an ext2 external journal on C<device> with label C<label>.");
3704
3705   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3706    (let uuid = uuidgen () in
3707     [InitEmpty, Always, TestOutput (
3708        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3709         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3710         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3711         ["mount_options"; ""; "/dev/sda2"; "/"];
3712         ["write_file"; "/new"; "new file contents"; "0"];
3713         ["cat"; "/new"]], "new file contents")]),
3714    "make ext2/3/4 external journal with UUID",
3715    "\
3716 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3717
3718   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3719    [],
3720    "make ext2/3/4 filesystem with external journal",
3721    "\
3722 This creates an ext2/3/4 filesystem on C<device> with
3723 an external journal on C<journal>.  It is equivalent
3724 to the command:
3725
3726  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3727
3728 See also C<guestfs_mke2journal>.");
3729
3730   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3731    [],
3732    "make ext2/3/4 filesystem with external journal",
3733    "\
3734 This creates an ext2/3/4 filesystem on C<device> with
3735 an external journal on the journal labeled C<label>.
3736
3737 See also C<guestfs_mke2journal_L>.");
3738
3739   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3740    [],
3741    "make ext2/3/4 filesystem with external journal",
3742    "\
3743 This creates an ext2/3/4 filesystem on C<device> with
3744 an external journal on the journal with UUID C<uuid>.
3745
3746 See also C<guestfs_mke2journal_U>.");
3747
3748   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3749    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3750    "load a kernel module",
3751    "\
3752 This loads a kernel module in the appliance.
3753
3754 The kernel module must have been whitelisted when libguestfs
3755 was built (see C<appliance/kmod.whitelist.in> in the source).");
3756
3757   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3758    [InitNone, Always, TestOutput (
3759       [["echo_daemon"; "This is a test"]], "This is a test"
3760     )],
3761    "echo arguments back to the client",
3762    "\
3763 This command concatenate the list of C<words> passed with single spaces between
3764 them and returns the resulting string.
3765
3766 You can use this command to test the connection through to the daemon.
3767
3768 See also C<guestfs_ping_daemon>.");
3769
3770   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3771    [], (* There is a regression test for this. *)
3772    "find all files and directories, returning NUL-separated list",
3773    "\
3774 This command lists out all files and directories, recursively,
3775 starting at C<directory>, placing the resulting list in the
3776 external file called C<files>.
3777
3778 This command works the same way as C<guestfs_find> with the
3779 following exceptions:
3780
3781 =over 4
3782
3783 =item *
3784
3785 The resulting list is written to an external file.
3786
3787 =item *
3788
3789 Items (filenames) in the result are separated
3790 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3791
3792 =item *
3793
3794 This command is not limited in the number of names that it
3795 can return.
3796
3797 =item *
3798
3799 The result list is not sorted.
3800
3801 =back");
3802
3803   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3804    [InitISOFS, Always, TestOutput (
3805       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3806     InitISOFS, Always, TestOutput (
3807       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3808     InitISOFS, Always, TestOutput (
3809       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3810     InitISOFS, Always, TestLastFail (
3811       [["case_sensitive_path"; "/Known-1/"]]);
3812     InitBasicFS, Always, TestOutput (
3813       [["mkdir"; "/a"];
3814        ["mkdir"; "/a/bbb"];
3815        ["touch"; "/a/bbb/c"];
3816        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3817     InitBasicFS, Always, TestOutput (
3818       [["mkdir"; "/a"];
3819        ["mkdir"; "/a/bbb"];
3820        ["touch"; "/a/bbb/c"];
3821        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3822     InitBasicFS, Always, TestLastFail (
3823       [["mkdir"; "/a"];
3824        ["mkdir"; "/a/bbb"];
3825        ["touch"; "/a/bbb/c"];
3826        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3827    "return true path on case-insensitive filesystem",
3828    "\
3829 This can be used to resolve case insensitive paths on
3830 a filesystem which is case sensitive.  The use case is
3831 to resolve paths which you have read from Windows configuration
3832 files or the Windows Registry, to the true path.
3833
3834 The command handles a peculiarity of the Linux ntfs-3g
3835 filesystem driver (and probably others), which is that although
3836 the underlying filesystem is case-insensitive, the driver
3837 exports the filesystem to Linux as case-sensitive.
3838
3839 One consequence of this is that special directories such
3840 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3841 (or other things) depending on the precise details of how
3842 they were created.  In Windows itself this would not be
3843 a problem.
3844
3845 Bug or feature?  You decide:
3846 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3847
3848 This function resolves the true case of each element in the
3849 path and returns the case-sensitive path.
3850
3851 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3852 might return C<\"/WINDOWS/system32\"> (the exact return value
3853 would depend on details of how the directories were originally
3854 created under Windows).
3855
3856 I<Note>:
3857 This function does not handle drive names, backslashes etc.
3858
3859 See also C<guestfs_realpath>.");
3860
3861   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3862    [InitBasicFS, Always, TestOutput (
3863       [["vfs_type"; "/dev/sda1"]], "ext2")],
3864    "get the Linux VFS type corresponding to a mounted device",
3865    "\
3866 This command gets the block device type corresponding to
3867 a mounted device called C<device>.
3868
3869 Usually the result is the name of the Linux VFS module that
3870 is used to mount this device (probably determined automatically
3871 if you used the C<guestfs_mount> call).");
3872
3873   ("truncate", (RErr, [Pathname "path"]), 199, [],
3874    [InitBasicFS, Always, TestOutputStruct (
3875       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3876        ["truncate"; "/test"];
3877        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3878    "truncate a file to zero size",
3879    "\
3880 This command truncates C<path> to a zero-length file.  The
3881 file must exist already.");
3882
3883   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3884    [InitBasicFS, Always, TestOutputStruct (
3885       [["touch"; "/test"];
3886        ["truncate_size"; "/test"; "1000"];
3887        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3888    "truncate a file to a particular size",
3889    "\
3890 This command truncates C<path> to size C<size> bytes.  The file
3891 must exist already.  If the file is smaller than C<size> then
3892 the file is extended to the required size with null bytes.");
3893
3894   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3895    [InitBasicFS, Always, TestOutputStruct (
3896       [["touch"; "/test"];
3897        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3898        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3899    "set timestamp of a file with nanosecond precision",
3900    "\
3901 This command sets the timestamps of a file with nanosecond
3902 precision.
3903
3904 C<atsecs, atnsecs> are the last access time (atime) in secs and
3905 nanoseconds from the epoch.
3906
3907 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3908 secs and nanoseconds from the epoch.
3909
3910 If the C<*nsecs> field contains the special value C<-1> then
3911 the corresponding timestamp is set to the current time.  (The
3912 C<*secs> field is ignored in this case).
3913
3914 If the C<*nsecs> field contains the special value C<-2> then
3915 the corresponding timestamp is left unchanged.  (The
3916 C<*secs> field is ignored in this case).");
3917
3918   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3919    [InitBasicFS, Always, TestOutputStruct (
3920       [["mkdir_mode"; "/test"; "0o111"];
3921        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3922    "create a directory with a particular mode",
3923    "\
3924 This command creates a directory, setting the initial permissions
3925 of the directory to C<mode>.
3926
3927 For common Linux filesystems, the actual mode which is set will
3928 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3929 interpret the mode in other ways.
3930
3931 See also C<guestfs_mkdir>, C<guestfs_umask>");
3932
3933   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3934    [], (* XXX *)
3935    "change file owner and group",
3936    "\
3937 Change the file owner to C<owner> and group to C<group>.
3938 This is like C<guestfs_chown> but if C<path> is a symlink then
3939 the link itself is changed, not the target.
3940
3941 Only numeric uid and gid are supported.  If you want to use
3942 names, you will need to locate and parse the password file
3943 yourself (Augeas support makes this relatively easy).");
3944
3945   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3946    [], (* XXX *)
3947    "lstat on multiple files",
3948    "\
3949 This call allows you to perform the C<guestfs_lstat> operation
3950 on multiple files, where all files are in the directory C<path>.
3951 C<names> is the list of files from this directory.
3952
3953 On return you get a list of stat structs, with a one-to-one
3954 correspondence to the C<names> list.  If any name did not exist
3955 or could not be lstat'd, then the C<ino> field of that structure
3956 is set to C<-1>.
3957
3958 This call is intended for programs that want to efficiently
3959 list a directory contents without making many round-trips.
3960 See also C<guestfs_lxattrlist> for a similarly efficient call
3961 for getting extended attributes.  Very long directory listings
3962 might cause the protocol message size to be exceeded, causing
3963 this call to fail.  The caller must split up such requests
3964 into smaller groups of names.");
3965
3966   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3967    [], (* XXX *)
3968    "lgetxattr on multiple files",
3969    "\
3970 This call allows you to get the extended attributes
3971 of multiple files, where all files are in the directory C<path>.
3972 C<names> is the list of files from this directory.
3973
3974 On return you get a flat list of xattr structs which must be
3975 interpreted sequentially.  The first xattr struct always has a zero-length
3976 C<attrname>.  C<attrval> in this struct is zero-length
3977 to indicate there was an error doing C<lgetxattr> for this
3978 file, I<or> is a C string which is a decimal number
3979 (the number of following attributes for this file, which could
3980 be C<\"0\">).  Then after the first xattr struct are the
3981 zero or more attributes for the first named file.
3982 This repeats for the second and subsequent files.
3983
3984 This call is intended for programs that want to efficiently
3985 list a directory contents without making many round-trips.
3986 See also C<guestfs_lstatlist> for a similarly efficient call
3987 for getting standard stats.  Very long directory listings
3988 might cause the protocol message size to be exceeded, causing
3989 this call to fail.  The caller must split up such requests
3990 into smaller groups of names.");
3991
3992   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3993    [], (* XXX *)
3994    "readlink on multiple files",
3995    "\
3996 This call allows you to do a C<readlink> operation
3997 on multiple files, where all files are in the directory C<path>.
3998 C<names> is the list of files from this directory.
3999
4000 On return you get a list of strings, with a one-to-one
4001 correspondence to the C<names> list.  Each string is the
4002 value of the symbol link.
4003
4004 If the C<readlink(2)> operation fails on any name, then
4005 the corresponding result string is the empty string C<\"\">.
4006 However the whole operation is completed even if there
4007 were C<readlink(2)> errors, and so you can call this
4008 function with names where you don't know if they are
4009 symbolic links already (albeit slightly less efficient).
4010
4011 This call is intended for programs that want to efficiently
4012 list a directory contents without making many round-trips.
4013 Very long directory listings might cause the protocol
4014 message size to be exceeded, causing
4015 this call to fail.  The caller must split up such requests
4016 into smaller groups of names.");
4017
4018   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4019    [InitISOFS, Always, TestOutputBuffer (
4020       [["pread"; "/known-4"; "1"; "3"]], "\n");
4021     InitISOFS, Always, TestOutputBuffer (
4022       [["pread"; "/empty"; "0"; "100"]], "")],
4023    "read part of a file",
4024    "\
4025 This command lets you read part of a file.  It reads C<count>
4026 bytes of the file, starting at C<offset>, from file C<path>.
4027
4028 This may read fewer bytes than requested.  For further details
4029 see the L<pread(2)> system call.");
4030
4031   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4032    [InitEmpty, Always, TestRun (
4033       [["part_init"; "/dev/sda"; "gpt"]])],
4034    "create an empty partition table",
4035    "\
4036 This creates an empty partition table on C<device> of one of the
4037 partition types listed below.  Usually C<parttype> should be
4038 either C<msdos> or C<gpt> (for large disks).
4039
4040 Initially there are no partitions.  Following this, you should
4041 call C<guestfs_part_add> for each partition required.
4042
4043 Possible values for C<parttype> are:
4044
4045 =over 4
4046
4047 =item B<efi> | B<gpt>
4048
4049 Intel EFI / GPT partition table.
4050
4051 This is recommended for >= 2 TB partitions that will be accessed
4052 from Linux and Intel-based Mac OS X.  It also has limited backwards
4053 compatibility with the C<mbr> format.
4054
4055 =item B<mbr> | B<msdos>
4056
4057 The standard PC \"Master Boot Record\" (MBR) format used
4058 by MS-DOS and Windows.  This partition type will B<only> work
4059 for device sizes up to 2 TB.  For large disks we recommend
4060 using C<gpt>.
4061
4062 =back
4063
4064 Other partition table types that may work but are not
4065 supported include:
4066
4067 =over 4
4068
4069 =item B<aix>
4070
4071 AIX disk labels.
4072
4073 =item B<amiga> | B<rdb>
4074
4075 Amiga \"Rigid Disk Block\" format.
4076
4077 =item B<bsd>
4078
4079 BSD disk labels.
4080
4081 =item B<dasd>
4082
4083 DASD, used on IBM mainframes.
4084
4085 =item B<dvh>
4086
4087 MIPS/SGI volumes.
4088
4089 =item B<mac>
4090
4091 Old Mac partition format.  Modern Macs use C<gpt>.
4092
4093 =item B<pc98>
4094
4095 NEC PC-98 format, common in Japan apparently.
4096
4097 =item B<sun>
4098
4099 Sun disk labels.
4100
4101 =back");
4102
4103   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4104    [InitEmpty, Always, TestRun (
4105       [["part_init"; "/dev/sda"; "mbr"];
4106        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4107     InitEmpty, Always, TestRun (
4108       [["part_init"; "/dev/sda"; "gpt"];
4109        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4110        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4111     InitEmpty, Always, TestRun (
4112       [["part_init"; "/dev/sda"; "mbr"];
4113        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4114        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4115        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4116        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4117    "add a partition to the device",
4118    "\
4119 This command adds a partition to C<device>.  If there is no partition
4120 table on the device, call C<guestfs_part_init> first.
4121
4122 The C<prlogex> parameter is the type of partition.  Normally you
4123 should pass C<p> or C<primary> here, but MBR partition tables also
4124 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4125 types.
4126
4127 C<startsect> and C<endsect> are the start and end of the partition
4128 in I<sectors>.  C<endsect> may be negative, which means it counts
4129 backwards from the end of the disk (C<-1> is the last sector).
4130
4131 Creating a partition which covers the whole disk is not so easy.
4132 Use C<guestfs_part_disk> to do that.");
4133
4134   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4135    [InitEmpty, Always, TestRun (
4136       [["part_disk"; "/dev/sda"; "mbr"]]);
4137     InitEmpty, Always, TestRun (
4138       [["part_disk"; "/dev/sda"; "gpt"]])],
4139    "partition whole disk with a single primary partition",
4140    "\
4141 This command is simply a combination of C<guestfs_part_init>
4142 followed by C<guestfs_part_add> to create a single primary partition
4143 covering the whole disk.
4144
4145 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4146 but other possible values are described in C<guestfs_part_init>.");
4147
4148   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4149    [InitEmpty, Always, TestRun (
4150       [["part_disk"; "/dev/sda"; "mbr"];
4151        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4152    "make a partition bootable",
4153    "\
4154 This sets the bootable flag on partition numbered C<partnum> on
4155 device C<device>.  Note that partitions are numbered from 1.
4156
4157 The bootable flag is used by some operating systems (notably
4158 Windows) to determine which partition to boot from.  It is by
4159 no means universally recognized.");
4160
4161   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4162    [InitEmpty, Always, TestRun (
4163       [["part_disk"; "/dev/sda"; "gpt"];
4164        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4165    "set partition name",
4166    "\
4167 This sets the partition name on partition numbered C<partnum> on
4168 device C<device>.  Note that partitions are numbered from 1.
4169
4170 The partition name can only be set on certain types of partition
4171 table.  This works on C<gpt> but not on C<mbr> partitions.");
4172
4173   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4174    [], (* XXX Add a regression test for this. *)
4175    "list partitions on a device",
4176    "\
4177 This command parses the partition table on C<device> and
4178 returns the list of partitions found.
4179
4180 The fields in the returned structure are:
4181
4182 =over 4
4183
4184 =item B<part_num>
4185
4186 Partition number, counting from 1.
4187
4188 =item B<part_start>
4189
4190 Start of the partition I<in bytes>.  To get sectors you have to
4191 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4192
4193 =item B<part_end>
4194
4195 End of the partition in bytes.
4196
4197 =item B<part_size>
4198
4199 Size of the partition in bytes.
4200
4201 =back");
4202
4203   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4204    [InitEmpty, Always, TestOutput (
4205       [["part_disk"; "/dev/sda"; "gpt"];
4206        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4207    "get the partition table type",
4208    "\
4209 This command examines the partition table on C<device> and
4210 returns the partition table type (format) being used.
4211
4212 Common return values include: C<msdos> (a DOS/Windows style MBR
4213 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4214 values are possible, although unusual.  See C<guestfs_part_init>
4215 for a full list.");
4216
4217   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4218    [InitBasicFS, Always, TestOutputBuffer (
4219       [["fill"; "0x63"; "10"; "/test"];
4220        ["read_file"; "/test"]], "cccccccccc")],
4221    "fill a file with octets",
4222    "\
4223 This command creates a new file called C<path>.  The initial
4224 content of the file is C<len> octets of C<c>, where C<c>
4225 must be a number in the range C<[0..255]>.
4226
4227 To fill a file with zero bytes (sparsely), it is
4228 much more efficient to use C<guestfs_truncate_size>.");
4229
4230   ("available", (RErr, [StringList "groups"]), 216, [],
4231    [InitNone, Always, TestRun [["available"; ""]]],
4232    "test availability of some parts of the API",
4233    "\
4234 This command is used to check the availability of some
4235 groups of functionality in the appliance, which not all builds of
4236 the libguestfs appliance will be able to provide.
4237
4238 The libguestfs groups, and the functions that those
4239 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4240
4241 The argument C<groups> is a list of group names, eg:
4242 C<[\"inotify\", \"augeas\"]> would check for the availability of
4243 the Linux inotify functions and Augeas (configuration file
4244 editing) functions.
4245
4246 The command returns no error if I<all> requested groups are available.
4247
4248 It fails with an error if one or more of the requested
4249 groups is unavailable in the appliance.
4250
4251 If an unknown group name is included in the
4252 list of groups then an error is always returned.
4253
4254 I<Notes:>
4255
4256 =over 4
4257
4258 =item *
4259
4260 You must call C<guestfs_launch> before calling this function.
4261
4262 The reason is because we don't know what groups are
4263 supported by the appliance/daemon until it is running and can
4264 be queried.
4265
4266 =item *
4267
4268 If a group of functions is available, this does not necessarily
4269 mean that they will work.  You still have to check for errors
4270 when calling individual API functions even if they are
4271 available.
4272
4273 =item *
4274
4275 It is usually the job of distro packagers to build
4276 complete functionality into the libguestfs appliance.
4277 Upstream libguestfs, if built from source with all
4278 requirements satisfied, will support everything.
4279
4280 =item *
4281
4282 This call was added in version C<1.0.80>.  In previous
4283 versions of libguestfs all you could do would be to speculatively
4284 execute a command to find out if the daemon implemented it.
4285 See also C<guestfs_version>.
4286
4287 =back");
4288
4289   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4290    [InitBasicFS, Always, TestOutputBuffer (
4291       [["write_file"; "/src"; "hello, world"; "0"];
4292        ["dd"; "/src"; "/dest"];
4293        ["read_file"; "/dest"]], "hello, world")],
4294    "copy from source to destination using dd",
4295    "\
4296 This command copies from one source device or file C<src>
4297 to another destination device or file C<dest>.  Normally you
4298 would use this to copy to or from a device or partition, for
4299 example to duplicate a filesystem.
4300
4301 If the destination is a device, it must be as large or larger
4302 than the source file or device, otherwise the copy will fail.
4303 This command cannot do partial copies (see C<guestfs_copy_size>).");
4304
4305   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4306    [InitBasicFS, Always, TestOutputInt (
4307       [["write_file"; "/file"; "hello, world"; "0"];
4308        ["filesize"; "/file"]], 12)],
4309    "return the size of the file in bytes",
4310    "\
4311 This command returns the size of C<file> in bytes.
4312
4313 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4314 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4315 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4316
4317   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4318    [InitBasicFSonLVM, Always, TestOutputList (
4319       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4320        ["lvs"]], ["/dev/VG/LV2"])],
4321    "rename an LVM logical volume",
4322    "\
4323 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4324
4325   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4326    [InitBasicFSonLVM, Always, TestOutputList (
4327       [["umount"; "/"];
4328        ["vg_activate"; "false"; "VG"];
4329        ["vgrename"; "VG"; "VG2"];
4330        ["vg_activate"; "true"; "VG2"];
4331        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4332        ["vgs"]], ["VG2"])],
4333    "rename an LVM volume group",
4334    "\
4335 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4336
4337   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4338    [InitISOFS, Always, TestOutputBuffer (
4339       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4340    "list the contents of a single file in an initrd",
4341    "\
4342 This command unpacks the file C<filename> from the initrd file
4343 called C<initrdpath>.  The filename must be given I<without> the
4344 initial C</> character.
4345
4346 For example, in guestfish you could use the following command
4347 to examine the boot script (usually called C</init>)
4348 contained in a Linux initrd or initramfs image:
4349
4350  initrd-cat /boot/initrd-<version>.img init
4351
4352 See also C<guestfs_initrd_list>.");
4353
4354   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4355    [],
4356    "get the UUID of a physical volume",
4357    "\
4358 This command returns the UUID of the LVM PV C<device>.");
4359
4360   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4361    [],
4362    "get the UUID of a volume group",
4363    "\
4364 This command returns the UUID of the LVM VG named C<vgname>.");
4365
4366   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4367    [],
4368    "get the UUID of a logical volume",
4369    "\
4370 This command returns the UUID of the LVM LV C<device>.");
4371
4372   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4373    [],
4374    "get the PV UUIDs containing the volume group",
4375    "\
4376 Given a VG called C<vgname>, this returns the UUIDs of all
4377 the physical volumes that this volume group resides on.
4378
4379 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4380 calls to associate physical volumes and volume groups.
4381
4382 See also C<guestfs_vglvuuids>.");
4383
4384   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4385    [],
4386    "get the LV UUIDs of all LVs in the volume group",
4387    "\
4388 Given a VG called C<vgname>, this returns the UUIDs of all
4389 the logical volumes created in this volume group.
4390
4391 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4392 calls to associate logical volumes and volume groups.
4393
4394 See also C<guestfs_vgpvuuids>.");
4395
4396   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4397    [InitBasicFS, Always, TestOutputBuffer (
4398       [["write_file"; "/src"; "hello, world"; "0"];
4399        ["copy_size"; "/src"; "/dest"; "5"];
4400        ["read_file"; "/dest"]], "hello")],
4401    "copy size bytes from source to destination using dd",
4402    "\
4403 This command copies exactly C<size> bytes from one source device
4404 or file C<src> to another destination device or file C<dest>.
4405
4406 Note this will fail if the source is too short or if the destination
4407 is not large enough.");
4408
4409   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4410    [InitBasicFSonLVM, Always, TestRun (
4411       [["zero_device"; "/dev/VG/LV"]])],
4412    "write zeroes to an entire device",
4413    "\
4414 This command writes zeroes over the entire C<device>.  Compare
4415 with C<guestfs_zero> which just zeroes the first few blocks of
4416 a device.");
4417
4418   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4419    [InitBasicFS, Always, TestOutput (
4420       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4421        ["cat"; "/hello"]], "hello\n")],
4422    "unpack compressed tarball to directory",
4423    "\
4424 This command uploads and unpacks local file C<tarball> (an
4425 I<xz compressed> tar file) into C<directory>.");
4426
4427   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4428    [],
4429    "pack directory into compressed tarball",
4430    "\
4431 This command packs the contents of C<directory> and downloads
4432 it to local file C<tarball> (as an xz compressed tar archive).");
4433
4434   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4435    [],
4436    "resize an NTFS filesystem",
4437    "\
4438 This command resizes an NTFS filesystem, expanding or
4439 shrinking it to the size of the underlying device.
4440 See also L<ntfsresize(8)>.");
4441
4442   ("vgscan", (RErr, []), 232, [],
4443    [InitEmpty, Always, TestRun (
4444       [["vgscan"]])],
4445    "rescan for LVM physical volumes, volume groups and logical volumes",
4446    "\
4447 This rescans all block devices and rebuilds the list of LVM
4448 physical volumes, volume groups and logical volumes.");
4449
4450   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4451    [InitEmpty, Always, TestRun (
4452       [["part_init"; "/dev/sda"; "mbr"];
4453        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4454        ["part_del"; "/dev/sda"; "1"]])],
4455    "delete a partition",
4456    "\
4457 This command deletes the partition numbered C<partnum> on C<device>.
4458
4459 Note that in the case of MBR partitioning, deleting an
4460 extended partition also deletes any logical partitions
4461 it contains.");
4462
4463   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4464    [InitEmpty, Always, TestOutputTrue (
4465       [["part_init"; "/dev/sda"; "mbr"];
4466        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4467        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4468        ["part_get_bootable"; "/dev/sda"; "1"]])],
4469    "return true if a partition is bootable",
4470    "\
4471 This command returns true if the partition C<partnum> on
4472 C<device> has the bootable flag set.
4473
4474 See also C<guestfs_part_set_bootable>.");
4475
4476   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4477    [InitEmpty, Always, TestOutputInt (
4478       [["part_init"; "/dev/sda"; "mbr"];
4479        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4480        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4481        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4482    "get the MBR type byte (ID byte) from a partition",
4483    "\
4484 Returns the MBR type byte (also known as the ID byte) from
4485 the numbered partition C<partnum>.
4486
4487 Note that only MBR (old DOS-style) partitions have type bytes.
4488 You will get undefined results for other partition table
4489 types (see C<guestfs_part_get_parttype>).");
4490
4491   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4492    [], (* tested by part_get_mbr_id *)
4493    "set the MBR type byte (ID byte) of a partition",
4494    "\
4495 Sets the MBR type byte (also known as the ID byte) of
4496 the numbered partition C<partnum> to C<idbyte>.  Note
4497 that the type bytes quoted in most documentation are
4498 in fact hexadecimal numbers, but usually documented
4499 without any leading \"0x\" which might be confusing.
4500
4501 Note that only MBR (old DOS-style) partitions have type bytes.
4502 You will get undefined results for other partition table
4503 types (see C<guestfs_part_get_parttype>).");
4504
4505   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4506    [InitISOFS, Always, TestOutput (
4507       [["checksum_device"; "md5"; "/dev/sdd"]],
4508       (Digest.to_hex (Digest.file "images/test.iso")))],
4509    "compute MD5, SHAx or CRC checksum of the contents of a device",
4510    "\
4511 This call computes the MD5, SHAx or CRC checksum of the
4512 contents of the device named C<device>.  For the types of
4513 checksums supported see the C<guestfs_checksum> command.");
4514
4515   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4516    [InitNone, Always, TestRun (
4517       [["part_disk"; "/dev/sda"; "mbr"];
4518        ["pvcreate"; "/dev/sda1"];
4519        ["vgcreate"; "VG"; "/dev/sda1"];
4520        ["lvcreate"; "LV"; "VG"; "10"];
4521        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4522    "expand an LV to fill free space",
4523    "\
4524 This expands an existing logical volume C<lv> so that it fills
4525 C<pc>% of the remaining free space in the volume group.  Commonly
4526 you would call this with pc = 100 which expands the logical volume
4527 as much as possible, using all remaining free space in the volume
4528 group.");
4529
4530   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4531    [], (* XXX Augeas code needs tests. *)
4532    "clear Augeas path",
4533    "\
4534 Set the value associated with C<path> to C<NULL>.  This
4535 is the same as the L<augtool(1)> C<clear> command.");
4536
4537   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4538    [InitEmpty, Always, TestOutputInt (
4539       [["get_umask"]], 0o22)],
4540    "get the current umask",
4541    "\
4542 Return the current umask.  By default the umask is C<022>
4543 unless it has been set by calling C<guestfs_umask>.");
4544
4545   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4546    [],
4547    "upload a file to the appliance (internal use only)",
4548    "\
4549 The C<guestfs_debug_upload> command uploads a file to
4550 the libguestfs appliance.
4551
4552 There is no comprehensive help for this command.  You have
4553 to look at the file C<daemon/debug.c> in the libguestfs source
4554 to find out what it is for.");
4555
4556   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4557    [InitBasicFS, Always, TestOutput (
4558       [["base64_in"; "../images/hello.b64"; "/hello"];
4559        ["cat"; "/hello"]], "hello\n")],
4560    "upload base64-encoded data to file",
4561    "\
4562 This command uploads base64-encoded data from C<base64file>
4563 to C<filename>.");
4564
4565   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4566    [],
4567    "download file and encode as base64",
4568    "\
4569 This command downloads the contents of C<filename>, writing
4570 it out to local file C<base64file> encoded as base64.");
4571
4572   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4573    [],
4574    "compute MD5, SHAx or CRC checksum of files in a directory",
4575    "\
4576 This command computes the checksums of all regular files in
4577 C<directory> and then emits a list of those checksums to
4578 the local output file C<sumsfile>.
4579
4580 This can be used for verifying the integrity of a virtual
4581 machine.  However to be properly secure you should pay
4582 attention to the output of the checksum command (it uses
4583 the ones from GNU coreutils).  In particular when the
4584 filename is not printable, coreutils uses a special
4585 backslash syntax.  For more information, see the GNU
4586 coreutils info file.");
4587
4588 ]
4589
4590 let all_functions = non_daemon_functions @ daemon_functions
4591
4592 (* In some places we want the functions to be displayed sorted
4593  * alphabetically, so this is useful:
4594  *)
4595 let all_functions_sorted =
4596   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4597                compare n1 n2) all_functions
4598
4599 (* Field types for structures. *)
4600 type field =
4601   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4602   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4603   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4604   | FUInt32
4605   | FInt32
4606   | FUInt64
4607   | FInt64
4608   | FBytes                      (* Any int measure that counts bytes. *)
4609   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4610   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4611
4612 (* Because we generate extra parsing code for LVM command line tools,
4613  * we have to pull out the LVM columns separately here.
4614  *)
4615 let lvm_pv_cols = [
4616   "pv_name", FString;
4617   "pv_uuid", FUUID;
4618   "pv_fmt", FString;
4619   "pv_size", FBytes;
4620   "dev_size", FBytes;
4621   "pv_free", FBytes;
4622   "pv_used", FBytes;
4623   "pv_attr", FString (* XXX *);
4624   "pv_pe_count", FInt64;
4625   "pv_pe_alloc_count", FInt64;
4626   "pv_tags", FString;
4627   "pe_start", FBytes;
4628   "pv_mda_count", FInt64;
4629   "pv_mda_free", FBytes;
4630   (* Not in Fedora 10:
4631      "pv_mda_size", FBytes;
4632   *)
4633 ]
4634 let lvm_vg_cols = [
4635   "vg_name", FString;
4636   "vg_uuid", FUUID;
4637   "vg_fmt", FString;
4638   "vg_attr", FString (* XXX *);
4639   "vg_size", FBytes;
4640   "vg_free", FBytes;
4641   "vg_sysid", FString;
4642   "vg_extent_size", FBytes;
4643   "vg_extent_count", FInt64;
4644   "vg_free_count", FInt64;
4645   "max_lv", FInt64;
4646   "max_pv", FInt64;
4647   "pv_count", FInt64;
4648   "lv_count", FInt64;
4649   "snap_count", FInt64;
4650   "vg_seqno", FInt64;
4651   "vg_tags", FString;
4652   "vg_mda_count", FInt64;
4653   "vg_mda_free", FBytes;
4654   (* Not in Fedora 10:
4655      "vg_mda_size", FBytes;
4656   *)
4657 ]
4658 let lvm_lv_cols = [
4659   "lv_name", FString;
4660   "lv_uuid", FUUID;
4661   "lv_attr", FString (* XXX *);
4662   "lv_major", FInt64;
4663   "lv_minor", FInt64;
4664   "lv_kernel_major", FInt64;
4665   "lv_kernel_minor", FInt64;
4666   "lv_size", FBytes;
4667   "seg_count", FInt64;
4668   "origin", FString;
4669   "snap_percent", FOptPercent;
4670   "copy_percent", FOptPercent;
4671   "move_pv", FString;
4672   "lv_tags", FString;
4673   "mirror_log", FString;
4674   "modules", FString;
4675 ]
4676
4677 (* Names and fields in all structures (in RStruct and RStructList)
4678  * that we support.
4679  *)
4680 let structs = [
4681   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4682    * not use this struct in any new code.
4683    *)
4684   "int_bool", [
4685     "i", FInt32;                (* for historical compatibility *)
4686     "b", FInt32;                (* for historical compatibility *)
4687   ];
4688
4689   (* LVM PVs, VGs, LVs. *)
4690   "lvm_pv", lvm_pv_cols;
4691   "lvm_vg", lvm_vg_cols;
4692   "lvm_lv", lvm_lv_cols;
4693
4694   (* Column names and types from stat structures.
4695    * NB. Can't use things like 'st_atime' because glibc header files
4696    * define some of these as macros.  Ugh.
4697    *)
4698   "stat", [
4699     "dev", FInt64;
4700     "ino", FInt64;
4701     "mode", FInt64;
4702     "nlink", FInt64;
4703     "uid", FInt64;
4704     "gid", FInt64;
4705     "rdev", FInt64;
4706     "size", FInt64;
4707     "blksize", FInt64;
4708     "blocks", FInt64;
4709     "atime", FInt64;
4710     "mtime", FInt64;
4711     "ctime", FInt64;
4712   ];
4713   "statvfs", [
4714     "bsize", FInt64;
4715     "frsize", FInt64;
4716     "blocks", FInt64;
4717     "bfree", FInt64;
4718     "bavail", FInt64;
4719     "files", FInt64;
4720     "ffree", FInt64;
4721     "favail", FInt64;
4722     "fsid", FInt64;
4723     "flag", FInt64;
4724     "namemax", FInt64;
4725   ];
4726
4727   (* Column names in dirent structure. *)
4728   "dirent", [
4729     "ino", FInt64;
4730     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4731     "ftyp", FChar;
4732     "name", FString;
4733   ];
4734
4735   (* Version numbers. *)
4736   "version", [
4737     "major", FInt64;
4738     "minor", FInt64;
4739     "release", FInt64;
4740     "extra", FString;
4741   ];
4742
4743   (* Extended attribute. *)
4744   "xattr", [
4745     "attrname", FString;
4746     "attrval", FBuffer;
4747   ];
4748
4749   (* Inotify events. *)
4750   "inotify_event", [
4751     "in_wd", FInt64;
4752     "in_mask", FUInt32;
4753     "in_cookie", FUInt32;
4754     "in_name", FString;
4755   ];
4756
4757   (* Partition table entry. *)
4758   "partition", [
4759     "part_num", FInt32;
4760     "part_start", FBytes;
4761     "part_end", FBytes;
4762     "part_size", FBytes;
4763   ];
4764 ] (* end of structs *)
4765
4766 (* Ugh, Java has to be different ..
4767  * These names are also used by the Haskell bindings.
4768  *)
4769 let java_structs = [
4770   "int_bool", "IntBool";
4771   "lvm_pv", "PV";
4772   "lvm_vg", "VG";
4773   "lvm_lv", "LV";
4774   "stat", "Stat";
4775   "statvfs", "StatVFS";
4776   "dirent", "Dirent";
4777   "version", "Version";
4778   "xattr", "XAttr";
4779   "inotify_event", "INotifyEvent";
4780   "partition", "Partition";
4781 ]
4782
4783 (* What structs are actually returned. *)
4784 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4785
4786 (* Returns a list of RStruct/RStructList structs that are returned
4787  * by any function.  Each element of returned list is a pair:
4788  *
4789  * (structname, RStructOnly)
4790  *    == there exists function which returns RStruct (_, structname)
4791  * (structname, RStructListOnly)
4792  *    == there exists function which returns RStructList (_, structname)
4793  * (structname, RStructAndList)
4794  *    == there are functions returning both RStruct (_, structname)
4795  *                                      and RStructList (_, structname)
4796  *)
4797 let rstructs_used_by functions =
4798   (* ||| is a "logical OR" for rstructs_used_t *)
4799   let (|||) a b =
4800     match a, b with
4801     | RStructAndList, _
4802     | _, RStructAndList -> RStructAndList
4803     | RStructOnly, RStructListOnly
4804     | RStructListOnly, RStructOnly -> RStructAndList
4805     | RStructOnly, RStructOnly -> RStructOnly
4806     | RStructListOnly, RStructListOnly -> RStructListOnly
4807   in
4808
4809   let h = Hashtbl.create 13 in
4810
4811   (* if elem->oldv exists, update entry using ||| operator,
4812    * else just add elem->newv to the hash
4813    *)
4814   let update elem newv =
4815     try  let oldv = Hashtbl.find h elem in
4816          Hashtbl.replace h elem (newv ||| oldv)
4817     with Not_found -> Hashtbl.add h elem newv
4818   in
4819
4820   List.iter (
4821     fun (_, style, _, _, _, _, _) ->
4822       match fst style with
4823       | RStruct (_, structname) -> update structname RStructOnly
4824       | RStructList (_, structname) -> update structname RStructListOnly
4825       | _ -> ()
4826   ) functions;
4827
4828   (* return key->values as a list of (key,value) *)
4829   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4830
4831 (* Used for testing language bindings. *)
4832 type callt =
4833   | CallString of string
4834   | CallOptString of string option
4835   | CallStringList of string list
4836   | CallInt of int
4837   | CallInt64 of int64
4838   | CallBool of bool
4839
4840 (* Used to memoize the result of pod2text. *)
4841 let pod2text_memo_filename = "src/.pod2text.data"
4842 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4843   try
4844     let chan = open_in pod2text_memo_filename in
4845     let v = input_value chan in
4846     close_in chan;
4847     v
4848   with
4849     _ -> Hashtbl.create 13
4850 let pod2text_memo_updated () =
4851   let chan = open_out pod2text_memo_filename in
4852   output_value chan pod2text_memo;
4853   close_out chan
4854
4855 (* Useful functions.
4856  * Note we don't want to use any external OCaml libraries which
4857  * makes this a bit harder than it should be.
4858  *)
4859 module StringMap = Map.Make (String)
4860
4861 let failwithf fs = ksprintf failwith fs
4862
4863 let unique = let i = ref 0 in fun () -> incr i; !i
4864
4865 let replace_char s c1 c2 =
4866   let s2 = String.copy s in
4867   let r = ref false in
4868   for i = 0 to String.length s2 - 1 do
4869     if String.unsafe_get s2 i = c1 then (
4870       String.unsafe_set s2 i c2;
4871       r := true
4872     )
4873   done;
4874   if not !r then s else s2
4875
4876 let isspace c =
4877   c = ' '
4878   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4879
4880 let triml ?(test = isspace) str =
4881   let i = ref 0 in
4882   let n = ref (String.length str) in
4883   while !n > 0 && test str.[!i]; do
4884     decr n;
4885     incr i
4886   done;
4887   if !i = 0 then str
4888   else String.sub str !i !n
4889
4890 let trimr ?(test = isspace) str =
4891   let n = ref (String.length str) in
4892   while !n > 0 && test str.[!n-1]; do
4893     decr n
4894   done;
4895   if !n = String.length str then str
4896   else String.sub str 0 !n
4897
4898 let trim ?(test = isspace) str =
4899   trimr ~test (triml ~test str)
4900
4901 let rec find s sub =
4902   let len = String.length s in
4903   let sublen = String.length sub in
4904   let rec loop i =
4905     if i <= len-sublen then (
4906       let rec loop2 j =
4907         if j < sublen then (
4908           if s.[i+j] = sub.[j] then loop2 (j+1)
4909           else -1
4910         ) else
4911           i (* found *)
4912       in
4913       let r = loop2 0 in
4914       if r = -1 then loop (i+1) else r
4915     ) else
4916       -1 (* not found *)
4917   in
4918   loop 0
4919
4920 let rec replace_str s s1 s2 =
4921   let len = String.length s in
4922   let sublen = String.length s1 in
4923   let i = find s s1 in
4924   if i = -1 then s
4925   else (
4926     let s' = String.sub s 0 i in
4927     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4928     s' ^ s2 ^ replace_str s'' s1 s2
4929   )
4930
4931 let rec string_split sep str =
4932   let len = String.length str in
4933   let seplen = String.length sep in
4934   let i = find str sep in
4935   if i = -1 then [str]
4936   else (
4937     let s' = String.sub str 0 i in
4938     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4939     s' :: string_split sep s''
4940   )
4941
4942 let files_equal n1 n2 =
4943   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4944   match Sys.command cmd with
4945   | 0 -> true
4946   | 1 -> false
4947   | i -> failwithf "%s: failed with error code %d" cmd i
4948
4949 let rec filter_map f = function
4950   | [] -> []
4951   | x :: xs ->
4952       match f x with
4953       | Some y -> y :: filter_map f xs
4954       | None -> filter_map f xs
4955
4956 let rec find_map f = function
4957   | [] -> raise Not_found
4958   | x :: xs ->
4959       match f x with
4960       | Some y -> y
4961       | None -> find_map f xs
4962
4963 let iteri f xs =
4964   let rec loop i = function
4965     | [] -> ()
4966     | x :: xs -> f i x; loop (i+1) xs
4967   in
4968   loop 0 xs
4969
4970 let mapi f xs =
4971   let rec loop i = function
4972     | [] -> []
4973     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4974   in
4975   loop 0 xs
4976
4977 let count_chars c str =
4978   let count = ref 0 in
4979   for i = 0 to String.length str - 1 do
4980     if c = String.unsafe_get str i then incr count
4981   done;
4982   !count
4983
4984 let name_of_argt = function
4985   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4986   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4987   | FileIn n | FileOut n -> n
4988
4989 let java_name_of_struct typ =
4990   try List.assoc typ java_structs
4991   with Not_found ->
4992     failwithf
4993       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4994
4995 let cols_of_struct typ =
4996   try List.assoc typ structs
4997   with Not_found ->
4998     failwithf "cols_of_struct: unknown struct %s" typ
4999
5000 let seq_of_test = function
5001   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5002   | TestOutputListOfDevices (s, _)
5003   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5004   | TestOutputTrue s | TestOutputFalse s
5005   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5006   | TestOutputStruct (s, _)
5007   | TestLastFail s -> s
5008
5009 (* Handling for function flags. *)
5010 let protocol_limit_warning =
5011   "Because of the message protocol, there is a transfer limit
5012 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5013
5014 let danger_will_robinson =
5015   "B<This command is dangerous.  Without careful use you
5016 can easily destroy all your data>."
5017
5018 let deprecation_notice flags =
5019   try
5020     let alt =
5021       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5022     let txt =
5023       sprintf "This function is deprecated.
5024 In new code, use the C<%s> call instead.
5025
5026 Deprecated functions will not be removed from the API, but the
5027 fact that they are deprecated indicates that there are problems
5028 with correct use of these functions." alt in
5029     Some txt
5030   with
5031     Not_found -> None
5032
5033 (* Create list of optional groups. *)
5034 let optgroups =
5035   let h = Hashtbl.create 13 in
5036   List.iter (
5037     fun (name, _, _, flags, _, _, _) ->
5038       List.iter (
5039         function
5040         | Optional group ->
5041             let names = try Hashtbl.find h group with Not_found -> [] in
5042             Hashtbl.replace h group (name :: names)
5043         | _ -> ()
5044       ) flags
5045   ) daemon_functions;
5046   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5047   let groups =
5048     List.map (
5049       fun group -> group, List.sort compare (Hashtbl.find h group)
5050     ) groups in
5051   List.sort (fun x y -> compare (fst x) (fst y)) groups
5052
5053 (* Check function names etc. for consistency. *)
5054 let check_functions () =
5055   let contains_uppercase str =
5056     let len = String.length str in
5057     let rec loop i =
5058       if i >= len then false
5059       else (
5060         let c = str.[i] in
5061         if c >= 'A' && c <= 'Z' then true
5062         else loop (i+1)
5063       )
5064     in
5065     loop 0
5066   in
5067
5068   (* Check function names. *)
5069   List.iter (
5070     fun (name, _, _, _, _, _, _) ->
5071       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5072         failwithf "function name %s does not need 'guestfs' prefix" name;
5073       if name = "" then
5074         failwithf "function name is empty";
5075       if name.[0] < 'a' || name.[0] > 'z' then
5076         failwithf "function name %s must start with lowercase a-z" name;
5077       if String.contains name '-' then
5078         failwithf "function name %s should not contain '-', use '_' instead."
5079           name
5080   ) all_functions;
5081
5082   (* Check function parameter/return names. *)
5083   List.iter (
5084     fun (name, style, _, _, _, _, _) ->
5085       let check_arg_ret_name n =
5086         if contains_uppercase n then
5087           failwithf "%s param/ret %s should not contain uppercase chars"
5088             name n;
5089         if String.contains n '-' || String.contains n '_' then
5090           failwithf "%s param/ret %s should not contain '-' or '_'"
5091             name n;
5092         if n = "value" then
5093           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;
5094         if n = "int" || n = "char" || n = "short" || n = "long" then
5095           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5096         if n = "i" || n = "n" then
5097           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5098         if n = "argv" || n = "args" then
5099           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5100
5101         (* List Haskell, OCaml and C keywords here.
5102          * http://www.haskell.org/haskellwiki/Keywords
5103          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5104          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5105          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5106          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5107          * Omitting _-containing words, since they're handled above.
5108          * Omitting the OCaml reserved word, "val", is ok,
5109          * and saves us from renaming several parameters.
5110          *)
5111         let reserved = [
5112           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5113           "char"; "class"; "const"; "constraint"; "continue"; "data";
5114           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5115           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5116           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5117           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5118           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5119           "interface";
5120           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5121           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5122           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5123           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5124           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5125           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5126           "volatile"; "when"; "where"; "while";
5127           ] in
5128         if List.mem n reserved then
5129           failwithf "%s has param/ret using reserved word %s" name n;
5130       in
5131
5132       (match fst style with
5133        | RErr -> ()
5134        | RInt n | RInt64 n | RBool n
5135        | RConstString n | RConstOptString n | RString n
5136        | RStringList n | RStruct (n, _) | RStructList (n, _)
5137        | RHashtable n | RBufferOut n ->
5138            check_arg_ret_name n
5139       );
5140       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5141   ) all_functions;
5142
5143   (* Check short descriptions. *)
5144   List.iter (
5145     fun (name, _, _, _, _, shortdesc, _) ->
5146       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5147         failwithf "short description of %s should begin with lowercase." name;
5148       let c = shortdesc.[String.length shortdesc-1] in
5149       if c = '\n' || c = '.' then
5150         failwithf "short description of %s should not end with . or \\n." name
5151   ) all_functions;
5152
5153   (* Check long descriptions. *)
5154   List.iter (
5155     fun (name, _, _, _, _, _, longdesc) ->
5156       if longdesc.[String.length longdesc-1] = '\n' then
5157         failwithf "long description of %s should not end with \\n." name
5158   ) all_functions;
5159
5160   (* Check proc_nrs. *)
5161   List.iter (
5162     fun (name, _, proc_nr, _, _, _, _) ->
5163       if proc_nr <= 0 then
5164         failwithf "daemon function %s should have proc_nr > 0" name
5165   ) daemon_functions;
5166
5167   List.iter (
5168     fun (name, _, proc_nr, _, _, _, _) ->
5169       if proc_nr <> -1 then
5170         failwithf "non-daemon function %s should have proc_nr -1" name
5171   ) non_daemon_functions;
5172
5173   let proc_nrs =
5174     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5175       daemon_functions in
5176   let proc_nrs =
5177     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5178   let rec loop = function
5179     | [] -> ()
5180     | [_] -> ()
5181     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5182         loop rest
5183     | (name1,nr1) :: (name2,nr2) :: _ ->
5184         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5185           name1 name2 nr1 nr2
5186   in
5187   loop proc_nrs;
5188
5189   (* Check tests. *)
5190   List.iter (
5191     function
5192       (* Ignore functions that have no tests.  We generate a
5193        * warning when the user does 'make check' instead.
5194        *)
5195     | name, _, _, _, [], _, _ -> ()
5196     | name, _, _, _, tests, _, _ ->
5197         let funcs =
5198           List.map (
5199             fun (_, _, test) ->
5200               match seq_of_test test with
5201               | [] ->
5202                   failwithf "%s has a test containing an empty sequence" name
5203               | cmds -> List.map List.hd cmds
5204           ) tests in
5205         let funcs = List.flatten funcs in
5206
5207         let tested = List.mem name funcs in
5208
5209         if not tested then
5210           failwithf "function %s has tests but does not test itself" name
5211   ) all_functions
5212
5213 (* 'pr' prints to the current output file. *)
5214 let chan = ref Pervasives.stdout
5215 let lines = ref 0
5216 let pr fs =
5217   ksprintf
5218     (fun str ->
5219        let i = count_chars '\n' str in
5220        lines := !lines + i;
5221        output_string !chan str
5222     ) fs
5223
5224 let copyright_years =
5225   let this_year = 1900 + (localtime (time ())).tm_year in
5226   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5227
5228 (* Generate a header block in a number of standard styles. *)
5229 type comment_style =
5230     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5231 type license = GPLv2plus | LGPLv2plus
5232
5233 let generate_header ?(extra_inputs = []) comment license =
5234   let inputs = "src/generator.ml" :: extra_inputs in
5235   let c = match comment with
5236     | CStyle ->         pr "/* "; " *"
5237     | CPlusPlusStyle -> pr "// "; "//"
5238     | HashStyle ->      pr "# ";  "#"
5239     | OCamlStyle ->     pr "(* "; " *"
5240     | HaskellStyle ->   pr "{- "; "  " in
5241   pr "libguestfs generated file\n";
5242   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5243   List.iter (pr "%s   %s\n" c) inputs;
5244   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5245   pr "%s\n" c;
5246   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5247   pr "%s\n" c;
5248   (match license with
5249    | GPLv2plus ->
5250        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5251        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5252        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5253        pr "%s (at your option) any later version.\n" c;
5254        pr "%s\n" c;
5255        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5256        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5257        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5258        pr "%s GNU General Public License for more details.\n" c;
5259        pr "%s\n" c;
5260        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5261        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5262        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5263
5264    | LGPLv2plus ->
5265        pr "%s This library is free software; you can redistribute it and/or\n" c;
5266        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5267        pr "%s License as published by the Free Software Foundation; either\n" c;
5268        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5269        pr "%s\n" c;
5270        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5271        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5272        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5273        pr "%s Lesser General Public License for more details.\n" c;
5274        pr "%s\n" c;
5275        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5276        pr "%s License along with this library; if not, write to the Free Software\n" c;
5277        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5278   );
5279   (match comment with
5280    | CStyle -> pr " */\n"
5281    | CPlusPlusStyle
5282    | HashStyle -> ()
5283    | OCamlStyle -> pr " *)\n"
5284    | HaskellStyle -> pr "-}\n"
5285   );
5286   pr "\n"
5287
5288 (* Start of main code generation functions below this line. *)
5289
5290 (* Generate the pod documentation for the C API. *)
5291 let rec generate_actions_pod () =
5292   List.iter (
5293     fun (shortname, style, _, flags, _, _, longdesc) ->
5294       if not (List.mem NotInDocs flags) then (
5295         let name = "guestfs_" ^ shortname in
5296         pr "=head2 %s\n\n" name;
5297         pr " ";
5298         generate_prototype ~extern:false ~handle:"g" name style;
5299         pr "\n\n";
5300         pr "%s\n\n" longdesc;
5301         (match fst style with
5302          | RErr ->
5303              pr "This function returns 0 on success or -1 on error.\n\n"
5304          | RInt _ ->
5305              pr "On error this function returns -1.\n\n"
5306          | RInt64 _ ->
5307              pr "On error this function returns -1.\n\n"
5308          | RBool _ ->
5309              pr "This function returns a C truth value on success or -1 on error.\n\n"
5310          | RConstString _ ->
5311              pr "This function returns a string, or NULL on error.
5312 The string is owned by the guest handle and must I<not> be freed.\n\n"
5313          | RConstOptString _ ->
5314              pr "This function returns a string which may be NULL.
5315 There is way to return an error from this function.
5316 The string is owned by the guest handle and must I<not> be freed.\n\n"
5317          | RString _ ->
5318              pr "This function returns a string, or NULL on error.
5319 I<The caller must free the returned string after use>.\n\n"
5320          | RStringList _ ->
5321              pr "This function returns a NULL-terminated array of strings
5322 (like L<environ(3)>), or NULL if there was an error.
5323 I<The caller must free the strings and the array after use>.\n\n"
5324          | RStruct (_, typ) ->
5325              pr "This function returns a C<struct guestfs_%s *>,
5326 or NULL if there was an error.
5327 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5328          | RStructList (_, typ) ->
5329              pr "This function returns a C<struct guestfs_%s_list *>
5330 (see E<lt>guestfs-structs.hE<gt>),
5331 or NULL if there was an error.
5332 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5333          | RHashtable _ ->
5334              pr "This function returns a NULL-terminated array of
5335 strings, or NULL if there was an error.
5336 The array of strings will always have length C<2n+1>, where
5337 C<n> keys and values alternate, followed by the trailing NULL entry.
5338 I<The caller must free the strings and the array after use>.\n\n"
5339          | RBufferOut _ ->
5340              pr "This function returns a buffer, or NULL on error.
5341 The size of the returned buffer is written to C<*size_r>.
5342 I<The caller must free the returned buffer after use>.\n\n"
5343         );
5344         if List.mem ProtocolLimitWarning flags then
5345           pr "%s\n\n" protocol_limit_warning;
5346         if List.mem DangerWillRobinson flags then
5347           pr "%s\n\n" danger_will_robinson;
5348         match deprecation_notice flags with
5349         | None -> ()
5350         | Some txt -> pr "%s\n\n" txt
5351       )
5352   ) all_functions_sorted
5353
5354 and generate_structs_pod () =
5355   (* Structs documentation. *)
5356   List.iter (
5357     fun (typ, cols) ->
5358       pr "=head2 guestfs_%s\n" typ;
5359       pr "\n";
5360       pr " struct guestfs_%s {\n" typ;
5361       List.iter (
5362         function
5363         | name, FChar -> pr "   char %s;\n" name
5364         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5365         | name, FInt32 -> pr "   int32_t %s;\n" name
5366         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5367         | name, FInt64 -> pr "   int64_t %s;\n" name
5368         | name, FString -> pr "   char *%s;\n" name
5369         | name, FBuffer ->
5370             pr "   /* The next two fields describe a byte array. */\n";
5371             pr "   uint32_t %s_len;\n" name;
5372             pr "   char *%s;\n" name
5373         | name, FUUID ->
5374             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5375             pr "   char %s[32];\n" name
5376         | name, FOptPercent ->
5377             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5378             pr "   float %s;\n" name
5379       ) cols;
5380       pr " };\n";
5381       pr " \n";
5382       pr " struct guestfs_%s_list {\n" typ;
5383       pr "   uint32_t len; /* Number of elements in list. */\n";
5384       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5385       pr " };\n";
5386       pr " \n";
5387       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5388       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5389         typ typ;
5390       pr "\n"
5391   ) structs
5392
5393 and generate_availability_pod () =
5394   (* Availability documentation. *)
5395   pr "=over 4\n";
5396   pr "\n";
5397   List.iter (
5398     fun (group, functions) ->
5399       pr "=item B<%s>\n" group;
5400       pr "\n";
5401       pr "The following functions:\n";
5402       List.iter (pr "L</guestfs_%s>\n") functions;
5403       pr "\n"
5404   ) optgroups;
5405   pr "=back\n";
5406   pr "\n"
5407
5408 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5409  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5410  *
5411  * We have to use an underscore instead of a dash because otherwise
5412  * rpcgen generates incorrect code.
5413  *
5414  * This header is NOT exported to clients, but see also generate_structs_h.
5415  *)
5416 and generate_xdr () =
5417   generate_header CStyle LGPLv2plus;
5418
5419   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5420   pr "typedef string str<>;\n";
5421   pr "\n";
5422
5423   (* Internal structures. *)
5424   List.iter (
5425     function
5426     | typ, cols ->
5427         pr "struct guestfs_int_%s {\n" typ;
5428         List.iter (function
5429                    | name, FChar -> pr "  char %s;\n" name
5430                    | name, FString -> pr "  string %s<>;\n" name
5431                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5432                    | name, FUUID -> pr "  opaque %s[32];\n" name
5433                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5434                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5435                    | name, FOptPercent -> pr "  float %s;\n" name
5436                   ) cols;
5437         pr "};\n";
5438         pr "\n";
5439         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5440         pr "\n";
5441   ) structs;
5442
5443   List.iter (
5444     fun (shortname, style, _, _, _, _, _) ->
5445       let name = "guestfs_" ^ shortname in
5446
5447       (match snd style with
5448        | [] -> ()
5449        | args ->
5450            pr "struct %s_args {\n" name;
5451            List.iter (
5452              function
5453              | Pathname n | Device n | Dev_or_Path n | String n ->
5454                  pr "  string %s<>;\n" n
5455              | OptString n -> pr "  str *%s;\n" n
5456              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5457              | Bool n -> pr "  bool %s;\n" n
5458              | Int n -> pr "  int %s;\n" n
5459              | Int64 n -> pr "  hyper %s;\n" n
5460              | FileIn _ | FileOut _ -> ()
5461            ) args;
5462            pr "};\n\n"
5463       );
5464       (match fst style with
5465        | RErr -> ()
5466        | RInt n ->
5467            pr "struct %s_ret {\n" name;
5468            pr "  int %s;\n" n;
5469            pr "};\n\n"
5470        | RInt64 n ->
5471            pr "struct %s_ret {\n" name;
5472            pr "  hyper %s;\n" n;
5473            pr "};\n\n"
5474        | RBool n ->
5475            pr "struct %s_ret {\n" name;
5476            pr "  bool %s;\n" n;
5477            pr "};\n\n"
5478        | RConstString _ | RConstOptString _ ->
5479            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5480        | RString n ->
5481            pr "struct %s_ret {\n" name;
5482            pr "  string %s<>;\n" n;
5483            pr "};\n\n"
5484        | RStringList n ->
5485            pr "struct %s_ret {\n" name;
5486            pr "  str %s<>;\n" n;
5487            pr "};\n\n"
5488        | RStruct (n, typ) ->
5489            pr "struct %s_ret {\n" name;
5490            pr "  guestfs_int_%s %s;\n" typ n;
5491            pr "};\n\n"
5492        | RStructList (n, typ) ->
5493            pr "struct %s_ret {\n" name;
5494            pr "  guestfs_int_%s_list %s;\n" typ n;
5495            pr "};\n\n"
5496        | RHashtable n ->
5497            pr "struct %s_ret {\n" name;
5498            pr "  str %s<>;\n" n;
5499            pr "};\n\n"
5500        | RBufferOut n ->
5501            pr "struct %s_ret {\n" name;
5502            pr "  opaque %s<>;\n" n;
5503            pr "};\n\n"
5504       );
5505   ) daemon_functions;
5506
5507   (* Table of procedure numbers. *)
5508   pr "enum guestfs_procedure {\n";
5509   List.iter (
5510     fun (shortname, _, proc_nr, _, _, _, _) ->
5511       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5512   ) daemon_functions;
5513   pr "  GUESTFS_PROC_NR_PROCS\n";
5514   pr "};\n";
5515   pr "\n";
5516
5517   (* Having to choose a maximum message size is annoying for several
5518    * reasons (it limits what we can do in the API), but it (a) makes
5519    * the protocol a lot simpler, and (b) provides a bound on the size
5520    * of the daemon which operates in limited memory space.
5521    *)
5522   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5523   pr "\n";
5524
5525   (* Message header, etc. *)
5526   pr "\
5527 /* The communication protocol is now documented in the guestfs(3)
5528  * manpage.
5529  */
5530
5531 const GUESTFS_PROGRAM = 0x2000F5F5;
5532 const GUESTFS_PROTOCOL_VERSION = 1;
5533
5534 /* These constants must be larger than any possible message length. */
5535 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5536 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5537
5538 enum guestfs_message_direction {
5539   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5540   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5541 };
5542
5543 enum guestfs_message_status {
5544   GUESTFS_STATUS_OK = 0,
5545   GUESTFS_STATUS_ERROR = 1
5546 };
5547
5548 const GUESTFS_ERROR_LEN = 256;
5549
5550 struct guestfs_message_error {
5551   string error_message<GUESTFS_ERROR_LEN>;
5552 };
5553
5554 struct guestfs_message_header {
5555   unsigned prog;                     /* GUESTFS_PROGRAM */
5556   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5557   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5558   guestfs_message_direction direction;
5559   unsigned serial;                   /* message serial number */
5560   guestfs_message_status status;
5561 };
5562
5563 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5564
5565 struct guestfs_chunk {
5566   int cancel;                        /* if non-zero, transfer is cancelled */
5567   /* data size is 0 bytes if the transfer has finished successfully */
5568   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5569 };
5570 "
5571
5572 (* Generate the guestfs-structs.h file. *)
5573 and generate_structs_h () =
5574   generate_header CStyle LGPLv2plus;
5575
5576   (* This is a public exported header file containing various
5577    * structures.  The structures are carefully written to have
5578    * exactly the same in-memory format as the XDR structures that
5579    * we use on the wire to the daemon.  The reason for creating
5580    * copies of these structures here is just so we don't have to
5581    * export the whole of guestfs_protocol.h (which includes much
5582    * unrelated and XDR-dependent stuff that we don't want to be
5583    * public, or required by clients).
5584    *
5585    * To reiterate, we will pass these structures to and from the
5586    * client with a simple assignment or memcpy, so the format
5587    * must be identical to what rpcgen / the RFC defines.
5588    *)
5589
5590   (* Public structures. *)
5591   List.iter (
5592     fun (typ, cols) ->
5593       pr "struct guestfs_%s {\n" typ;
5594       List.iter (
5595         function
5596         | name, FChar -> pr "  char %s;\n" name
5597         | name, FString -> pr "  char *%s;\n" name
5598         | name, FBuffer ->
5599             pr "  uint32_t %s_len;\n" name;
5600             pr "  char *%s;\n" name
5601         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5602         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5603         | name, FInt32 -> pr "  int32_t %s;\n" name
5604         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5605         | name, FInt64 -> pr "  int64_t %s;\n" name
5606         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5607       ) cols;
5608       pr "};\n";
5609       pr "\n";
5610       pr "struct guestfs_%s_list {\n" typ;
5611       pr "  uint32_t len;\n";
5612       pr "  struct guestfs_%s *val;\n" typ;
5613       pr "};\n";
5614       pr "\n";
5615       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5616       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5617       pr "\n"
5618   ) structs
5619
5620 (* Generate the guestfs-actions.h file. *)
5621 and generate_actions_h () =
5622   generate_header CStyle LGPLv2plus;
5623   List.iter (
5624     fun (shortname, style, _, _, _, _, _) ->
5625       let name = "guestfs_" ^ shortname in
5626       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5627         name style
5628   ) all_functions
5629
5630 (* Generate the guestfs-internal-actions.h file. *)
5631 and generate_internal_actions_h () =
5632   generate_header CStyle LGPLv2plus;
5633   List.iter (
5634     fun (shortname, style, _, _, _, _, _) ->
5635       let name = "guestfs__" ^ shortname in
5636       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5637         name style
5638   ) non_daemon_functions
5639
5640 (* Generate the client-side dispatch stubs. *)
5641 and generate_client_actions () =
5642   generate_header CStyle LGPLv2plus;
5643
5644   pr "\
5645 #include <stdio.h>
5646 #include <stdlib.h>
5647 #include <stdint.h>
5648 #include <string.h>
5649 #include <inttypes.h>
5650
5651 #include \"guestfs.h\"
5652 #include \"guestfs-internal.h\"
5653 #include \"guestfs-internal-actions.h\"
5654 #include \"guestfs_protocol.h\"
5655
5656 #define error guestfs_error
5657 //#define perrorf guestfs_perrorf
5658 #define safe_malloc guestfs_safe_malloc
5659 #define safe_realloc guestfs_safe_realloc
5660 //#define safe_strdup guestfs_safe_strdup
5661 #define safe_memdup guestfs_safe_memdup
5662
5663 /* Check the return message from a call for validity. */
5664 static int
5665 check_reply_header (guestfs_h *g,
5666                     const struct guestfs_message_header *hdr,
5667                     unsigned int proc_nr, unsigned int serial)
5668 {
5669   if (hdr->prog != GUESTFS_PROGRAM) {
5670     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5671     return -1;
5672   }
5673   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5674     error (g, \"wrong protocol version (%%d/%%d)\",
5675            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5676     return -1;
5677   }
5678   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5679     error (g, \"unexpected message direction (%%d/%%d)\",
5680            hdr->direction, GUESTFS_DIRECTION_REPLY);
5681     return -1;
5682   }
5683   if (hdr->proc != proc_nr) {
5684     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5685     return -1;
5686   }
5687   if (hdr->serial != serial) {
5688     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5689     return -1;
5690   }
5691
5692   return 0;
5693 }
5694
5695 /* Check we are in the right state to run a high-level action. */
5696 static int
5697 check_state (guestfs_h *g, const char *caller)
5698 {
5699   if (!guestfs__is_ready (g)) {
5700     if (guestfs__is_config (g) || guestfs__is_launching (g))
5701       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5702         caller);
5703     else
5704       error (g, \"%%s called from the wrong state, %%d != READY\",
5705         caller, guestfs__get_state (g));
5706     return -1;
5707   }
5708   return 0;
5709 }
5710
5711 ";
5712
5713   (* Generate code to generate guestfish call traces. *)
5714   let trace_call shortname style =
5715     pr "  if (guestfs__get_trace (g)) {\n";
5716
5717     let needs_i =
5718       List.exists (function
5719                    | StringList _ | DeviceList _ -> true
5720                    | _ -> false) (snd style) in
5721     if needs_i then (
5722       pr "    int i;\n";
5723       pr "\n"
5724     );
5725
5726     pr "    printf (\"%s\");\n" shortname;
5727     List.iter (
5728       function
5729       | String n                        (* strings *)
5730       | Device n
5731       | Pathname n
5732       | Dev_or_Path n
5733       | FileIn n
5734       | FileOut n ->
5735           (* guestfish doesn't support string escaping, so neither do we *)
5736           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5737       | OptString n ->                  (* string option *)
5738           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5739           pr "    else printf (\" null\");\n"
5740       | StringList n
5741       | DeviceList n ->                 (* string list *)
5742           pr "    putchar (' ');\n";
5743           pr "    putchar ('\"');\n";
5744           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5745           pr "      if (i > 0) putchar (' ');\n";
5746           pr "      fputs (%s[i], stdout);\n" n;
5747           pr "    }\n";
5748           pr "    putchar ('\"');\n";
5749       | Bool n ->                       (* boolean *)
5750           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5751       | Int n ->                        (* int *)
5752           pr "    printf (\" %%d\", %s);\n" n
5753       | Int64 n ->
5754           pr "    printf (\" %%\" PRIi64, %s);\n" n
5755     ) (snd style);
5756     pr "    putchar ('\\n');\n";
5757     pr "  }\n";
5758     pr "\n";
5759   in
5760
5761   (* For non-daemon functions, generate a wrapper around each function. *)
5762   List.iter (
5763     fun (shortname, style, _, _, _, _, _) ->
5764       let name = "guestfs_" ^ shortname in
5765
5766       generate_prototype ~extern:false ~semicolon:false ~newline:true
5767         ~handle:"g" name style;
5768       pr "{\n";
5769       trace_call shortname style;
5770       pr "  return guestfs__%s " shortname;
5771       generate_c_call_args ~handle:"g" style;
5772       pr ";\n";
5773       pr "}\n";
5774       pr "\n"
5775   ) non_daemon_functions;
5776
5777   (* Client-side stubs for each function. *)
5778   List.iter (
5779     fun (shortname, style, _, _, _, _, _) ->
5780       let name = "guestfs_" ^ shortname in
5781
5782       (* Generate the action stub. *)
5783       generate_prototype ~extern:false ~semicolon:false ~newline:true
5784         ~handle:"g" name style;
5785
5786       let error_code =
5787         match fst style with
5788         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5789         | RConstString _ | RConstOptString _ ->
5790             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5791         | RString _ | RStringList _
5792         | RStruct _ | RStructList _
5793         | RHashtable _ | RBufferOut _ ->
5794             "NULL" in
5795
5796       pr "{\n";
5797
5798       (match snd style with
5799        | [] -> ()
5800        | _ -> pr "  struct %s_args args;\n" name
5801       );
5802
5803       pr "  guestfs_message_header hdr;\n";
5804       pr "  guestfs_message_error err;\n";
5805       let has_ret =
5806         match fst style with
5807         | RErr -> false
5808         | RConstString _ | RConstOptString _ ->
5809             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5810         | RInt _ | RInt64 _
5811         | RBool _ | RString _ | RStringList _
5812         | RStruct _ | RStructList _
5813         | RHashtable _ | RBufferOut _ ->
5814             pr "  struct %s_ret ret;\n" name;
5815             true in
5816
5817       pr "  int serial;\n";
5818       pr "  int r;\n";
5819       pr "\n";
5820       trace_call shortname style;
5821       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5822         shortname error_code;
5823       pr "  guestfs___set_busy (g);\n";
5824       pr "\n";
5825
5826       (* Send the main header and arguments. *)
5827       (match snd style with
5828        | [] ->
5829            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5830              (String.uppercase shortname)
5831        | args ->
5832            List.iter (
5833              function
5834              | Pathname n | Device n | Dev_or_Path n | String n ->
5835                  pr "  args.%s = (char *) %s;\n" n n
5836              | OptString n ->
5837                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5838              | StringList n | DeviceList n ->
5839                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5840                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5841              | Bool n ->
5842                  pr "  args.%s = %s;\n" n n
5843              | Int n ->
5844                  pr "  args.%s = %s;\n" n n
5845              | Int64 n ->
5846                  pr "  args.%s = %s;\n" n n
5847              | FileIn _ | FileOut _ -> ()
5848            ) args;
5849            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5850              (String.uppercase shortname);
5851            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5852              name;
5853       );
5854       pr "  if (serial == -1) {\n";
5855       pr "    guestfs___end_busy (g);\n";
5856       pr "    return %s;\n" error_code;
5857       pr "  }\n";
5858       pr "\n";
5859
5860       (* Send any additional files (FileIn) requested. *)
5861       let need_read_reply_label = ref false in
5862       List.iter (
5863         function
5864         | FileIn n ->
5865             pr "  r = guestfs___send_file (g, %s);\n" n;
5866             pr "  if (r == -1) {\n";
5867             pr "    guestfs___end_busy (g);\n";
5868             pr "    return %s;\n" error_code;
5869             pr "  }\n";
5870             pr "  if (r == -2) /* daemon cancelled */\n";
5871             pr "    goto read_reply;\n";
5872             need_read_reply_label := true;
5873             pr "\n";
5874         | _ -> ()
5875       ) (snd style);
5876
5877       (* Wait for the reply from the remote end. *)
5878       if !need_read_reply_label then pr " read_reply:\n";
5879       pr "  memset (&hdr, 0, sizeof hdr);\n";
5880       pr "  memset (&err, 0, sizeof err);\n";
5881       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5882       pr "\n";
5883       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5884       if not has_ret then
5885         pr "NULL, NULL"
5886       else
5887         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5888       pr ");\n";
5889
5890       pr "  if (r == -1) {\n";
5891       pr "    guestfs___end_busy (g);\n";
5892       pr "    return %s;\n" error_code;
5893       pr "  }\n";
5894       pr "\n";
5895
5896       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5897         (String.uppercase shortname);
5898       pr "    guestfs___end_busy (g);\n";
5899       pr "    return %s;\n" error_code;
5900       pr "  }\n";
5901       pr "\n";
5902
5903       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5904       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5905       pr "    free (err.error_message);\n";
5906       pr "    guestfs___end_busy (g);\n";
5907       pr "    return %s;\n" error_code;
5908       pr "  }\n";
5909       pr "\n";
5910
5911       (* Expecting to receive further files (FileOut)? *)
5912       List.iter (
5913         function
5914         | FileOut n ->
5915             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5916             pr "    guestfs___end_busy (g);\n";
5917             pr "    return %s;\n" error_code;
5918             pr "  }\n";
5919             pr "\n";
5920         | _ -> ()
5921       ) (snd style);
5922
5923       pr "  guestfs___end_busy (g);\n";
5924
5925       (match fst style with
5926        | RErr -> pr "  return 0;\n"
5927        | RInt n | RInt64 n | RBool n ->
5928            pr "  return ret.%s;\n" n
5929        | RConstString _ | RConstOptString _ ->
5930            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5931        | RString n ->
5932            pr "  return ret.%s; /* caller will free */\n" n
5933        | RStringList n | RHashtable n ->
5934            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5935            pr "  ret.%s.%s_val =\n" n n;
5936            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5937            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5938              n n;
5939            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5940            pr "  return ret.%s.%s_val;\n" n n
5941        | RStruct (n, _) ->
5942            pr "  /* caller will free this */\n";
5943            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5944        | RStructList (n, _) ->
5945            pr "  /* caller will free this */\n";
5946            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5947        | RBufferOut n ->
5948            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5949            pr "   * _val might be NULL here.  To make the API saner for\n";
5950            pr "   * callers, we turn this case into a unique pointer (using\n";
5951            pr "   * malloc(1)).\n";
5952            pr "   */\n";
5953            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5954            pr "    *size_r = ret.%s.%s_len;\n" n n;
5955            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5956            pr "  } else {\n";
5957            pr "    free (ret.%s.%s_val);\n" n n;
5958            pr "    char *p = safe_malloc (g, 1);\n";
5959            pr "    *size_r = ret.%s.%s_len;\n" n n;
5960            pr "    return p;\n";
5961            pr "  }\n";
5962       );
5963
5964       pr "}\n\n"
5965   ) daemon_functions;
5966
5967   (* Functions to free structures. *)
5968   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5969   pr " * structure format is identical to the XDR format.  See note in\n";
5970   pr " * generator.ml.\n";
5971   pr " */\n";
5972   pr "\n";
5973
5974   List.iter (
5975     fun (typ, _) ->
5976       pr "void\n";
5977       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5978       pr "{\n";
5979       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5980       pr "  free (x);\n";
5981       pr "}\n";
5982       pr "\n";
5983
5984       pr "void\n";
5985       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5986       pr "{\n";
5987       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5988       pr "  free (x);\n";
5989       pr "}\n";
5990       pr "\n";
5991
5992   ) structs;
5993
5994 (* Generate daemon/actions.h. *)
5995 and generate_daemon_actions_h () =
5996   generate_header CStyle GPLv2plus;
5997
5998   pr "#include \"../src/guestfs_protocol.h\"\n";
5999   pr "\n";
6000
6001   List.iter (
6002     fun (name, style, _, _, _, _, _) ->
6003       generate_prototype
6004         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6005         name style;
6006   ) daemon_functions
6007
6008 (* Generate the linker script which controls the visibility of
6009  * symbols in the public ABI and ensures no other symbols get
6010  * exported accidentally.
6011  *)
6012 and generate_linker_script () =
6013   generate_header HashStyle GPLv2plus;
6014
6015   let globals = [
6016     "guestfs_create";
6017     "guestfs_close";
6018     "guestfs_get_error_handler";
6019     "guestfs_get_out_of_memory_handler";
6020     "guestfs_last_error";
6021     "guestfs_set_error_handler";
6022     "guestfs_set_launch_done_callback";
6023     "guestfs_set_log_message_callback";
6024     "guestfs_set_out_of_memory_handler";
6025     "guestfs_set_subprocess_quit_callback";
6026
6027     (* Unofficial parts of the API: the bindings code use these
6028      * functions, so it is useful to export them.
6029      *)
6030     "guestfs_safe_calloc";
6031     "guestfs_safe_malloc";
6032   ] in
6033   let functions =
6034     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6035       all_functions in
6036   let structs =
6037     List.concat (
6038       List.map (fun (typ, _) ->
6039                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6040         structs
6041     ) in
6042   let globals = List.sort compare (globals @ functions @ structs) in
6043
6044   pr "{\n";
6045   pr "    global:\n";
6046   List.iter (pr "        %s;\n") globals;
6047   pr "\n";
6048
6049   pr "    local:\n";
6050   pr "        *;\n";
6051   pr "};\n"
6052
6053 (* Generate the server-side stubs. *)
6054 and generate_daemon_actions () =
6055   generate_header CStyle GPLv2plus;
6056
6057   pr "#include <config.h>\n";
6058   pr "\n";
6059   pr "#include <stdio.h>\n";
6060   pr "#include <stdlib.h>\n";
6061   pr "#include <string.h>\n";
6062   pr "#include <inttypes.h>\n";
6063   pr "#include <rpc/types.h>\n";
6064   pr "#include <rpc/xdr.h>\n";
6065   pr "\n";
6066   pr "#include \"daemon.h\"\n";
6067   pr "#include \"c-ctype.h\"\n";
6068   pr "#include \"../src/guestfs_protocol.h\"\n";
6069   pr "#include \"actions.h\"\n";
6070   pr "\n";
6071
6072   List.iter (
6073     fun (name, style, _, _, _, _, _) ->
6074       (* Generate server-side stubs. *)
6075       pr "static void %s_stub (XDR *xdr_in)\n" name;
6076       pr "{\n";
6077       let error_code =
6078         match fst style with
6079         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6080         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6081         | RBool _ -> pr "  int r;\n"; "-1"
6082         | RConstString _ | RConstOptString _ ->
6083             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6084         | RString _ -> pr "  char *r;\n"; "NULL"
6085         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6086         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6087         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6088         | RBufferOut _ ->
6089             pr "  size_t size = 1;\n";
6090             pr "  char *r;\n";
6091             "NULL" in
6092
6093       (match snd style with
6094        | [] -> ()
6095        | args ->
6096            pr "  struct guestfs_%s_args args;\n" name;
6097            List.iter (
6098              function
6099              | Device n | Dev_or_Path n
6100              | Pathname n
6101              | String n -> ()
6102              | OptString n -> pr "  char *%s;\n" n
6103              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6104              | Bool n -> pr "  int %s;\n" n
6105              | Int n -> pr "  int %s;\n" n
6106              | Int64 n -> pr "  int64_t %s;\n" n
6107              | FileIn _ | FileOut _ -> ()
6108            ) args
6109       );
6110       pr "\n";
6111
6112       let is_filein =
6113         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6114
6115       (match snd style with
6116        | [] -> ()
6117        | args ->
6118            pr "  memset (&args, 0, sizeof args);\n";
6119            pr "\n";
6120            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6121            if is_filein then
6122              pr "    cancel_receive ();\n";
6123            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6124            pr "    goto done;\n";
6125            pr "  }\n";
6126            let pr_args n =
6127              pr "  char *%s = args.%s;\n" n n
6128            in
6129            let pr_list_handling_code n =
6130              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6131              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6132              pr "  if (%s == NULL) {\n" n;
6133              if is_filein then
6134                pr "    cancel_receive ();\n";
6135              pr "    reply_with_perror (\"realloc\");\n";
6136              pr "    goto done;\n";
6137              pr "  }\n";
6138              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6139              pr "  args.%s.%s_val = %s;\n" n n n;
6140            in
6141            List.iter (
6142              function
6143              | Pathname n ->
6144                  pr_args n;
6145                  pr "  ABS_PATH (%s, %s, goto done);\n"
6146                    n (if is_filein then "cancel_receive ()" else "");
6147              | Device n ->
6148                  pr_args n;
6149                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6150                    n (if is_filein then "cancel_receive ()" else "");
6151              | Dev_or_Path n ->
6152                  pr_args n;
6153                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6154                    n (if is_filein then "cancel_receive ()" else "");
6155              | String n -> pr_args n
6156              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6157              | StringList n ->
6158                  pr_list_handling_code n;
6159              | DeviceList n ->
6160                  pr_list_handling_code n;
6161                  pr "  /* Ensure that each is a device,\n";
6162                  pr "   * and perform device name translation. */\n";
6163                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6164                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6165                    (if is_filein then "cancel_receive ()" else "");
6166                  pr "  }\n";
6167              | Bool n -> pr "  %s = args.%s;\n" n n
6168              | Int n -> pr "  %s = args.%s;\n" n n
6169              | Int64 n -> pr "  %s = args.%s;\n" n n
6170              | FileIn _ | FileOut _ -> ()
6171            ) args;
6172            pr "\n"
6173       );
6174
6175
6176       (* this is used at least for do_equal *)
6177       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6178         (* Emit NEED_ROOT just once, even when there are two or
6179            more Pathname args *)
6180         pr "  NEED_ROOT (%s, goto done);\n"
6181           (if is_filein then "cancel_receive ()" else "");
6182       );
6183
6184       (* Don't want to call the impl with any FileIn or FileOut
6185        * parameters, since these go "outside" the RPC protocol.
6186        *)
6187       let args' =
6188         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6189           (snd style) in
6190       pr "  r = do_%s " name;
6191       generate_c_call_args (fst style, args');
6192       pr ";\n";
6193
6194       (match fst style with
6195        | RErr | RInt _ | RInt64 _ | RBool _
6196        | RConstString _ | RConstOptString _
6197        | RString _ | RStringList _ | RHashtable _
6198        | RStruct (_, _) | RStructList (_, _) ->
6199            pr "  if (r == %s)\n" error_code;
6200            pr "    /* do_%s has already called reply_with_error */\n" name;
6201            pr "    goto done;\n";
6202            pr "\n"
6203        | RBufferOut _ ->
6204            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6205            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6206            pr "   */\n";
6207            pr "  if (size == 1 && r == %s)\n" error_code;
6208            pr "    /* do_%s has already called reply_with_error */\n" name;
6209            pr "    goto done;\n";
6210            pr "\n"
6211       );
6212
6213       (* If there are any FileOut parameters, then the impl must
6214        * send its own reply.
6215        *)
6216       let no_reply =
6217         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6218       if no_reply then
6219         pr "  /* do_%s has already sent a reply */\n" name
6220       else (
6221         match fst style with
6222         | RErr -> pr "  reply (NULL, NULL);\n"
6223         | RInt n | RInt64 n | RBool n ->
6224             pr "  struct guestfs_%s_ret ret;\n" name;
6225             pr "  ret.%s = r;\n" n;
6226             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6227               name
6228         | RConstString _ | RConstOptString _ ->
6229             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6230         | RString n ->
6231             pr "  struct guestfs_%s_ret ret;\n" name;
6232             pr "  ret.%s = r;\n" n;
6233             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6234               name;
6235             pr "  free (r);\n"
6236         | RStringList n | RHashtable n ->
6237             pr "  struct guestfs_%s_ret ret;\n" name;
6238             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6239             pr "  ret.%s.%s_val = r;\n" n n;
6240             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6241               name;
6242             pr "  free_strings (r);\n"
6243         | RStruct (n, _) ->
6244             pr "  struct guestfs_%s_ret ret;\n" name;
6245             pr "  ret.%s = *r;\n" n;
6246             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6247               name;
6248             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6249               name
6250         | RStructList (n, _) ->
6251             pr "  struct guestfs_%s_ret ret;\n" name;
6252             pr "  ret.%s = *r;\n" n;
6253             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6254               name;
6255             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6256               name
6257         | RBufferOut n ->
6258             pr "  struct guestfs_%s_ret ret;\n" name;
6259             pr "  ret.%s.%s_val = r;\n" n n;
6260             pr "  ret.%s.%s_len = size;\n" n n;
6261             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6262               name;
6263             pr "  free (r);\n"
6264       );
6265
6266       (* Free the args. *)
6267       pr "done:\n";
6268       (match snd style with
6269        | [] -> ()
6270        | _ ->
6271            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6272              name
6273       );
6274       pr "  return;\n";
6275       pr "}\n\n";
6276   ) daemon_functions;
6277
6278   (* Dispatch function. *)
6279   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6280   pr "{\n";
6281   pr "  switch (proc_nr) {\n";
6282
6283   List.iter (
6284     fun (name, style, _, _, _, _, _) ->
6285       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6286       pr "      %s_stub (xdr_in);\n" name;
6287       pr "      break;\n"
6288   ) daemon_functions;
6289
6290   pr "    default:\n";
6291   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";
6292   pr "  }\n";
6293   pr "}\n";
6294   pr "\n";
6295
6296   (* LVM columns and tokenization functions. *)
6297   (* XXX This generates crap code.  We should rethink how we
6298    * do this parsing.
6299    *)
6300   List.iter (
6301     function
6302     | typ, cols ->
6303         pr "static const char *lvm_%s_cols = \"%s\";\n"
6304           typ (String.concat "," (List.map fst cols));
6305         pr "\n";
6306
6307         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6308         pr "{\n";
6309         pr "  char *tok, *p, *next;\n";
6310         pr "  int i, j;\n";
6311         pr "\n";
6312         (*
6313           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6314           pr "\n";
6315         *)
6316         pr "  if (!str) {\n";
6317         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6318         pr "    return -1;\n";
6319         pr "  }\n";
6320         pr "  if (!*str || c_isspace (*str)) {\n";
6321         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6322         pr "    return -1;\n";
6323         pr "  }\n";
6324         pr "  tok = str;\n";
6325         List.iter (
6326           fun (name, coltype) ->
6327             pr "  if (!tok) {\n";
6328             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6329             pr "    return -1;\n";
6330             pr "  }\n";
6331             pr "  p = strchrnul (tok, ',');\n";
6332             pr "  if (*p) next = p+1; else next = NULL;\n";
6333             pr "  *p = '\\0';\n";
6334             (match coltype with
6335              | FString ->
6336                  pr "  r->%s = strdup (tok);\n" name;
6337                  pr "  if (r->%s == NULL) {\n" name;
6338                  pr "    perror (\"strdup\");\n";
6339                  pr "    return -1;\n";
6340                  pr "  }\n"
6341              | FUUID ->
6342                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6343                  pr "    if (tok[j] == '\\0') {\n";
6344                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6345                  pr "      return -1;\n";
6346                  pr "    } else if (tok[j] != '-')\n";
6347                  pr "      r->%s[i++] = tok[j];\n" name;
6348                  pr "  }\n";
6349              | FBytes ->
6350                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6351                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6352                  pr "    return -1;\n";
6353                  pr "  }\n";
6354              | FInt64 ->
6355                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6356                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6357                  pr "    return -1;\n";
6358                  pr "  }\n";
6359              | FOptPercent ->
6360                  pr "  if (tok[0] == '\\0')\n";
6361                  pr "    r->%s = -1;\n" name;
6362                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6363                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6364                  pr "    return -1;\n";
6365                  pr "  }\n";
6366              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6367                  assert false (* can never be an LVM column *)
6368             );
6369             pr "  tok = next;\n";
6370         ) cols;
6371
6372         pr "  if (tok != NULL) {\n";
6373         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6374         pr "    return -1;\n";
6375         pr "  }\n";
6376         pr "  return 0;\n";
6377         pr "}\n";
6378         pr "\n";
6379
6380         pr "guestfs_int_lvm_%s_list *\n" typ;
6381         pr "parse_command_line_%ss (void)\n" typ;
6382         pr "{\n";
6383         pr "  char *out, *err;\n";
6384         pr "  char *p, *pend;\n";
6385         pr "  int r, i;\n";
6386         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6387         pr "  void *newp;\n";
6388         pr "\n";
6389         pr "  ret = malloc (sizeof *ret);\n";
6390         pr "  if (!ret) {\n";
6391         pr "    reply_with_perror (\"malloc\");\n";
6392         pr "    return NULL;\n";
6393         pr "  }\n";
6394         pr "\n";
6395         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6396         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6397         pr "\n";
6398         pr "  r = command (&out, &err,\n";
6399         pr "           \"lvm\", \"%ss\",\n" typ;
6400         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6401         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6402         pr "  if (r == -1) {\n";
6403         pr "    reply_with_error (\"%%s\", err);\n";
6404         pr "    free (out);\n";
6405         pr "    free (err);\n";
6406         pr "    free (ret);\n";
6407         pr "    return NULL;\n";
6408         pr "  }\n";
6409         pr "\n";
6410         pr "  free (err);\n";
6411         pr "\n";
6412         pr "  /* Tokenize each line of the output. */\n";
6413         pr "  p = out;\n";
6414         pr "  i = 0;\n";
6415         pr "  while (p) {\n";
6416         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6417         pr "    if (pend) {\n";
6418         pr "      *pend = '\\0';\n";
6419         pr "      pend++;\n";
6420         pr "    }\n";
6421         pr "\n";
6422         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6423         pr "      p++;\n";
6424         pr "\n";
6425         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6426         pr "      p = pend;\n";
6427         pr "      continue;\n";
6428         pr "    }\n";
6429         pr "\n";
6430         pr "    /* Allocate some space to store this next entry. */\n";
6431         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6432         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6433         pr "    if (newp == NULL) {\n";
6434         pr "      reply_with_perror (\"realloc\");\n";
6435         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6436         pr "      free (ret);\n";
6437         pr "      free (out);\n";
6438         pr "      return NULL;\n";
6439         pr "    }\n";
6440         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6441         pr "\n";
6442         pr "    /* Tokenize the next entry. */\n";
6443         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6444         pr "    if (r == -1) {\n";
6445         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6446         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6447         pr "      free (ret);\n";
6448         pr "      free (out);\n";
6449         pr "      return NULL;\n";
6450         pr "    }\n";
6451         pr "\n";
6452         pr "    ++i;\n";
6453         pr "    p = pend;\n";
6454         pr "  }\n";
6455         pr "\n";
6456         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6457         pr "\n";
6458         pr "  free (out);\n";
6459         pr "  return ret;\n";
6460         pr "}\n"
6461
6462   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6463
6464 (* Generate a list of function names, for debugging in the daemon.. *)
6465 and generate_daemon_names () =
6466   generate_header CStyle GPLv2plus;
6467
6468   pr "#include <config.h>\n";
6469   pr "\n";
6470   pr "#include \"daemon.h\"\n";
6471   pr "\n";
6472
6473   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6474   pr "const char *function_names[] = {\n";
6475   List.iter (
6476     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6477   ) daemon_functions;
6478   pr "};\n";
6479
6480 (* Generate the optional groups for the daemon to implement
6481  * guestfs_available.
6482  *)
6483 and generate_daemon_optgroups_c () =
6484   generate_header CStyle GPLv2plus;
6485
6486   pr "#include <config.h>\n";
6487   pr "\n";
6488   pr "#include \"daemon.h\"\n";
6489   pr "#include \"optgroups.h\"\n";
6490   pr "\n";
6491
6492   pr "struct optgroup optgroups[] = {\n";
6493   List.iter (
6494     fun (group, _) ->
6495       pr "  { \"%s\", optgroup_%s_available },\n" group group
6496   ) optgroups;
6497   pr "  { NULL, NULL }\n";
6498   pr "};\n"
6499
6500 and generate_daemon_optgroups_h () =
6501   generate_header CStyle GPLv2plus;
6502
6503   List.iter (
6504     fun (group, _) ->
6505       pr "extern int optgroup_%s_available (void);\n" group
6506   ) optgroups
6507
6508 (* Generate the tests. *)
6509 and generate_tests () =
6510   generate_header CStyle GPLv2plus;
6511
6512   pr "\
6513 #include <stdio.h>
6514 #include <stdlib.h>
6515 #include <string.h>
6516 #include <unistd.h>
6517 #include <sys/types.h>
6518 #include <fcntl.h>
6519
6520 #include \"guestfs.h\"
6521 #include \"guestfs-internal.h\"
6522
6523 static guestfs_h *g;
6524 static int suppress_error = 0;
6525
6526 static void print_error (guestfs_h *g, void *data, const char *msg)
6527 {
6528   if (!suppress_error)
6529     fprintf (stderr, \"%%s\\n\", msg);
6530 }
6531
6532 /* FIXME: nearly identical code appears in fish.c */
6533 static void print_strings (char *const *argv)
6534 {
6535   int argc;
6536
6537   for (argc = 0; argv[argc] != NULL; ++argc)
6538     printf (\"\\t%%s\\n\", argv[argc]);
6539 }
6540
6541 /*
6542 static void print_table (char const *const *argv)
6543 {
6544   int i;
6545
6546   for (i = 0; argv[i] != NULL; i += 2)
6547     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6548 }
6549 */
6550
6551 ";
6552
6553   (* Generate a list of commands which are not tested anywhere. *)
6554   pr "static void no_test_warnings (void)\n";
6555   pr "{\n";
6556
6557   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6558   List.iter (
6559     fun (_, _, _, _, tests, _, _) ->
6560       let tests = filter_map (
6561         function
6562         | (_, (Always|If _|Unless _), test) -> Some test
6563         | (_, Disabled, _) -> None
6564       ) tests in
6565       let seq = List.concat (List.map seq_of_test tests) in
6566       let cmds_tested = List.map List.hd seq in
6567       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6568   ) all_functions;
6569
6570   List.iter (
6571     fun (name, _, _, _, _, _, _) ->
6572       if not (Hashtbl.mem hash name) then
6573         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6574   ) all_functions;
6575
6576   pr "}\n";
6577   pr "\n";
6578
6579   (* Generate the actual tests.  Note that we generate the tests
6580    * in reverse order, deliberately, so that (in general) the
6581    * newest tests run first.  This makes it quicker and easier to
6582    * debug them.
6583    *)
6584   let test_names =
6585     List.map (
6586       fun (name, _, _, flags, tests, _, _) ->
6587         mapi (generate_one_test name flags) tests
6588     ) (List.rev all_functions) in
6589   let test_names = List.concat test_names in
6590   let nr_tests = List.length test_names in
6591
6592   pr "\
6593 int main (int argc, char *argv[])
6594 {
6595   char c = 0;
6596   unsigned long int n_failed = 0;
6597   const char *filename;
6598   int fd;
6599   int nr_tests, test_num = 0;
6600
6601   setbuf (stdout, NULL);
6602
6603   no_test_warnings ();
6604
6605   g = guestfs_create ();
6606   if (g == NULL) {
6607     printf (\"guestfs_create FAILED\\n\");
6608     exit (EXIT_FAILURE);
6609   }
6610
6611   guestfs_set_error_handler (g, print_error, NULL);
6612
6613   guestfs_set_path (g, \"../appliance\");
6614
6615   filename = \"test1.img\";
6616   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6617   if (fd == -1) {
6618     perror (filename);
6619     exit (EXIT_FAILURE);
6620   }
6621   if (lseek (fd, %d, SEEK_SET) == -1) {
6622     perror (\"lseek\");
6623     close (fd);
6624     unlink (filename);
6625     exit (EXIT_FAILURE);
6626   }
6627   if (write (fd, &c, 1) == -1) {
6628     perror (\"write\");
6629     close (fd);
6630     unlink (filename);
6631     exit (EXIT_FAILURE);
6632   }
6633   if (close (fd) == -1) {
6634     perror (filename);
6635     unlink (filename);
6636     exit (EXIT_FAILURE);
6637   }
6638   if (guestfs_add_drive (g, filename) == -1) {
6639     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6640     exit (EXIT_FAILURE);
6641   }
6642
6643   filename = \"test2.img\";
6644   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6645   if (fd == -1) {
6646     perror (filename);
6647     exit (EXIT_FAILURE);
6648   }
6649   if (lseek (fd, %d, SEEK_SET) == -1) {
6650     perror (\"lseek\");
6651     close (fd);
6652     unlink (filename);
6653     exit (EXIT_FAILURE);
6654   }
6655   if (write (fd, &c, 1) == -1) {
6656     perror (\"write\");
6657     close (fd);
6658     unlink (filename);
6659     exit (EXIT_FAILURE);
6660   }
6661   if (close (fd) == -1) {
6662     perror (filename);
6663     unlink (filename);
6664     exit (EXIT_FAILURE);
6665   }
6666   if (guestfs_add_drive (g, filename) == -1) {
6667     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6668     exit (EXIT_FAILURE);
6669   }
6670
6671   filename = \"test3.img\";
6672   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6673   if (fd == -1) {
6674     perror (filename);
6675     exit (EXIT_FAILURE);
6676   }
6677   if (lseek (fd, %d, SEEK_SET) == -1) {
6678     perror (\"lseek\");
6679     close (fd);
6680     unlink (filename);
6681     exit (EXIT_FAILURE);
6682   }
6683   if (write (fd, &c, 1) == -1) {
6684     perror (\"write\");
6685     close (fd);
6686     unlink (filename);
6687     exit (EXIT_FAILURE);
6688   }
6689   if (close (fd) == -1) {
6690     perror (filename);
6691     unlink (filename);
6692     exit (EXIT_FAILURE);
6693   }
6694   if (guestfs_add_drive (g, filename) == -1) {
6695     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6696     exit (EXIT_FAILURE);
6697   }
6698
6699   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6700     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6701     exit (EXIT_FAILURE);
6702   }
6703
6704   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6705   alarm (600);
6706
6707   if (guestfs_launch (g) == -1) {
6708     printf (\"guestfs_launch FAILED\\n\");
6709     exit (EXIT_FAILURE);
6710   }
6711
6712   /* Cancel previous alarm. */
6713   alarm (0);
6714
6715   nr_tests = %d;
6716
6717 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6718
6719   iteri (
6720     fun i test_name ->
6721       pr "  test_num++;\n";
6722       pr "  if (guestfs_get_verbose (g))\n";
6723       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6724       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6725       pr "  if (%s () == -1) {\n" test_name;
6726       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6727       pr "    n_failed++;\n";
6728       pr "  }\n";
6729   ) test_names;
6730   pr "\n";
6731
6732   pr "  guestfs_close (g);\n";
6733   pr "  unlink (\"test1.img\");\n";
6734   pr "  unlink (\"test2.img\");\n";
6735   pr "  unlink (\"test3.img\");\n";
6736   pr "\n";
6737
6738   pr "  if (n_failed > 0) {\n";
6739   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6740   pr "    exit (EXIT_FAILURE);\n";
6741   pr "  }\n";
6742   pr "\n";
6743
6744   pr "  exit (EXIT_SUCCESS);\n";
6745   pr "}\n"
6746
6747 and generate_one_test name flags i (init, prereq, test) =
6748   let test_name = sprintf "test_%s_%d" name i in
6749
6750   pr "\
6751 static int %s_skip (void)
6752 {
6753   const char *str;
6754
6755   str = getenv (\"TEST_ONLY\");
6756   if (str)
6757     return strstr (str, \"%s\") == NULL;
6758   str = getenv (\"SKIP_%s\");
6759   if (str && STREQ (str, \"1\")) return 1;
6760   str = getenv (\"SKIP_TEST_%s\");
6761   if (str && STREQ (str, \"1\")) return 1;
6762   return 0;
6763 }
6764
6765 " test_name name (String.uppercase test_name) (String.uppercase name);
6766
6767   (match prereq with
6768    | Disabled | Always -> ()
6769    | If code | Unless code ->
6770        pr "static int %s_prereq (void)\n" test_name;
6771        pr "{\n";
6772        pr "  %s\n" code;
6773        pr "}\n";
6774        pr "\n";
6775   );
6776
6777   pr "\
6778 static int %s (void)
6779 {
6780   if (%s_skip ()) {
6781     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6782     return 0;
6783   }
6784
6785 " test_name test_name test_name;
6786
6787   (* Optional functions should only be tested if the relevant
6788    * support is available in the daemon.
6789    *)
6790   List.iter (
6791     function
6792     | Optional group ->
6793         pr "  {\n";
6794         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6795         pr "    int r;\n";
6796         pr "    suppress_error = 1;\n";
6797         pr "    r = guestfs_available (g, (char **) groups);\n";
6798         pr "    suppress_error = 0;\n";
6799         pr "    if (r == -1) {\n";
6800         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6801         pr "      return 0;\n";
6802         pr "    }\n";
6803         pr "  }\n";
6804     | _ -> ()
6805   ) flags;
6806
6807   (match prereq with
6808    | Disabled ->
6809        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6810    | If _ ->
6811        pr "  if (! %s_prereq ()) {\n" test_name;
6812        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6813        pr "    return 0;\n";
6814        pr "  }\n";
6815        pr "\n";
6816        generate_one_test_body name i test_name init test;
6817    | Unless _ ->
6818        pr "  if (%s_prereq ()) {\n" test_name;
6819        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6820        pr "    return 0;\n";
6821        pr "  }\n";
6822        pr "\n";
6823        generate_one_test_body name i test_name init test;
6824    | Always ->
6825        generate_one_test_body name i test_name init test
6826   );
6827
6828   pr "  return 0;\n";
6829   pr "}\n";
6830   pr "\n";
6831   test_name
6832
6833 and generate_one_test_body name i test_name init test =
6834   (match init with
6835    | InitNone (* XXX at some point, InitNone and InitEmpty became
6836                * folded together as the same thing.  Really we should
6837                * make InitNone do nothing at all, but the tests may
6838                * need to be checked to make sure this is OK.
6839                *)
6840    | InitEmpty ->
6841        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6842        List.iter (generate_test_command_call test_name)
6843          [["blockdev_setrw"; "/dev/sda"];
6844           ["umount_all"];
6845           ["lvm_remove_all"]]
6846    | InitPartition ->
6847        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6848        List.iter (generate_test_command_call test_name)
6849          [["blockdev_setrw"; "/dev/sda"];
6850           ["umount_all"];
6851           ["lvm_remove_all"];
6852           ["part_disk"; "/dev/sda"; "mbr"]]
6853    | InitBasicFS ->
6854        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6855        List.iter (generate_test_command_call test_name)
6856          [["blockdev_setrw"; "/dev/sda"];
6857           ["umount_all"];
6858           ["lvm_remove_all"];
6859           ["part_disk"; "/dev/sda"; "mbr"];
6860           ["mkfs"; "ext2"; "/dev/sda1"];
6861           ["mount_options"; ""; "/dev/sda1"; "/"]]
6862    | InitBasicFSonLVM ->
6863        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6864          test_name;
6865        List.iter (generate_test_command_call test_name)
6866          [["blockdev_setrw"; "/dev/sda"];
6867           ["umount_all"];
6868           ["lvm_remove_all"];
6869           ["part_disk"; "/dev/sda"; "mbr"];
6870           ["pvcreate"; "/dev/sda1"];
6871           ["vgcreate"; "VG"; "/dev/sda1"];
6872           ["lvcreate"; "LV"; "VG"; "8"];
6873           ["mkfs"; "ext2"; "/dev/VG/LV"];
6874           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6875    | InitISOFS ->
6876        pr "  /* InitISOFS for %s */\n" test_name;
6877        List.iter (generate_test_command_call test_name)
6878          [["blockdev_setrw"; "/dev/sda"];
6879           ["umount_all"];
6880           ["lvm_remove_all"];
6881           ["mount_ro"; "/dev/sdd"; "/"]]
6882   );
6883
6884   let get_seq_last = function
6885     | [] ->
6886         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6887           test_name
6888     | seq ->
6889         let seq = List.rev seq in
6890         List.rev (List.tl seq), List.hd seq
6891   in
6892
6893   match test with
6894   | TestRun seq ->
6895       pr "  /* TestRun for %s (%d) */\n" name i;
6896       List.iter (generate_test_command_call test_name) seq
6897   | TestOutput (seq, expected) ->
6898       pr "  /* TestOutput for %s (%d) */\n" name i;
6899       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6900       let seq, last = get_seq_last seq in
6901       let test () =
6902         pr "    if (STRNEQ (r, expected)) {\n";
6903         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6904         pr "      return -1;\n";
6905         pr "    }\n"
6906       in
6907       List.iter (generate_test_command_call test_name) seq;
6908       generate_test_command_call ~test test_name last
6909   | TestOutputList (seq, expected) ->
6910       pr "  /* TestOutputList for %s (%d) */\n" name i;
6911       let seq, last = get_seq_last seq in
6912       let test () =
6913         iteri (
6914           fun i str ->
6915             pr "    if (!r[%d]) {\n" i;
6916             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6917             pr "      print_strings (r);\n";
6918             pr "      return -1;\n";
6919             pr "    }\n";
6920             pr "    {\n";
6921             pr "      const char *expected = \"%s\";\n" (c_quote str);
6922             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6923             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6924             pr "        return -1;\n";
6925             pr "      }\n";
6926             pr "    }\n"
6927         ) expected;
6928         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6929         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6930           test_name;
6931         pr "      print_strings (r);\n";
6932         pr "      return -1;\n";
6933         pr "    }\n"
6934       in
6935       List.iter (generate_test_command_call test_name) seq;
6936       generate_test_command_call ~test test_name last
6937   | TestOutputListOfDevices (seq, expected) ->
6938       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6939       let seq, last = get_seq_last seq in
6940       let test () =
6941         iteri (
6942           fun i str ->
6943             pr "    if (!r[%d]) {\n" i;
6944             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6945             pr "      print_strings (r);\n";
6946             pr "      return -1;\n";
6947             pr "    }\n";
6948             pr "    {\n";
6949             pr "      const char *expected = \"%s\";\n" (c_quote str);
6950             pr "      r[%d][5] = 's';\n" i;
6951             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6952             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6953             pr "        return -1;\n";
6954             pr "      }\n";
6955             pr "    }\n"
6956         ) expected;
6957         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6958         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6959           test_name;
6960         pr "      print_strings (r);\n";
6961         pr "      return -1;\n";
6962         pr "    }\n"
6963       in
6964       List.iter (generate_test_command_call test_name) seq;
6965       generate_test_command_call ~test test_name last
6966   | TestOutputInt (seq, expected) ->
6967       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6968       let seq, last = get_seq_last seq in
6969       let test () =
6970         pr "    if (r != %d) {\n" expected;
6971         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6972           test_name expected;
6973         pr "               (int) r);\n";
6974         pr "      return -1;\n";
6975         pr "    }\n"
6976       in
6977       List.iter (generate_test_command_call test_name) seq;
6978       generate_test_command_call ~test test_name last
6979   | TestOutputIntOp (seq, op, expected) ->
6980       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6981       let seq, last = get_seq_last seq in
6982       let test () =
6983         pr "    if (! (r %s %d)) {\n" op expected;
6984         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6985           test_name op expected;
6986         pr "               (int) r);\n";
6987         pr "      return -1;\n";
6988         pr "    }\n"
6989       in
6990       List.iter (generate_test_command_call test_name) seq;
6991       generate_test_command_call ~test test_name last
6992   | TestOutputTrue seq ->
6993       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6994       let seq, last = get_seq_last seq in
6995       let test () =
6996         pr "    if (!r) {\n";
6997         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6998           test_name;
6999         pr "      return -1;\n";
7000         pr "    }\n"
7001       in
7002       List.iter (generate_test_command_call test_name) seq;
7003       generate_test_command_call ~test test_name last
7004   | TestOutputFalse seq ->
7005       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7006       let seq, last = get_seq_last seq in
7007       let test () =
7008         pr "    if (r) {\n";
7009         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7010           test_name;
7011         pr "      return -1;\n";
7012         pr "    }\n"
7013       in
7014       List.iter (generate_test_command_call test_name) seq;
7015       generate_test_command_call ~test test_name last
7016   | TestOutputLength (seq, expected) ->
7017       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7018       let seq, last = get_seq_last seq in
7019       let test () =
7020         pr "    int j;\n";
7021         pr "    for (j = 0; j < %d; ++j)\n" expected;
7022         pr "      if (r[j] == NULL) {\n";
7023         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7024           test_name;
7025         pr "        print_strings (r);\n";
7026         pr "        return -1;\n";
7027         pr "      }\n";
7028         pr "    if (r[j] != NULL) {\n";
7029         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7030           test_name;
7031         pr "      print_strings (r);\n";
7032         pr "      return -1;\n";
7033         pr "    }\n"
7034       in
7035       List.iter (generate_test_command_call test_name) seq;
7036       generate_test_command_call ~test test_name last
7037   | TestOutputBuffer (seq, expected) ->
7038       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7039       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7040       let seq, last = get_seq_last seq in
7041       let len = String.length expected in
7042       let test () =
7043         pr "    if (size != %d) {\n" len;
7044         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7045         pr "      return -1;\n";
7046         pr "    }\n";
7047         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7048         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7049         pr "      return -1;\n";
7050         pr "    }\n"
7051       in
7052       List.iter (generate_test_command_call test_name) seq;
7053       generate_test_command_call ~test test_name last
7054   | TestOutputStruct (seq, checks) ->
7055       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7056       let seq, last = get_seq_last seq in
7057       let test () =
7058         List.iter (
7059           function
7060           | CompareWithInt (field, expected) ->
7061               pr "    if (r->%s != %d) {\n" field expected;
7062               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7063                 test_name field expected;
7064               pr "               (int) r->%s);\n" field;
7065               pr "      return -1;\n";
7066               pr "    }\n"
7067           | CompareWithIntOp (field, op, expected) ->
7068               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7069               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7070                 test_name field op expected;
7071               pr "               (int) r->%s);\n" field;
7072               pr "      return -1;\n";
7073               pr "    }\n"
7074           | CompareWithString (field, expected) ->
7075               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7076               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7077                 test_name field expected;
7078               pr "               r->%s);\n" field;
7079               pr "      return -1;\n";
7080               pr "    }\n"
7081           | CompareFieldsIntEq (field1, field2) ->
7082               pr "    if (r->%s != r->%s) {\n" field1 field2;
7083               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7084                 test_name field1 field2;
7085               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7086               pr "      return -1;\n";
7087               pr "    }\n"
7088           | CompareFieldsStrEq (field1, field2) ->
7089               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7090               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7091                 test_name field1 field2;
7092               pr "               r->%s, r->%s);\n" field1 field2;
7093               pr "      return -1;\n";
7094               pr "    }\n"
7095         ) checks
7096       in
7097       List.iter (generate_test_command_call test_name) seq;
7098       generate_test_command_call ~test test_name last
7099   | TestLastFail seq ->
7100       pr "  /* TestLastFail for %s (%d) */\n" name i;
7101       let seq, last = get_seq_last seq in
7102       List.iter (generate_test_command_call test_name) seq;
7103       generate_test_command_call test_name ~expect_error:true last
7104
7105 (* Generate the code to run a command, leaving the result in 'r'.
7106  * If you expect to get an error then you should set expect_error:true.
7107  *)
7108 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7109   match cmd with
7110   | [] -> assert false
7111   | name :: args ->
7112       (* Look up the command to find out what args/ret it has. *)
7113       let style =
7114         try
7115           let _, style, _, _, _, _, _ =
7116             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7117           style
7118         with Not_found ->
7119           failwithf "%s: in test, command %s was not found" test_name name in
7120
7121       if List.length (snd style) <> List.length args then
7122         failwithf "%s: in test, wrong number of args given to %s"
7123           test_name name;
7124
7125       pr "  {\n";
7126
7127       List.iter (
7128         function
7129         | OptString n, "NULL" -> ()
7130         | Pathname n, arg
7131         | Device n, arg
7132         | Dev_or_Path n, arg
7133         | String n, arg
7134         | OptString n, arg ->
7135             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7136         | Int _, _
7137         | Int64 _, _
7138         | Bool _, _
7139         | FileIn _, _ | FileOut _, _ -> ()
7140         | StringList n, "" | DeviceList n, "" ->
7141             pr "    const char *const %s[1] = { NULL };\n" n
7142         | StringList n, arg | DeviceList n, arg ->
7143             let strs = string_split " " arg in
7144             iteri (
7145               fun i str ->
7146                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7147             ) strs;
7148             pr "    const char *const %s[] = {\n" n;
7149             iteri (
7150               fun i _ -> pr "      %s_%d,\n" n i
7151             ) strs;
7152             pr "      NULL\n";
7153             pr "    };\n";
7154       ) (List.combine (snd style) args);
7155
7156       let error_code =
7157         match fst style with
7158         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7159         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7160         | RConstString _ | RConstOptString _ ->
7161             pr "    const char *r;\n"; "NULL"
7162         | RString _ -> pr "    char *r;\n"; "NULL"
7163         | RStringList _ | RHashtable _ ->
7164             pr "    char **r;\n";
7165             pr "    int i;\n";
7166             "NULL"
7167         | RStruct (_, typ) ->
7168             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7169         | RStructList (_, typ) ->
7170             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7171         | RBufferOut _ ->
7172             pr "    char *r;\n";
7173             pr "    size_t size;\n";
7174             "NULL" in
7175
7176       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7177       pr "    r = guestfs_%s (g" name;
7178
7179       (* Generate the parameters. *)
7180       List.iter (
7181         function
7182         | OptString _, "NULL" -> pr ", NULL"
7183         | Pathname n, _
7184         | Device n, _ | Dev_or_Path n, _
7185         | String n, _
7186         | OptString n, _ ->
7187             pr ", %s" n
7188         | FileIn _, arg | FileOut _, arg ->
7189             pr ", \"%s\"" (c_quote arg)
7190         | StringList n, _ | DeviceList n, _ ->
7191             pr ", (char **) %s" n
7192         | Int _, arg ->
7193             let i =
7194               try int_of_string arg
7195               with Failure "int_of_string" ->
7196                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7197             pr ", %d" i
7198         | Int64 _, arg ->
7199             let i =
7200               try Int64.of_string arg
7201               with Failure "int_of_string" ->
7202                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7203             pr ", %Ld" i
7204         | Bool _, arg ->
7205             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7206       ) (List.combine (snd style) args);
7207
7208       (match fst style with
7209        | RBufferOut _ -> pr ", &size"
7210        | _ -> ()
7211       );
7212
7213       pr ");\n";
7214
7215       if not expect_error then
7216         pr "    if (r == %s)\n" error_code
7217       else
7218         pr "    if (r != %s)\n" error_code;
7219       pr "      return -1;\n";
7220
7221       (* Insert the test code. *)
7222       (match test with
7223        | None -> ()
7224        | Some f -> f ()
7225       );
7226
7227       (match fst style with
7228        | RErr | RInt _ | RInt64 _ | RBool _
7229        | RConstString _ | RConstOptString _ -> ()
7230        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7231        | RStringList _ | RHashtable _ ->
7232            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7233            pr "      free (r[i]);\n";
7234            pr "    free (r);\n"
7235        | RStruct (_, typ) ->
7236            pr "    guestfs_free_%s (r);\n" typ
7237        | RStructList (_, typ) ->
7238            pr "    guestfs_free_%s_list (r);\n" typ
7239       );
7240
7241       pr "  }\n"
7242
7243 and c_quote str =
7244   let str = replace_str str "\r" "\\r" in
7245   let str = replace_str str "\n" "\\n" in
7246   let str = replace_str str "\t" "\\t" in
7247   let str = replace_str str "\000" "\\0" in
7248   str
7249
7250 (* Generate a lot of different functions for guestfish. *)
7251 and generate_fish_cmds () =
7252   generate_header CStyle GPLv2plus;
7253
7254   let all_functions =
7255     List.filter (
7256       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7257     ) all_functions in
7258   let all_functions_sorted =
7259     List.filter (
7260       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7261     ) all_functions_sorted in
7262
7263   pr "#include <config.h>\n";
7264   pr "\n";
7265   pr "#include <stdio.h>\n";
7266   pr "#include <stdlib.h>\n";
7267   pr "#include <string.h>\n";
7268   pr "#include <inttypes.h>\n";
7269   pr "\n";
7270   pr "#include <guestfs.h>\n";
7271   pr "#include \"c-ctype.h\"\n";
7272   pr "#include \"full-write.h\"\n";
7273   pr "#include \"xstrtol.h\"\n";
7274   pr "#include \"fish.h\"\n";
7275   pr "\n";
7276
7277   (* list_commands function, which implements guestfish -h *)
7278   pr "void list_commands (void)\n";
7279   pr "{\n";
7280   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7281   pr "  list_builtin_commands ();\n";
7282   List.iter (
7283     fun (name, _, _, flags, _, shortdesc, _) ->
7284       let name = replace_char name '_' '-' in
7285       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7286         name shortdesc
7287   ) all_functions_sorted;
7288   pr "  printf (\"    %%s\\n\",";
7289   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7290   pr "}\n";
7291   pr "\n";
7292
7293   (* display_command function, which implements guestfish -h cmd *)
7294   pr "void display_command (const char *cmd)\n";
7295   pr "{\n";
7296   List.iter (
7297     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7298       let name2 = replace_char name '_' '-' in
7299       let alias =
7300         try find_map (function FishAlias n -> Some n | _ -> None) flags
7301         with Not_found -> name in
7302       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7303       let synopsis =
7304         match snd style with
7305         | [] -> name2
7306         | args ->
7307             sprintf "%s %s"
7308               name2 (String.concat " " (List.map name_of_argt args)) in
7309
7310       let warnings =
7311         if List.mem ProtocolLimitWarning flags then
7312           ("\n\n" ^ protocol_limit_warning)
7313         else "" in
7314
7315       (* For DangerWillRobinson commands, we should probably have
7316        * guestfish prompt before allowing you to use them (especially
7317        * in interactive mode). XXX
7318        *)
7319       let warnings =
7320         warnings ^
7321           if List.mem DangerWillRobinson flags then
7322             ("\n\n" ^ danger_will_robinson)
7323           else "" in
7324
7325       let warnings =
7326         warnings ^
7327           match deprecation_notice flags with
7328           | None -> ""
7329           | Some txt -> "\n\n" ^ txt in
7330
7331       let describe_alias =
7332         if name <> alias then
7333           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7334         else "" in
7335
7336       pr "  if (";
7337       pr "STRCASEEQ (cmd, \"%s\")" name;
7338       if name <> name2 then
7339         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7340       if name <> alias then
7341         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7342       pr ")\n";
7343       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7344         name2 shortdesc
7345         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7346          "=head1 DESCRIPTION\n\n" ^
7347          longdesc ^ warnings ^ describe_alias);
7348       pr "  else\n"
7349   ) all_functions;
7350   pr "    display_builtin_command (cmd);\n";
7351   pr "}\n";
7352   pr "\n";
7353
7354   let emit_print_list_function typ =
7355     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7356       typ typ typ;
7357     pr "{\n";
7358     pr "  unsigned int i;\n";
7359     pr "\n";
7360     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7361     pr "    printf (\"[%%d] = {\\n\", i);\n";
7362     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7363     pr "    printf (\"}\\n\");\n";
7364     pr "  }\n";
7365     pr "}\n";
7366     pr "\n";
7367   in
7368
7369   (* print_* functions *)
7370   List.iter (
7371     fun (typ, cols) ->
7372       let needs_i =
7373         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7374
7375       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7376       pr "{\n";
7377       if needs_i then (
7378         pr "  unsigned int i;\n";
7379         pr "\n"
7380       );
7381       List.iter (
7382         function
7383         | name, FString ->
7384             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7385         | name, FUUID ->
7386             pr "  printf (\"%%s%s: \", indent);\n" name;
7387             pr "  for (i = 0; i < 32; ++i)\n";
7388             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7389             pr "  printf (\"\\n\");\n"
7390         | name, FBuffer ->
7391             pr "  printf (\"%%s%s: \", indent);\n" name;
7392             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7393             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7394             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7395             pr "    else\n";
7396             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7397             pr "  printf (\"\\n\");\n"
7398         | name, (FUInt64|FBytes) ->
7399             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7400               name typ name
7401         | name, FInt64 ->
7402             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7403               name typ name
7404         | name, FUInt32 ->
7405             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7406               name typ name
7407         | name, FInt32 ->
7408             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7409               name typ name
7410         | name, FChar ->
7411             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7412               name typ name
7413         | name, FOptPercent ->
7414             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7415               typ name name typ name;
7416             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7417       ) cols;
7418       pr "}\n";
7419       pr "\n";
7420   ) structs;
7421
7422   (* Emit a print_TYPE_list function definition only if that function is used. *)
7423   List.iter (
7424     function
7425     | typ, (RStructListOnly | RStructAndList) ->
7426         (* generate the function for typ *)
7427         emit_print_list_function typ
7428     | typ, _ -> () (* empty *)
7429   ) (rstructs_used_by all_functions);
7430
7431   (* Emit a print_TYPE function definition only if that function is used. *)
7432   List.iter (
7433     function
7434     | typ, (RStructOnly | RStructAndList) ->
7435         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7436         pr "{\n";
7437         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7438         pr "}\n";
7439         pr "\n";
7440     | typ, _ -> () (* empty *)
7441   ) (rstructs_used_by all_functions);
7442
7443   (* run_<action> actions *)
7444   List.iter (
7445     fun (name, style, _, flags, _, _, _) ->
7446       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7447       pr "{\n";
7448       (match fst style with
7449        | RErr
7450        | RInt _
7451        | RBool _ -> pr "  int r;\n"
7452        | RInt64 _ -> pr "  int64_t r;\n"
7453        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7454        | RString _ -> pr "  char *r;\n"
7455        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7456        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7457        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7458        | RBufferOut _ ->
7459            pr "  char *r;\n";
7460            pr "  size_t size;\n";
7461       );
7462       List.iter (
7463         function
7464         | Device n
7465         | String n
7466         | OptString n -> pr "  const char *%s;\n" n
7467         | Pathname n
7468         | Dev_or_Path n
7469         | FileIn n
7470         | FileOut n -> pr "  char *%s;\n" n
7471         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7472         | Bool n -> pr "  int %s;\n" n
7473         | Int n -> pr "  int %s;\n" n
7474         | Int64 n -> pr "  int64_t %s;\n" n
7475       ) (snd style);
7476
7477       (* Check and convert parameters. *)
7478       let argc_expected = List.length (snd style) in
7479       pr "  if (argc != %d) {\n" argc_expected;
7480       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7481         argc_expected;
7482       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7483       pr "    return -1;\n";
7484       pr "  }\n";
7485
7486       let parse_integer fn fntyp rtyp range name i =
7487         pr "  {\n";
7488         pr "    strtol_error xerr;\n";
7489         pr "    %s r;\n" fntyp;
7490         pr "\n";
7491         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7492         pr "    if (xerr != LONGINT_OK) {\n";
7493         pr "      fprintf (stderr,\n";
7494         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7495         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7496         pr "      return -1;\n";
7497         pr "    }\n";
7498         (match range with
7499          | None -> ()
7500          | Some (min, max, comment) ->
7501              pr "    /* %s */\n" comment;
7502              pr "    if (r < %s || r > %s) {\n" min max;
7503              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7504                name;
7505              pr "      return -1;\n";
7506              pr "    }\n";
7507              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7508         );
7509         pr "    %s = r;\n" name;
7510         pr "  }\n";
7511       in
7512
7513       iteri (
7514         fun i ->
7515           function
7516           | Device name
7517           | String name ->
7518               pr "  %s = argv[%d];\n" name i
7519           | Pathname name
7520           | Dev_or_Path name ->
7521               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7522               pr "  if (%s == NULL) return -1;\n" name
7523           | OptString name ->
7524               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7525                 name i i
7526           | FileIn name ->
7527               pr "  %s = file_in (argv[%d]);\n" name i;
7528               pr "  if (%s == NULL) return -1;\n" name
7529           | FileOut name ->
7530               pr "  %s = file_out (argv[%d]);\n" name i;
7531               pr "  if (%s == NULL) return -1;\n" name
7532           | StringList name | DeviceList name ->
7533               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7534               pr "  if (%s == NULL) return -1;\n" name;
7535           | Bool name ->
7536               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7537           | Int name ->
7538               let range =
7539                 let min = "(-(2LL<<30))"
7540                 and max = "((2LL<<30)-1)"
7541                 and comment =
7542                   "The Int type in the generator is a signed 31 bit int." in
7543                 Some (min, max, comment) in
7544               parse_integer "xstrtoll" "long long" "int" range name i
7545           | Int64 name ->
7546               parse_integer "xstrtoll" "long long" "int64_t" None name i
7547       ) (snd style);
7548
7549       (* Call C API function. *)
7550       let fn =
7551         try find_map (function FishAction n -> Some n | _ -> None) flags
7552         with Not_found -> sprintf "guestfs_%s" name in
7553       pr "  r = %s " fn;
7554       generate_c_call_args ~handle:"g" style;
7555       pr ";\n";
7556
7557       List.iter (
7558         function
7559         | Device name | String name
7560         | OptString name | Bool name
7561         | Int name | Int64 name -> ()
7562         | Pathname name | Dev_or_Path name | FileOut name ->
7563             pr "  free (%s);\n" name
7564         | FileIn name ->
7565             pr "  free_file_in (%s);\n" name
7566         | StringList name | DeviceList name ->
7567             pr "  free_strings (%s);\n" name
7568       ) (snd style);
7569
7570       (* Any output flags? *)
7571       let fish_output =
7572         let flags = filter_map (
7573           function FishOutput flag -> Some flag | _ -> None
7574         ) flags in
7575         match flags with
7576         | [] -> None
7577         | [f] -> Some f
7578         | _ ->
7579             failwithf "%s: more than one FishOutput flag is not allowed" name in
7580
7581       (* Check return value for errors and display command results. *)
7582       (match fst style with
7583        | RErr -> pr "  return r;\n"
7584        | RInt _ ->
7585            pr "  if (r == -1) return -1;\n";
7586            (match fish_output with
7587             | None ->
7588                 pr "  printf (\"%%d\\n\", r);\n";
7589             | Some FishOutputOctal ->
7590                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7591             | Some FishOutputHexadecimal ->
7592                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7593            pr "  return 0;\n"
7594        | RInt64 _ ->
7595            pr "  if (r == -1) return -1;\n";
7596            (match fish_output with
7597             | None ->
7598                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7599             | Some FishOutputOctal ->
7600                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7601             | Some FishOutputHexadecimal ->
7602                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7603            pr "  return 0;\n"
7604        | RBool _ ->
7605            pr "  if (r == -1) return -1;\n";
7606            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7607            pr "  return 0;\n"
7608        | RConstString _ ->
7609            pr "  if (r == NULL) return -1;\n";
7610            pr "  printf (\"%%s\\n\", r);\n";
7611            pr "  return 0;\n"
7612        | RConstOptString _ ->
7613            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7614            pr "  return 0;\n"
7615        | RString _ ->
7616            pr "  if (r == NULL) return -1;\n";
7617            pr "  printf (\"%%s\\n\", r);\n";
7618            pr "  free (r);\n";
7619            pr "  return 0;\n"
7620        | RStringList _ ->
7621            pr "  if (r == NULL) return -1;\n";
7622            pr "  print_strings (r);\n";
7623            pr "  free_strings (r);\n";
7624            pr "  return 0;\n"
7625        | RStruct (_, typ) ->
7626            pr "  if (r == NULL) return -1;\n";
7627            pr "  print_%s (r);\n" typ;
7628            pr "  guestfs_free_%s (r);\n" typ;
7629            pr "  return 0;\n"
7630        | RStructList (_, typ) ->
7631            pr "  if (r == NULL) return -1;\n";
7632            pr "  print_%s_list (r);\n" typ;
7633            pr "  guestfs_free_%s_list (r);\n" typ;
7634            pr "  return 0;\n"
7635        | RHashtable _ ->
7636            pr "  if (r == NULL) return -1;\n";
7637            pr "  print_table (r);\n";
7638            pr "  free_strings (r);\n";
7639            pr "  return 0;\n"
7640        | RBufferOut _ ->
7641            pr "  if (r == NULL) return -1;\n";
7642            pr "  if (full_write (1, r, size) != size) {\n";
7643            pr "    perror (\"write\");\n";
7644            pr "    free (r);\n";
7645            pr "    return -1;\n";
7646            pr "  }\n";
7647            pr "  free (r);\n";
7648            pr "  return 0;\n"
7649       );
7650       pr "}\n";
7651       pr "\n"
7652   ) all_functions;
7653
7654   (* run_action function *)
7655   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7656   pr "{\n";
7657   List.iter (
7658     fun (name, _, _, flags, _, _, _) ->
7659       let name2 = replace_char name '_' '-' in
7660       let alias =
7661         try find_map (function FishAlias n -> Some n | _ -> None) flags
7662         with Not_found -> name in
7663       pr "  if (";
7664       pr "STRCASEEQ (cmd, \"%s\")" name;
7665       if name <> name2 then
7666         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7667       if name <> alias then
7668         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7669       pr ")\n";
7670       pr "    return run_%s (cmd, argc, argv);\n" name;
7671       pr "  else\n";
7672   ) all_functions;
7673   pr "    {\n";
7674   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7675   pr "      if (command_num == 1)\n";
7676   pr "        extended_help_message ();\n";
7677   pr "      return -1;\n";
7678   pr "    }\n";
7679   pr "  return 0;\n";
7680   pr "}\n";
7681   pr "\n"
7682
7683 (* Readline completion for guestfish. *)
7684 and generate_fish_completion () =
7685   generate_header CStyle GPLv2plus;
7686
7687   let all_functions =
7688     List.filter (
7689       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7690     ) all_functions in
7691
7692   pr "\
7693 #include <config.h>
7694
7695 #include <stdio.h>
7696 #include <stdlib.h>
7697 #include <string.h>
7698
7699 #ifdef HAVE_LIBREADLINE
7700 #include <readline/readline.h>
7701 #endif
7702
7703 #include \"fish.h\"
7704
7705 #ifdef HAVE_LIBREADLINE
7706
7707 static const char *const commands[] = {
7708   BUILTIN_COMMANDS_FOR_COMPLETION,
7709 ";
7710
7711   (* Get the commands, including the aliases.  They don't need to be
7712    * sorted - the generator() function just does a dumb linear search.
7713    *)
7714   let commands =
7715     List.map (
7716       fun (name, _, _, flags, _, _, _) ->
7717         let name2 = replace_char name '_' '-' in
7718         let alias =
7719           try find_map (function FishAlias n -> Some n | _ -> None) flags
7720           with Not_found -> name in
7721
7722         if name <> alias then [name2; alias] else [name2]
7723     ) all_functions in
7724   let commands = List.flatten commands in
7725
7726   List.iter (pr "  \"%s\",\n") commands;
7727
7728   pr "  NULL
7729 };
7730
7731 static char *
7732 generator (const char *text, int state)
7733 {
7734   static int index, len;
7735   const char *name;
7736
7737   if (!state) {
7738     index = 0;
7739     len = strlen (text);
7740   }
7741
7742   rl_attempted_completion_over = 1;
7743
7744   while ((name = commands[index]) != NULL) {
7745     index++;
7746     if (STRCASEEQLEN (name, text, len))
7747       return strdup (name);
7748   }
7749
7750   return NULL;
7751 }
7752
7753 #endif /* HAVE_LIBREADLINE */
7754
7755 #ifdef HAVE_RL_COMPLETION_MATCHES
7756 #define RL_COMPLETION_MATCHES rl_completion_matches
7757 #else
7758 #ifdef HAVE_COMPLETION_MATCHES
7759 #define RL_COMPLETION_MATCHES completion_matches
7760 #endif
7761 #endif /* else just fail if we don't have either symbol */
7762
7763 char **
7764 do_completion (const char *text, int start, int end)
7765 {
7766   char **matches = NULL;
7767
7768 #ifdef HAVE_LIBREADLINE
7769   rl_completion_append_character = ' ';
7770
7771   if (start == 0)
7772     matches = RL_COMPLETION_MATCHES (text, generator);
7773   else if (complete_dest_paths)
7774     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7775 #endif
7776
7777   return matches;
7778 }
7779 ";
7780
7781 (* Generate the POD documentation for guestfish. *)
7782 and generate_fish_actions_pod () =
7783   let all_functions_sorted =
7784     List.filter (
7785       fun (_, _, _, flags, _, _, _) ->
7786         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7787     ) all_functions_sorted in
7788
7789   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7790
7791   List.iter (
7792     fun (name, style, _, flags, _, _, longdesc) ->
7793       let longdesc =
7794         Str.global_substitute rex (
7795           fun s ->
7796             let sub =
7797               try Str.matched_group 1 s
7798               with Not_found ->
7799                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7800             "C<" ^ replace_char sub '_' '-' ^ ">"
7801         ) longdesc in
7802       let name = replace_char name '_' '-' in
7803       let alias =
7804         try find_map (function FishAlias n -> Some n | _ -> None) flags
7805         with Not_found -> name in
7806
7807       pr "=head2 %s" name;
7808       if name <> alias then
7809         pr " | %s" alias;
7810       pr "\n";
7811       pr "\n";
7812       pr " %s" name;
7813       List.iter (
7814         function
7815         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7816         | OptString n -> pr " %s" n
7817         | StringList n | DeviceList n -> pr " '%s ...'" n
7818         | Bool _ -> pr " true|false"
7819         | Int n -> pr " %s" n
7820         | Int64 n -> pr " %s" n
7821         | FileIn n | FileOut n -> pr " (%s|-)" n
7822       ) (snd style);
7823       pr "\n";
7824       pr "\n";
7825       pr "%s\n\n" longdesc;
7826
7827       if List.exists (function FileIn _ | FileOut _ -> true
7828                       | _ -> false) (snd style) then
7829         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7830
7831       if List.mem ProtocolLimitWarning flags then
7832         pr "%s\n\n" protocol_limit_warning;
7833
7834       if List.mem DangerWillRobinson flags then
7835         pr "%s\n\n" danger_will_robinson;
7836
7837       match deprecation_notice flags with
7838       | None -> ()
7839       | Some txt -> pr "%s\n\n" txt
7840   ) all_functions_sorted
7841
7842 (* Generate a C function prototype. *)
7843 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7844     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7845     ?(prefix = "")
7846     ?handle name style =
7847   if extern then pr "extern ";
7848   if static then pr "static ";
7849   (match fst style with
7850    | RErr -> pr "int "
7851    | RInt _ -> pr "int "
7852    | RInt64 _ -> pr "int64_t "
7853    | RBool _ -> pr "int "
7854    | RConstString _ | RConstOptString _ -> pr "const char *"
7855    | RString _ | RBufferOut _ -> pr "char *"
7856    | RStringList _ | RHashtable _ -> pr "char **"
7857    | RStruct (_, typ) ->
7858        if not in_daemon then pr "struct guestfs_%s *" typ
7859        else pr "guestfs_int_%s *" typ
7860    | RStructList (_, typ) ->
7861        if not in_daemon then pr "struct guestfs_%s_list *" typ
7862        else pr "guestfs_int_%s_list *" typ
7863   );
7864   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7865   pr "%s%s (" prefix name;
7866   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7867     pr "void"
7868   else (
7869     let comma = ref false in
7870     (match handle with
7871      | None -> ()
7872      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7873     );
7874     let next () =
7875       if !comma then (
7876         if single_line then pr ", " else pr ",\n\t\t"
7877       );
7878       comma := true
7879     in
7880     List.iter (
7881       function
7882       | Pathname n
7883       | Device n | Dev_or_Path n
7884       | String n
7885       | OptString n ->
7886           next ();
7887           pr "const char *%s" n
7888       | StringList n | DeviceList n ->
7889           next ();
7890           pr "char *const *%s" n
7891       | Bool n -> next (); pr "int %s" n
7892       | Int n -> next (); pr "int %s" n
7893       | Int64 n -> next (); pr "int64_t %s" n
7894       | FileIn n
7895       | FileOut n ->
7896           if not in_daemon then (next (); pr "const char *%s" n)
7897     ) (snd style);
7898     if is_RBufferOut then (next (); pr "size_t *size_r");
7899   );
7900   pr ")";
7901   if semicolon then pr ";";
7902   if newline then pr "\n"
7903
7904 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7905 and generate_c_call_args ?handle ?(decl = false) style =
7906   pr "(";
7907   let comma = ref false in
7908   let next () =
7909     if !comma then pr ", ";
7910     comma := true
7911   in
7912   (match handle with
7913    | None -> ()
7914    | Some handle -> pr "%s" handle; comma := true
7915   );
7916   List.iter (
7917     fun arg ->
7918       next ();
7919       pr "%s" (name_of_argt arg)
7920   ) (snd style);
7921   (* For RBufferOut calls, add implicit &size parameter. *)
7922   if not decl then (
7923     match fst style with
7924     | RBufferOut _ ->
7925         next ();
7926         pr "&size"
7927     | _ -> ()
7928   );
7929   pr ")"
7930
7931 (* Generate the OCaml bindings interface. *)
7932 and generate_ocaml_mli () =
7933   generate_header OCamlStyle LGPLv2plus;
7934
7935   pr "\
7936 (** For API documentation you should refer to the C API
7937     in the guestfs(3) manual page.  The OCaml API uses almost
7938     exactly the same calls. *)
7939
7940 type t
7941 (** A [guestfs_h] handle. *)
7942
7943 exception Error of string
7944 (** This exception is raised when there is an error. *)
7945
7946 exception Handle_closed of string
7947 (** This exception is raised if you use a {!Guestfs.t} handle
7948     after calling {!close} on it.  The string is the name of
7949     the function. *)
7950
7951 val create : unit -> t
7952 (** Create a {!Guestfs.t} handle. *)
7953
7954 val close : t -> unit
7955 (** Close the {!Guestfs.t} handle and free up all resources used
7956     by it immediately.
7957
7958     Handles are closed by the garbage collector when they become
7959     unreferenced, but callers can call this in order to provide
7960     predictable cleanup. *)
7961
7962 ";
7963   generate_ocaml_structure_decls ();
7964
7965   (* The actions. *)
7966   List.iter (
7967     fun (name, style, _, _, _, shortdesc, _) ->
7968       generate_ocaml_prototype name style;
7969       pr "(** %s *)\n" shortdesc;
7970       pr "\n"
7971   ) all_functions_sorted
7972
7973 (* Generate the OCaml bindings implementation. *)
7974 and generate_ocaml_ml () =
7975   generate_header OCamlStyle LGPLv2plus;
7976
7977   pr "\
7978 type t
7979
7980 exception Error of string
7981 exception Handle_closed of string
7982
7983 external create : unit -> t = \"ocaml_guestfs_create\"
7984 external close : t -> unit = \"ocaml_guestfs_close\"
7985
7986 (* Give the exceptions names, so they can be raised from the C code. *)
7987 let () =
7988   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7989   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7990
7991 ";
7992
7993   generate_ocaml_structure_decls ();
7994
7995   (* The actions. *)
7996   List.iter (
7997     fun (name, style, _, _, _, shortdesc, _) ->
7998       generate_ocaml_prototype ~is_external:true name style;
7999   ) all_functions_sorted
8000
8001 (* Generate the OCaml bindings C implementation. *)
8002 and generate_ocaml_c () =
8003   generate_header CStyle LGPLv2plus;
8004
8005   pr "\
8006 #include <stdio.h>
8007 #include <stdlib.h>
8008 #include <string.h>
8009
8010 #include <caml/config.h>
8011 #include <caml/alloc.h>
8012 #include <caml/callback.h>
8013 #include <caml/fail.h>
8014 #include <caml/memory.h>
8015 #include <caml/mlvalues.h>
8016 #include <caml/signals.h>
8017
8018 #include <guestfs.h>
8019
8020 #include \"guestfs_c.h\"
8021
8022 /* Copy a hashtable of string pairs into an assoc-list.  We return
8023  * the list in reverse order, but hashtables aren't supposed to be
8024  * ordered anyway.
8025  */
8026 static CAMLprim value
8027 copy_table (char * const * argv)
8028 {
8029   CAMLparam0 ();
8030   CAMLlocal5 (rv, pairv, kv, vv, cons);
8031   int i;
8032
8033   rv = Val_int (0);
8034   for (i = 0; argv[i] != NULL; i += 2) {
8035     kv = caml_copy_string (argv[i]);
8036     vv = caml_copy_string (argv[i+1]);
8037     pairv = caml_alloc (2, 0);
8038     Store_field (pairv, 0, kv);
8039     Store_field (pairv, 1, vv);
8040     cons = caml_alloc (2, 0);
8041     Store_field (cons, 1, rv);
8042     rv = cons;
8043     Store_field (cons, 0, pairv);
8044   }
8045
8046   CAMLreturn (rv);
8047 }
8048
8049 ";
8050
8051   (* Struct copy functions. *)
8052
8053   let emit_ocaml_copy_list_function typ =
8054     pr "static CAMLprim value\n";
8055     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8056     pr "{\n";
8057     pr "  CAMLparam0 ();\n";
8058     pr "  CAMLlocal2 (rv, v);\n";
8059     pr "  unsigned int i;\n";
8060     pr "\n";
8061     pr "  if (%ss->len == 0)\n" typ;
8062     pr "    CAMLreturn (Atom (0));\n";
8063     pr "  else {\n";
8064     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8065     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8066     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8067     pr "      caml_modify (&Field (rv, i), v);\n";
8068     pr "    }\n";
8069     pr "    CAMLreturn (rv);\n";
8070     pr "  }\n";
8071     pr "}\n";
8072     pr "\n";
8073   in
8074
8075   List.iter (
8076     fun (typ, cols) ->
8077       let has_optpercent_col =
8078         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8079
8080       pr "static CAMLprim value\n";
8081       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8082       pr "{\n";
8083       pr "  CAMLparam0 ();\n";
8084       if has_optpercent_col then
8085         pr "  CAMLlocal3 (rv, v, v2);\n"
8086       else
8087         pr "  CAMLlocal2 (rv, v);\n";
8088       pr "\n";
8089       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8090       iteri (
8091         fun i col ->
8092           (match col with
8093            | name, FString ->
8094                pr "  v = caml_copy_string (%s->%s);\n" typ name
8095            | name, FBuffer ->
8096                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8097                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8098                  typ name typ name
8099            | name, FUUID ->
8100                pr "  v = caml_alloc_string (32);\n";
8101                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8102            | name, (FBytes|FInt64|FUInt64) ->
8103                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8104            | name, (FInt32|FUInt32) ->
8105                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8106            | name, FOptPercent ->
8107                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8108                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8109                pr "    v = caml_alloc (1, 0);\n";
8110                pr "    Store_field (v, 0, v2);\n";
8111                pr "  } else /* None */\n";
8112                pr "    v = Val_int (0);\n";
8113            | name, FChar ->
8114                pr "  v = Val_int (%s->%s);\n" typ name
8115           );
8116           pr "  Store_field (rv, %d, v);\n" i
8117       ) cols;
8118       pr "  CAMLreturn (rv);\n";
8119       pr "}\n";
8120       pr "\n";
8121   ) structs;
8122
8123   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8124   List.iter (
8125     function
8126     | typ, (RStructListOnly | RStructAndList) ->
8127         (* generate the function for typ *)
8128         emit_ocaml_copy_list_function typ
8129     | typ, _ -> () (* empty *)
8130   ) (rstructs_used_by all_functions);
8131
8132   (* The wrappers. *)
8133   List.iter (
8134     fun (name, style, _, _, _, _, _) ->
8135       pr "/* Automatically generated wrapper for function\n";
8136       pr " * ";
8137       generate_ocaml_prototype name style;
8138       pr " */\n";
8139       pr "\n";
8140
8141       let params =
8142         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8143
8144       let needs_extra_vs =
8145         match fst style with RConstOptString _ -> true | _ -> false in
8146
8147       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8148       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8149       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8150       pr "\n";
8151
8152       pr "CAMLprim value\n";
8153       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8154       List.iter (pr ", value %s") (List.tl params);
8155       pr ")\n";
8156       pr "{\n";
8157
8158       (match params with
8159        | [p1; p2; p3; p4; p5] ->
8160            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8161        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8162            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8163            pr "  CAMLxparam%d (%s);\n"
8164              (List.length rest) (String.concat ", " rest)
8165        | ps ->
8166            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8167       );
8168       if not needs_extra_vs then
8169         pr "  CAMLlocal1 (rv);\n"
8170       else
8171         pr "  CAMLlocal3 (rv, v, v2);\n";
8172       pr "\n";
8173
8174       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8175       pr "  if (g == NULL)\n";
8176       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8177       pr "\n";
8178
8179       List.iter (
8180         function
8181         | Pathname n
8182         | Device n | Dev_or_Path n
8183         | String n
8184         | FileIn n
8185         | FileOut n ->
8186             pr "  const char *%s = String_val (%sv);\n" n n
8187         | OptString n ->
8188             pr "  const char *%s =\n" n;
8189             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8190               n n
8191         | StringList n | DeviceList n ->
8192             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8193         | Bool n ->
8194             pr "  int %s = Bool_val (%sv);\n" n n
8195         | Int n ->
8196             pr "  int %s = Int_val (%sv);\n" n n
8197         | Int64 n ->
8198             pr "  int64_t %s = Int64_val (%sv);\n" n n
8199       ) (snd style);
8200       let error_code =
8201         match fst style with
8202         | RErr -> pr "  int r;\n"; "-1"
8203         | RInt _ -> pr "  int r;\n"; "-1"
8204         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8205         | RBool _ -> pr "  int r;\n"; "-1"
8206         | RConstString _ | RConstOptString _ ->
8207             pr "  const char *r;\n"; "NULL"
8208         | RString _ -> pr "  char *r;\n"; "NULL"
8209         | RStringList _ ->
8210             pr "  int i;\n";
8211             pr "  char **r;\n";
8212             "NULL"
8213         | RStruct (_, typ) ->
8214             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8215         | RStructList (_, typ) ->
8216             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8217         | RHashtable _ ->
8218             pr "  int i;\n";
8219             pr "  char **r;\n";
8220             "NULL"
8221         | RBufferOut _ ->
8222             pr "  char *r;\n";
8223             pr "  size_t size;\n";
8224             "NULL" in
8225       pr "\n";
8226
8227       pr "  caml_enter_blocking_section ();\n";
8228       pr "  r = guestfs_%s " name;
8229       generate_c_call_args ~handle:"g" style;
8230       pr ";\n";
8231       pr "  caml_leave_blocking_section ();\n";
8232
8233       List.iter (
8234         function
8235         | StringList n | DeviceList n ->
8236             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8237         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8238         | Bool _ | Int _ | Int64 _
8239         | FileIn _ | FileOut _ -> ()
8240       ) (snd style);
8241
8242       pr "  if (r == %s)\n" error_code;
8243       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8244       pr "\n";
8245
8246       (match fst style with
8247        | RErr -> pr "  rv = Val_unit;\n"
8248        | RInt _ -> pr "  rv = Val_int (r);\n"
8249        | RInt64 _ ->
8250            pr "  rv = caml_copy_int64 (r);\n"
8251        | RBool _ -> pr "  rv = Val_bool (r);\n"
8252        | RConstString _ ->
8253            pr "  rv = caml_copy_string (r);\n"
8254        | RConstOptString _ ->
8255            pr "  if (r) { /* Some string */\n";
8256            pr "    v = caml_alloc (1, 0);\n";
8257            pr "    v2 = caml_copy_string (r);\n";
8258            pr "    Store_field (v, 0, v2);\n";
8259            pr "  } else /* None */\n";
8260            pr "    v = Val_int (0);\n";
8261        | RString _ ->
8262            pr "  rv = caml_copy_string (r);\n";
8263            pr "  free (r);\n"
8264        | RStringList _ ->
8265            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8266            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8267            pr "  free (r);\n"
8268        | RStruct (_, typ) ->
8269            pr "  rv = copy_%s (r);\n" typ;
8270            pr "  guestfs_free_%s (r);\n" typ;
8271        | RStructList (_, typ) ->
8272            pr "  rv = copy_%s_list (r);\n" typ;
8273            pr "  guestfs_free_%s_list (r);\n" typ;
8274        | RHashtable _ ->
8275            pr "  rv = copy_table (r);\n";
8276            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8277            pr "  free (r);\n";
8278        | RBufferOut _ ->
8279            pr "  rv = caml_alloc_string (size);\n";
8280            pr "  memcpy (String_val (rv), r, size);\n";
8281       );
8282
8283       pr "  CAMLreturn (rv);\n";
8284       pr "}\n";
8285       pr "\n";
8286
8287       if List.length params > 5 then (
8288         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8289         pr "CAMLprim value ";
8290         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8291         pr "CAMLprim value\n";
8292         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8293         pr "{\n";
8294         pr "  return ocaml_guestfs_%s (argv[0]" name;
8295         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8296         pr ");\n";
8297         pr "}\n";
8298         pr "\n"
8299       )
8300   ) all_functions_sorted
8301
8302 and generate_ocaml_structure_decls () =
8303   List.iter (
8304     fun (typ, cols) ->
8305       pr "type %s = {\n" typ;
8306       List.iter (
8307         function
8308         | name, FString -> pr "  %s : string;\n" name
8309         | name, FBuffer -> pr "  %s : string;\n" name
8310         | name, FUUID -> pr "  %s : string;\n" name
8311         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8312         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8313         | name, FChar -> pr "  %s : char;\n" name
8314         | name, FOptPercent -> pr "  %s : float option;\n" name
8315       ) cols;
8316       pr "}\n";
8317       pr "\n"
8318   ) structs
8319
8320 and generate_ocaml_prototype ?(is_external = false) name style =
8321   if is_external then pr "external " else pr "val ";
8322   pr "%s : t -> " name;
8323   List.iter (
8324     function
8325     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8326     | OptString _ -> pr "string option -> "
8327     | StringList _ | DeviceList _ -> pr "string array -> "
8328     | Bool _ -> pr "bool -> "
8329     | Int _ -> pr "int -> "
8330     | Int64 _ -> pr "int64 -> "
8331   ) (snd style);
8332   (match fst style with
8333    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8334    | RInt _ -> pr "int"
8335    | RInt64 _ -> pr "int64"
8336    | RBool _ -> pr "bool"
8337    | RConstString _ -> pr "string"
8338    | RConstOptString _ -> pr "string option"
8339    | RString _ | RBufferOut _ -> pr "string"
8340    | RStringList _ -> pr "string array"
8341    | RStruct (_, typ) -> pr "%s" typ
8342    | RStructList (_, typ) -> pr "%s array" typ
8343    | RHashtable _ -> pr "(string * string) list"
8344   );
8345   if is_external then (
8346     pr " = ";
8347     if List.length (snd style) + 1 > 5 then
8348       pr "\"ocaml_guestfs_%s_byte\" " name;
8349     pr "\"ocaml_guestfs_%s\"" name
8350   );
8351   pr "\n"
8352
8353 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8354 and generate_perl_xs () =
8355   generate_header CStyle LGPLv2plus;
8356
8357   pr "\
8358 #include \"EXTERN.h\"
8359 #include \"perl.h\"
8360 #include \"XSUB.h\"
8361
8362 #include <guestfs.h>
8363
8364 #ifndef PRId64
8365 #define PRId64 \"lld\"
8366 #endif
8367
8368 static SV *
8369 my_newSVll(long long val) {
8370 #ifdef USE_64_BIT_ALL
8371   return newSViv(val);
8372 #else
8373   char buf[100];
8374   int len;
8375   len = snprintf(buf, 100, \"%%\" PRId64, val);
8376   return newSVpv(buf, len);
8377 #endif
8378 }
8379
8380 #ifndef PRIu64
8381 #define PRIu64 \"llu\"
8382 #endif
8383
8384 static SV *
8385 my_newSVull(unsigned long long val) {
8386 #ifdef USE_64_BIT_ALL
8387   return newSVuv(val);
8388 #else
8389   char buf[100];
8390   int len;
8391   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8392   return newSVpv(buf, len);
8393 #endif
8394 }
8395
8396 /* http://www.perlmonks.org/?node_id=680842 */
8397 static char **
8398 XS_unpack_charPtrPtr (SV *arg) {
8399   char **ret;
8400   AV *av;
8401   I32 i;
8402
8403   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8404     croak (\"array reference expected\");
8405
8406   av = (AV *)SvRV (arg);
8407   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8408   if (!ret)
8409     croak (\"malloc failed\");
8410
8411   for (i = 0; i <= av_len (av); i++) {
8412     SV **elem = av_fetch (av, i, 0);
8413
8414     if (!elem || !*elem)
8415       croak (\"missing element in list\");
8416
8417     ret[i] = SvPV_nolen (*elem);
8418   }
8419
8420   ret[i] = NULL;
8421
8422   return ret;
8423 }
8424
8425 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8426
8427 PROTOTYPES: ENABLE
8428
8429 guestfs_h *
8430 _create ()
8431    CODE:
8432       RETVAL = guestfs_create ();
8433       if (!RETVAL)
8434         croak (\"could not create guestfs handle\");
8435       guestfs_set_error_handler (RETVAL, NULL, NULL);
8436  OUTPUT:
8437       RETVAL
8438
8439 void
8440 DESTROY (g)
8441       guestfs_h *g;
8442  PPCODE:
8443       guestfs_close (g);
8444
8445 ";
8446
8447   List.iter (
8448     fun (name, style, _, _, _, _, _) ->
8449       (match fst style with
8450        | RErr -> pr "void\n"
8451        | RInt _ -> pr "SV *\n"
8452        | RInt64 _ -> pr "SV *\n"
8453        | RBool _ -> pr "SV *\n"
8454        | RConstString _ -> pr "SV *\n"
8455        | RConstOptString _ -> pr "SV *\n"
8456        | RString _ -> pr "SV *\n"
8457        | RBufferOut _ -> pr "SV *\n"
8458        | RStringList _
8459        | RStruct _ | RStructList _
8460        | RHashtable _ ->
8461            pr "void\n" (* all lists returned implictly on the stack *)
8462       );
8463       (* Call and arguments. *)
8464       pr "%s " name;
8465       generate_c_call_args ~handle:"g" ~decl:true style;
8466       pr "\n";
8467       pr "      guestfs_h *g;\n";
8468       iteri (
8469         fun i ->
8470           function
8471           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8472               pr "      char *%s;\n" n
8473           | OptString n ->
8474               (* http://www.perlmonks.org/?node_id=554277
8475                * Note that the implicit handle argument means we have
8476                * to add 1 to the ST(x) operator.
8477                *)
8478               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8479           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8480           | Bool n -> pr "      int %s;\n" n
8481           | Int n -> pr "      int %s;\n" n
8482           | Int64 n -> pr "      int64_t %s;\n" n
8483       ) (snd style);
8484
8485       let do_cleanups () =
8486         List.iter (
8487           function
8488           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8489           | Bool _ | Int _ | Int64 _
8490           | FileIn _ | FileOut _ -> ()
8491           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8492         ) (snd style)
8493       in
8494
8495       (* Code. *)
8496       (match fst style with
8497        | RErr ->
8498            pr "PREINIT:\n";
8499            pr "      int r;\n";
8500            pr " PPCODE:\n";
8501            pr "      r = guestfs_%s " name;
8502            generate_c_call_args ~handle:"g" style;
8503            pr ";\n";
8504            do_cleanups ();
8505            pr "      if (r == -1)\n";
8506            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8507        | RInt n
8508        | RBool n ->
8509            pr "PREINIT:\n";
8510            pr "      int %s;\n" n;
8511            pr "   CODE:\n";
8512            pr "      %s = guestfs_%s " n name;
8513            generate_c_call_args ~handle:"g" style;
8514            pr ";\n";
8515            do_cleanups ();
8516            pr "      if (%s == -1)\n" n;
8517            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8518            pr "      RETVAL = newSViv (%s);\n" n;
8519            pr " OUTPUT:\n";
8520            pr "      RETVAL\n"
8521        | RInt64 n ->
8522            pr "PREINIT:\n";
8523            pr "      int64_t %s;\n" n;
8524            pr "   CODE:\n";
8525            pr "      %s = guestfs_%s " n name;
8526            generate_c_call_args ~handle:"g" style;
8527            pr ";\n";
8528            do_cleanups ();
8529            pr "      if (%s == -1)\n" n;
8530            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8531            pr "      RETVAL = my_newSVll (%s);\n" n;
8532            pr " OUTPUT:\n";
8533            pr "      RETVAL\n"
8534        | RConstString n ->
8535            pr "PREINIT:\n";
8536            pr "      const char *%s;\n" n;
8537            pr "   CODE:\n";
8538            pr "      %s = guestfs_%s " n name;
8539            generate_c_call_args ~handle:"g" style;
8540            pr ";\n";
8541            do_cleanups ();
8542            pr "      if (%s == NULL)\n" n;
8543            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8544            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8545            pr " OUTPUT:\n";
8546            pr "      RETVAL\n"
8547        | RConstOptString n ->
8548            pr "PREINIT:\n";
8549            pr "      const char *%s;\n" n;
8550            pr "   CODE:\n";
8551            pr "      %s = guestfs_%s " n name;
8552            generate_c_call_args ~handle:"g" style;
8553            pr ";\n";
8554            do_cleanups ();
8555            pr "      if (%s == NULL)\n" n;
8556            pr "        RETVAL = &PL_sv_undef;\n";
8557            pr "      else\n";
8558            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8559            pr " OUTPUT:\n";
8560            pr "      RETVAL\n"
8561        | RString n ->
8562            pr "PREINIT:\n";
8563            pr "      char *%s;\n" n;
8564            pr "   CODE:\n";
8565            pr "      %s = guestfs_%s " n name;
8566            generate_c_call_args ~handle:"g" style;
8567            pr ";\n";
8568            do_cleanups ();
8569            pr "      if (%s == NULL)\n" n;
8570            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8571            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8572            pr "      free (%s);\n" n;
8573            pr " OUTPUT:\n";
8574            pr "      RETVAL\n"
8575        | RStringList n | RHashtable n ->
8576            pr "PREINIT:\n";
8577            pr "      char **%s;\n" n;
8578            pr "      int i, n;\n";
8579            pr " PPCODE:\n";
8580            pr "      %s = guestfs_%s " n name;
8581            generate_c_call_args ~handle:"g" style;
8582            pr ";\n";
8583            do_cleanups ();
8584            pr "      if (%s == NULL)\n" n;
8585            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8586            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8587            pr "      EXTEND (SP, n);\n";
8588            pr "      for (i = 0; i < n; ++i) {\n";
8589            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8590            pr "        free (%s[i]);\n" n;
8591            pr "      }\n";
8592            pr "      free (%s);\n" n;
8593        | RStruct (n, typ) ->
8594            let cols = cols_of_struct typ in
8595            generate_perl_struct_code typ cols name style n do_cleanups
8596        | RStructList (n, typ) ->
8597            let cols = cols_of_struct typ in
8598            generate_perl_struct_list_code typ cols name style n do_cleanups
8599        | RBufferOut n ->
8600            pr "PREINIT:\n";
8601            pr "      char *%s;\n" n;
8602            pr "      size_t size;\n";
8603            pr "   CODE:\n";
8604            pr "      %s = guestfs_%s " n name;
8605            generate_c_call_args ~handle:"g" style;
8606            pr ";\n";
8607            do_cleanups ();
8608            pr "      if (%s == NULL)\n" n;
8609            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8610            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8611            pr "      free (%s);\n" n;
8612            pr " OUTPUT:\n";
8613            pr "      RETVAL\n"
8614       );
8615
8616       pr "\n"
8617   ) all_functions
8618
8619 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8620   pr "PREINIT:\n";
8621   pr "      struct guestfs_%s_list *%s;\n" typ n;
8622   pr "      int i;\n";
8623   pr "      HV *hv;\n";
8624   pr " PPCODE:\n";
8625   pr "      %s = guestfs_%s " n name;
8626   generate_c_call_args ~handle:"g" style;
8627   pr ";\n";
8628   do_cleanups ();
8629   pr "      if (%s == NULL)\n" n;
8630   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8631   pr "      EXTEND (SP, %s->len);\n" n;
8632   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8633   pr "        hv = newHV ();\n";
8634   List.iter (
8635     function
8636     | name, FString ->
8637         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8638           name (String.length name) n name
8639     | name, FUUID ->
8640         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8641           name (String.length name) n name
8642     | name, FBuffer ->
8643         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8644           name (String.length name) n name n name
8645     | name, (FBytes|FUInt64) ->
8646         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8647           name (String.length name) n name
8648     | name, FInt64 ->
8649         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8650           name (String.length name) n name
8651     | name, (FInt32|FUInt32) ->
8652         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8653           name (String.length name) n name
8654     | name, FChar ->
8655         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8656           name (String.length name) n name
8657     | name, FOptPercent ->
8658         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8659           name (String.length name) n name
8660   ) cols;
8661   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8662   pr "      }\n";
8663   pr "      guestfs_free_%s_list (%s);\n" typ n
8664
8665 and generate_perl_struct_code typ cols name style n do_cleanups =
8666   pr "PREINIT:\n";
8667   pr "      struct guestfs_%s *%s;\n" typ n;
8668   pr " PPCODE:\n";
8669   pr "      %s = guestfs_%s " n name;
8670   generate_c_call_args ~handle:"g" style;
8671   pr ";\n";
8672   do_cleanups ();
8673   pr "      if (%s == NULL)\n" n;
8674   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8675   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8676   List.iter (
8677     fun ((name, _) as col) ->
8678       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8679
8680       match col with
8681       | name, FString ->
8682           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8683             n name
8684       | name, FBuffer ->
8685           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8686             n name n name
8687       | name, FUUID ->
8688           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8689             n name
8690       | name, (FBytes|FUInt64) ->
8691           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8692             n name
8693       | name, FInt64 ->
8694           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8695             n name
8696       | name, (FInt32|FUInt32) ->
8697           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8698             n name
8699       | name, FChar ->
8700           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8701             n name
8702       | name, FOptPercent ->
8703           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8704             n name
8705   ) cols;
8706   pr "      free (%s);\n" n
8707
8708 (* Generate Sys/Guestfs.pm. *)
8709 and generate_perl_pm () =
8710   generate_header HashStyle LGPLv2plus;
8711
8712   pr "\
8713 =pod
8714
8715 =head1 NAME
8716
8717 Sys::Guestfs - Perl bindings for libguestfs
8718
8719 =head1 SYNOPSIS
8720
8721  use Sys::Guestfs;
8722
8723  my $h = Sys::Guestfs->new ();
8724  $h->add_drive ('guest.img');
8725  $h->launch ();
8726  $h->mount ('/dev/sda1', '/');
8727  $h->touch ('/hello');
8728  $h->sync ();
8729
8730 =head1 DESCRIPTION
8731
8732 The C<Sys::Guestfs> module provides a Perl XS binding to the
8733 libguestfs API for examining and modifying virtual machine
8734 disk images.
8735
8736 Amongst the things this is good for: making batch configuration
8737 changes to guests, getting disk used/free statistics (see also:
8738 virt-df), migrating between virtualization systems (see also:
8739 virt-p2v), performing partial backups, performing partial guest
8740 clones, cloning guests and changing registry/UUID/hostname info, and
8741 much else besides.
8742
8743 Libguestfs uses Linux kernel and qemu code, and can access any type of
8744 guest filesystem that Linux and qemu can, including but not limited
8745 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8746 schemes, qcow, qcow2, vmdk.
8747
8748 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8749 LVs, what filesystem is in each LV, etc.).  It can also run commands
8750 in the context of the guest.  Also you can access filesystems over
8751 FUSE.
8752
8753 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8754 functions for using libguestfs from Perl, including integration
8755 with libvirt.
8756
8757 =head1 ERRORS
8758
8759 All errors turn into calls to C<croak> (see L<Carp(3)>).
8760
8761 =head1 METHODS
8762
8763 =over 4
8764
8765 =cut
8766
8767 package Sys::Guestfs;
8768
8769 use strict;
8770 use warnings;
8771
8772 require XSLoader;
8773 XSLoader::load ('Sys::Guestfs');
8774
8775 =item $h = Sys::Guestfs->new ();
8776
8777 Create a new guestfs handle.
8778
8779 =cut
8780
8781 sub new {
8782   my $proto = shift;
8783   my $class = ref ($proto) || $proto;
8784
8785   my $self = Sys::Guestfs::_create ();
8786   bless $self, $class;
8787   return $self;
8788 }
8789
8790 ";
8791
8792   (* Actions.  We only need to print documentation for these as
8793    * they are pulled in from the XS code automatically.
8794    *)
8795   List.iter (
8796     fun (name, style, _, flags, _, _, longdesc) ->
8797       if not (List.mem NotInDocs flags) then (
8798         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8799         pr "=item ";
8800         generate_perl_prototype name style;
8801         pr "\n\n";
8802         pr "%s\n\n" longdesc;
8803         if List.mem ProtocolLimitWarning flags then
8804           pr "%s\n\n" protocol_limit_warning;
8805         if List.mem DangerWillRobinson flags then
8806           pr "%s\n\n" danger_will_robinson;
8807         match deprecation_notice flags with
8808         | None -> ()
8809         | Some txt -> pr "%s\n\n" txt
8810       )
8811   ) all_functions_sorted;
8812
8813   (* End of file. *)
8814   pr "\
8815 =cut
8816
8817 1;
8818
8819 =back
8820
8821 =head1 COPYRIGHT
8822
8823 Copyright (C) %s Red Hat Inc.
8824
8825 =head1 LICENSE
8826
8827 Please see the file COPYING.LIB for the full license.
8828
8829 =head1 SEE ALSO
8830
8831 L<guestfs(3)>,
8832 L<guestfish(1)>,
8833 L<http://libguestfs.org>,
8834 L<Sys::Guestfs::Lib(3)>.
8835
8836 =cut
8837 " copyright_years
8838
8839 and generate_perl_prototype name style =
8840   (match fst style with
8841    | RErr -> ()
8842    | RBool n
8843    | RInt n
8844    | RInt64 n
8845    | RConstString n
8846    | RConstOptString n
8847    | RString n
8848    | RBufferOut n -> pr "$%s = " n
8849    | RStruct (n,_)
8850    | RHashtable n -> pr "%%%s = " n
8851    | RStringList n
8852    | RStructList (n,_) -> pr "@%s = " n
8853   );
8854   pr "$h->%s (" name;
8855   let comma = ref false in
8856   List.iter (
8857     fun arg ->
8858       if !comma then pr ", ";
8859       comma := true;
8860       match arg with
8861       | Pathname n | Device n | Dev_or_Path n | String n
8862       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8863           pr "$%s" n
8864       | StringList n | DeviceList n ->
8865           pr "\\@%s" n
8866   ) (snd style);
8867   pr ");"
8868
8869 (* Generate Python C module. *)
8870 and generate_python_c () =
8871   generate_header CStyle LGPLv2plus;
8872
8873   pr "\
8874 #include <Python.h>
8875
8876 #include <stdio.h>
8877 #include <stdlib.h>
8878 #include <assert.h>
8879
8880 #include \"guestfs.h\"
8881
8882 typedef struct {
8883   PyObject_HEAD
8884   guestfs_h *g;
8885 } Pyguestfs_Object;
8886
8887 static guestfs_h *
8888 get_handle (PyObject *obj)
8889 {
8890   assert (obj);
8891   assert (obj != Py_None);
8892   return ((Pyguestfs_Object *) obj)->g;
8893 }
8894
8895 static PyObject *
8896 put_handle (guestfs_h *g)
8897 {
8898   assert (g);
8899   return
8900     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8901 }
8902
8903 /* This list should be freed (but not the strings) after use. */
8904 static char **
8905 get_string_list (PyObject *obj)
8906 {
8907   int i, len;
8908   char **r;
8909
8910   assert (obj);
8911
8912   if (!PyList_Check (obj)) {
8913     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8914     return NULL;
8915   }
8916
8917   len = PyList_Size (obj);
8918   r = malloc (sizeof (char *) * (len+1));
8919   if (r == NULL) {
8920     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8921     return NULL;
8922   }
8923
8924   for (i = 0; i < len; ++i)
8925     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8926   r[len] = NULL;
8927
8928   return r;
8929 }
8930
8931 static PyObject *
8932 put_string_list (char * const * const argv)
8933 {
8934   PyObject *list;
8935   int argc, i;
8936
8937   for (argc = 0; argv[argc] != NULL; ++argc)
8938     ;
8939
8940   list = PyList_New (argc);
8941   for (i = 0; i < argc; ++i)
8942     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8943
8944   return list;
8945 }
8946
8947 static PyObject *
8948 put_table (char * const * const argv)
8949 {
8950   PyObject *list, *item;
8951   int argc, i;
8952
8953   for (argc = 0; argv[argc] != NULL; ++argc)
8954     ;
8955
8956   list = PyList_New (argc >> 1);
8957   for (i = 0; i < argc; i += 2) {
8958     item = PyTuple_New (2);
8959     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8960     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8961     PyList_SetItem (list, i >> 1, item);
8962   }
8963
8964   return list;
8965 }
8966
8967 static void
8968 free_strings (char **argv)
8969 {
8970   int argc;
8971
8972   for (argc = 0; argv[argc] != NULL; ++argc)
8973     free (argv[argc]);
8974   free (argv);
8975 }
8976
8977 static PyObject *
8978 py_guestfs_create (PyObject *self, PyObject *args)
8979 {
8980   guestfs_h *g;
8981
8982   g = guestfs_create ();
8983   if (g == NULL) {
8984     PyErr_SetString (PyExc_RuntimeError,
8985                      \"guestfs.create: failed to allocate handle\");
8986     return NULL;
8987   }
8988   guestfs_set_error_handler (g, NULL, NULL);
8989   return put_handle (g);
8990 }
8991
8992 static PyObject *
8993 py_guestfs_close (PyObject *self, PyObject *args)
8994 {
8995   PyObject *py_g;
8996   guestfs_h *g;
8997
8998   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8999     return NULL;
9000   g = get_handle (py_g);
9001
9002   guestfs_close (g);
9003
9004   Py_INCREF (Py_None);
9005   return Py_None;
9006 }
9007
9008 ";
9009
9010   let emit_put_list_function typ =
9011     pr "static PyObject *\n";
9012     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9013     pr "{\n";
9014     pr "  PyObject *list;\n";
9015     pr "  int i;\n";
9016     pr "\n";
9017     pr "  list = PyList_New (%ss->len);\n" typ;
9018     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9019     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9020     pr "  return list;\n";
9021     pr "};\n";
9022     pr "\n"
9023   in
9024
9025   (* Structures, turned into Python dictionaries. *)
9026   List.iter (
9027     fun (typ, cols) ->
9028       pr "static PyObject *\n";
9029       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9030       pr "{\n";
9031       pr "  PyObject *dict;\n";
9032       pr "\n";
9033       pr "  dict = PyDict_New ();\n";
9034       List.iter (
9035         function
9036         | name, FString ->
9037             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9038             pr "                        PyString_FromString (%s->%s));\n"
9039               typ name
9040         | name, FBuffer ->
9041             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9042             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9043               typ name typ name
9044         | name, FUUID ->
9045             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9046             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9047               typ name
9048         | name, (FBytes|FUInt64) ->
9049             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9050             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9051               typ name
9052         | name, FInt64 ->
9053             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9054             pr "                        PyLong_FromLongLong (%s->%s));\n"
9055               typ name
9056         | name, FUInt32 ->
9057             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9058             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9059               typ name
9060         | name, FInt32 ->
9061             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9062             pr "                        PyLong_FromLong (%s->%s));\n"
9063               typ name
9064         | name, FOptPercent ->
9065             pr "  if (%s->%s >= 0)\n" typ name;
9066             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9067             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9068               typ name;
9069             pr "  else {\n";
9070             pr "    Py_INCREF (Py_None);\n";
9071             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9072             pr "  }\n"
9073         | name, FChar ->
9074             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9075             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9076       ) cols;
9077       pr "  return dict;\n";
9078       pr "};\n";
9079       pr "\n";
9080
9081   ) structs;
9082
9083   (* Emit a put_TYPE_list function definition only if that function is used. *)
9084   List.iter (
9085     function
9086     | typ, (RStructListOnly | RStructAndList) ->
9087         (* generate the function for typ *)
9088         emit_put_list_function typ
9089     | typ, _ -> () (* empty *)
9090   ) (rstructs_used_by all_functions);
9091
9092   (* Python wrapper functions. *)
9093   List.iter (
9094     fun (name, style, _, _, _, _, _) ->
9095       pr "static PyObject *\n";
9096       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9097       pr "{\n";
9098
9099       pr "  PyObject *py_g;\n";
9100       pr "  guestfs_h *g;\n";
9101       pr "  PyObject *py_r;\n";
9102
9103       let error_code =
9104         match fst style with
9105         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9106         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9107         | RConstString _ | RConstOptString _ ->
9108             pr "  const char *r;\n"; "NULL"
9109         | RString _ -> pr "  char *r;\n"; "NULL"
9110         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9111         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9112         | RStructList (_, typ) ->
9113             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9114         | RBufferOut _ ->
9115             pr "  char *r;\n";
9116             pr "  size_t size;\n";
9117             "NULL" in
9118
9119       List.iter (
9120         function
9121         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9122             pr "  const char *%s;\n" n
9123         | OptString n -> pr "  const char *%s;\n" n
9124         | StringList n | DeviceList n ->
9125             pr "  PyObject *py_%s;\n" n;
9126             pr "  char **%s;\n" n
9127         | Bool n -> pr "  int %s;\n" n
9128         | Int n -> pr "  int %s;\n" n
9129         | Int64 n -> pr "  long long %s;\n" n
9130       ) (snd style);
9131
9132       pr "\n";
9133
9134       (* Convert the parameters. *)
9135       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9136       List.iter (
9137         function
9138         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9139         | OptString _ -> pr "z"
9140         | StringList _ | DeviceList _ -> pr "O"
9141         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9142         | Int _ -> pr "i"
9143         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9144                              * emulate C's int/long/long long in Python?
9145                              *)
9146       ) (snd style);
9147       pr ":guestfs_%s\",\n" name;
9148       pr "                         &py_g";
9149       List.iter (
9150         function
9151         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9152         | OptString n -> pr ", &%s" n
9153         | StringList n | DeviceList n -> pr ", &py_%s" n
9154         | Bool n -> pr ", &%s" n
9155         | Int n -> pr ", &%s" n
9156         | Int64 n -> pr ", &%s" n
9157       ) (snd style);
9158
9159       pr "))\n";
9160       pr "    return NULL;\n";
9161
9162       pr "  g = get_handle (py_g);\n";
9163       List.iter (
9164         function
9165         | Pathname _ | Device _ | Dev_or_Path _ | String _
9166         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9167         | StringList n | DeviceList n ->
9168             pr "  %s = get_string_list (py_%s);\n" n n;
9169             pr "  if (!%s) return NULL;\n" n
9170       ) (snd style);
9171
9172       pr "\n";
9173
9174       pr "  r = guestfs_%s " name;
9175       generate_c_call_args ~handle:"g" style;
9176       pr ";\n";
9177
9178       List.iter (
9179         function
9180         | Pathname _ | Device _ | Dev_or_Path _ | String _
9181         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9182         | StringList n | DeviceList n ->
9183             pr "  free (%s);\n" n
9184       ) (snd style);
9185
9186       pr "  if (r == %s) {\n" error_code;
9187       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9188       pr "    return NULL;\n";
9189       pr "  }\n";
9190       pr "\n";
9191
9192       (match fst style with
9193        | RErr ->
9194            pr "  Py_INCREF (Py_None);\n";
9195            pr "  py_r = Py_None;\n"
9196        | RInt _
9197        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9198        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9199        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9200        | RConstOptString _ ->
9201            pr "  if (r)\n";
9202            pr "    py_r = PyString_FromString (r);\n";
9203            pr "  else {\n";
9204            pr "    Py_INCREF (Py_None);\n";
9205            pr "    py_r = Py_None;\n";
9206            pr "  }\n"
9207        | RString _ ->
9208            pr "  py_r = PyString_FromString (r);\n";
9209            pr "  free (r);\n"
9210        | RStringList _ ->
9211            pr "  py_r = put_string_list (r);\n";
9212            pr "  free_strings (r);\n"
9213        | RStruct (_, typ) ->
9214            pr "  py_r = put_%s (r);\n" typ;
9215            pr "  guestfs_free_%s (r);\n" typ
9216        | RStructList (_, typ) ->
9217            pr "  py_r = put_%s_list (r);\n" typ;
9218            pr "  guestfs_free_%s_list (r);\n" typ
9219        | RHashtable n ->
9220            pr "  py_r = put_table (r);\n";
9221            pr "  free_strings (r);\n"
9222        | RBufferOut _ ->
9223            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9224            pr "  free (r);\n"
9225       );
9226
9227       pr "  return py_r;\n";
9228       pr "}\n";
9229       pr "\n"
9230   ) all_functions;
9231
9232   (* Table of functions. *)
9233   pr "static PyMethodDef methods[] = {\n";
9234   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9235   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9236   List.iter (
9237     fun (name, _, _, _, _, _, _) ->
9238       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9239         name name
9240   ) all_functions;
9241   pr "  { NULL, NULL, 0, NULL }\n";
9242   pr "};\n";
9243   pr "\n";
9244
9245   (* Init function. *)
9246   pr "\
9247 void
9248 initlibguestfsmod (void)
9249 {
9250   static int initialized = 0;
9251
9252   if (initialized) return;
9253   Py_InitModule ((char *) \"libguestfsmod\", methods);
9254   initialized = 1;
9255 }
9256 "
9257
9258 (* Generate Python module. *)
9259 and generate_python_py () =
9260   generate_header HashStyle LGPLv2plus;
9261
9262   pr "\
9263 u\"\"\"Python bindings for libguestfs
9264
9265 import guestfs
9266 g = guestfs.GuestFS ()
9267 g.add_drive (\"guest.img\")
9268 g.launch ()
9269 parts = g.list_partitions ()
9270
9271 The guestfs module provides a Python binding to the libguestfs API
9272 for examining and modifying virtual machine disk images.
9273
9274 Amongst the things this is good for: making batch configuration
9275 changes to guests, getting disk used/free statistics (see also:
9276 virt-df), migrating between virtualization systems (see also:
9277 virt-p2v), performing partial backups, performing partial guest
9278 clones, cloning guests and changing registry/UUID/hostname info, and
9279 much else besides.
9280
9281 Libguestfs uses Linux kernel and qemu code, and can access any type of
9282 guest filesystem that Linux and qemu can, including but not limited
9283 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9284 schemes, qcow, qcow2, vmdk.
9285
9286 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9287 LVs, what filesystem is in each LV, etc.).  It can also run commands
9288 in the context of the guest.  Also you can access filesystems over
9289 FUSE.
9290
9291 Errors which happen while using the API are turned into Python
9292 RuntimeError exceptions.
9293
9294 To create a guestfs handle you usually have to perform the following
9295 sequence of calls:
9296
9297 # Create the handle, call add_drive at least once, and possibly
9298 # several times if the guest has multiple block devices:
9299 g = guestfs.GuestFS ()
9300 g.add_drive (\"guest.img\")
9301
9302 # Launch the qemu subprocess and wait for it to become ready:
9303 g.launch ()
9304
9305 # Now you can issue commands, for example:
9306 logvols = g.lvs ()
9307
9308 \"\"\"
9309
9310 import libguestfsmod
9311
9312 class GuestFS:
9313     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9314
9315     def __init__ (self):
9316         \"\"\"Create a new libguestfs handle.\"\"\"
9317         self._o = libguestfsmod.create ()
9318
9319     def __del__ (self):
9320         libguestfsmod.close (self._o)
9321
9322 ";
9323
9324   List.iter (
9325     fun (name, style, _, flags, _, _, longdesc) ->
9326       pr "    def %s " name;
9327       generate_py_call_args ~handle:"self" (snd style);
9328       pr ":\n";
9329
9330       if not (List.mem NotInDocs flags) then (
9331         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9332         let doc =
9333           match fst style with
9334           | RErr | RInt _ | RInt64 _ | RBool _
9335           | RConstOptString _ | RConstString _
9336           | RString _ | RBufferOut _ -> doc
9337           | RStringList _ ->
9338               doc ^ "\n\nThis function returns a list of strings."
9339           | RStruct (_, typ) ->
9340               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9341           | RStructList (_, typ) ->
9342               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9343           | RHashtable _ ->
9344               doc ^ "\n\nThis function returns a dictionary." in
9345         let doc =
9346           if List.mem ProtocolLimitWarning flags then
9347             doc ^ "\n\n" ^ protocol_limit_warning
9348           else doc in
9349         let doc =
9350           if List.mem DangerWillRobinson flags then
9351             doc ^ "\n\n" ^ danger_will_robinson
9352           else doc in
9353         let doc =
9354           match deprecation_notice flags with
9355           | None -> doc
9356           | Some txt -> doc ^ "\n\n" ^ txt in
9357         let doc = pod2text ~width:60 name doc in
9358         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9359         let doc = String.concat "\n        " doc in
9360         pr "        u\"\"\"%s\"\"\"\n" doc;
9361       );
9362       pr "        return libguestfsmod.%s " name;
9363       generate_py_call_args ~handle:"self._o" (snd style);
9364       pr "\n";
9365       pr "\n";
9366   ) all_functions
9367
9368 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9369 and generate_py_call_args ~handle args =
9370   pr "(%s" handle;
9371   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9372   pr ")"
9373
9374 (* Useful if you need the longdesc POD text as plain text.  Returns a
9375  * list of lines.
9376  *
9377  * Because this is very slow (the slowest part of autogeneration),
9378  * we memoize the results.
9379  *)
9380 and pod2text ~width name longdesc =
9381   let key = width, name, longdesc in
9382   try Hashtbl.find pod2text_memo key
9383   with Not_found ->
9384     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9385     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9386     close_out chan;
9387     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9388     let chan = open_process_in cmd in
9389     let lines = ref [] in
9390     let rec loop i =
9391       let line = input_line chan in
9392       if i = 1 then             (* discard the first line of output *)
9393         loop (i+1)
9394       else (
9395         let line = triml line in
9396         lines := line :: !lines;
9397         loop (i+1)
9398       ) in
9399     let lines = try loop 1 with End_of_file -> List.rev !lines in
9400     unlink filename;
9401     (match close_process_in chan with
9402      | WEXITED 0 -> ()
9403      | WEXITED i ->
9404          failwithf "pod2text: process exited with non-zero status (%d)" i
9405      | WSIGNALED i | WSTOPPED i ->
9406          failwithf "pod2text: process signalled or stopped by signal %d" i
9407     );
9408     Hashtbl.add pod2text_memo key lines;
9409     pod2text_memo_updated ();
9410     lines
9411
9412 (* Generate ruby bindings. *)
9413 and generate_ruby_c () =
9414   generate_header CStyle LGPLv2plus;
9415
9416   pr "\
9417 #include <stdio.h>
9418 #include <stdlib.h>
9419
9420 #include <ruby.h>
9421
9422 #include \"guestfs.h\"
9423
9424 #include \"extconf.h\"
9425
9426 /* For Ruby < 1.9 */
9427 #ifndef RARRAY_LEN
9428 #define RARRAY_LEN(r) (RARRAY((r))->len)
9429 #endif
9430
9431 static VALUE m_guestfs;                 /* guestfs module */
9432 static VALUE c_guestfs;                 /* guestfs_h handle */
9433 static VALUE e_Error;                   /* used for all errors */
9434
9435 static void ruby_guestfs_free (void *p)
9436 {
9437   if (!p) return;
9438   guestfs_close ((guestfs_h *) p);
9439 }
9440
9441 static VALUE ruby_guestfs_create (VALUE m)
9442 {
9443   guestfs_h *g;
9444
9445   g = guestfs_create ();
9446   if (!g)
9447     rb_raise (e_Error, \"failed to create guestfs handle\");
9448
9449   /* Don't print error messages to stderr by default. */
9450   guestfs_set_error_handler (g, NULL, NULL);
9451
9452   /* Wrap it, and make sure the close function is called when the
9453    * handle goes away.
9454    */
9455   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9456 }
9457
9458 static VALUE ruby_guestfs_close (VALUE gv)
9459 {
9460   guestfs_h *g;
9461   Data_Get_Struct (gv, guestfs_h, g);
9462
9463   ruby_guestfs_free (g);
9464   DATA_PTR (gv) = NULL;
9465
9466   return Qnil;
9467 }
9468
9469 ";
9470
9471   List.iter (
9472     fun (name, style, _, _, _, _, _) ->
9473       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9474       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9475       pr ")\n";
9476       pr "{\n";
9477       pr "  guestfs_h *g;\n";
9478       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9479       pr "  if (!g)\n";
9480       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9481         name;
9482       pr "\n";
9483
9484       List.iter (
9485         function
9486         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9487             pr "  Check_Type (%sv, T_STRING);\n" n;
9488             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9489             pr "  if (!%s)\n" n;
9490             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9491             pr "              \"%s\", \"%s\");\n" n name
9492         | OptString n ->
9493             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9494         | StringList n | DeviceList n ->
9495             pr "  char **%s;\n" n;
9496             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9497             pr "  {\n";
9498             pr "    int i, len;\n";
9499             pr "    len = RARRAY_LEN (%sv);\n" n;
9500             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9501               n;
9502             pr "    for (i = 0; i < len; ++i) {\n";
9503             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9504             pr "      %s[i] = StringValueCStr (v);\n" n;
9505             pr "    }\n";
9506             pr "    %s[len] = NULL;\n" n;
9507             pr "  }\n";
9508         | Bool n ->
9509             pr "  int %s = RTEST (%sv);\n" n n
9510         | Int n ->
9511             pr "  int %s = NUM2INT (%sv);\n" n n
9512         | Int64 n ->
9513             pr "  long long %s = NUM2LL (%sv);\n" n n
9514       ) (snd style);
9515       pr "\n";
9516
9517       let error_code =
9518         match fst style with
9519         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9520         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9521         | RConstString _ | RConstOptString _ ->
9522             pr "  const char *r;\n"; "NULL"
9523         | RString _ -> pr "  char *r;\n"; "NULL"
9524         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9525         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9526         | RStructList (_, typ) ->
9527             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9528         | RBufferOut _ ->
9529             pr "  char *r;\n";
9530             pr "  size_t size;\n";
9531             "NULL" in
9532       pr "\n";
9533
9534       pr "  r = guestfs_%s " name;
9535       generate_c_call_args ~handle:"g" style;
9536       pr ";\n";
9537
9538       List.iter (
9539         function
9540         | Pathname _ | Device _ | Dev_or_Path _ | String _
9541         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9542         | StringList n | DeviceList n ->
9543             pr "  free (%s);\n" n
9544       ) (snd style);
9545
9546       pr "  if (r == %s)\n" error_code;
9547       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9548       pr "\n";
9549
9550       (match fst style with
9551        | RErr ->
9552            pr "  return Qnil;\n"
9553        | RInt _ | RBool _ ->
9554            pr "  return INT2NUM (r);\n"
9555        | RInt64 _ ->
9556            pr "  return ULL2NUM (r);\n"
9557        | RConstString _ ->
9558            pr "  return rb_str_new2 (r);\n";
9559        | RConstOptString _ ->
9560            pr "  if (r)\n";
9561            pr "    return rb_str_new2 (r);\n";
9562            pr "  else\n";
9563            pr "    return Qnil;\n";
9564        | RString _ ->
9565            pr "  VALUE rv = rb_str_new2 (r);\n";
9566            pr "  free (r);\n";
9567            pr "  return rv;\n";
9568        | RStringList _ ->
9569            pr "  int i, len = 0;\n";
9570            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9571            pr "  VALUE rv = rb_ary_new2 (len);\n";
9572            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9573            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9574            pr "    free (r[i]);\n";
9575            pr "  }\n";
9576            pr "  free (r);\n";
9577            pr "  return rv;\n"
9578        | RStruct (_, typ) ->
9579            let cols = cols_of_struct typ in
9580            generate_ruby_struct_code typ cols
9581        | RStructList (_, typ) ->
9582            let cols = cols_of_struct typ in
9583            generate_ruby_struct_list_code typ cols
9584        | RHashtable _ ->
9585            pr "  VALUE rv = rb_hash_new ();\n";
9586            pr "  int i;\n";
9587            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9588            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9589            pr "    free (r[i]);\n";
9590            pr "    free (r[i+1]);\n";
9591            pr "  }\n";
9592            pr "  free (r);\n";
9593            pr "  return rv;\n"
9594        | RBufferOut _ ->
9595            pr "  VALUE rv = rb_str_new (r, size);\n";
9596            pr "  free (r);\n";
9597            pr "  return rv;\n";
9598       );
9599
9600       pr "}\n";
9601       pr "\n"
9602   ) all_functions;
9603
9604   pr "\
9605 /* Initialize the module. */
9606 void Init__guestfs ()
9607 {
9608   m_guestfs = rb_define_module (\"Guestfs\");
9609   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9610   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9611
9612   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9613   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9614
9615 ";
9616   (* Define the rest of the methods. *)
9617   List.iter (
9618     fun (name, style, _, _, _, _, _) ->
9619       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9620       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9621   ) all_functions;
9622
9623   pr "}\n"
9624
9625 (* Ruby code to return a struct. *)
9626 and generate_ruby_struct_code typ cols =
9627   pr "  VALUE rv = rb_hash_new ();\n";
9628   List.iter (
9629     function
9630     | name, FString ->
9631         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9632     | name, FBuffer ->
9633         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9634     | name, FUUID ->
9635         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9636     | name, (FBytes|FUInt64) ->
9637         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9638     | name, FInt64 ->
9639         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9640     | name, FUInt32 ->
9641         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9642     | name, FInt32 ->
9643         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9644     | name, FOptPercent ->
9645         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9646     | name, FChar -> (* XXX wrong? *)
9647         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9648   ) cols;
9649   pr "  guestfs_free_%s (r);\n" typ;
9650   pr "  return rv;\n"
9651
9652 (* Ruby code to return a struct list. *)
9653 and generate_ruby_struct_list_code typ cols =
9654   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9655   pr "  int i;\n";
9656   pr "  for (i = 0; i < r->len; ++i) {\n";
9657   pr "    VALUE hv = rb_hash_new ();\n";
9658   List.iter (
9659     function
9660     | name, FString ->
9661         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9662     | name, FBuffer ->
9663         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
9664     | name, FUUID ->
9665         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9666     | name, (FBytes|FUInt64) ->
9667         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9668     | name, FInt64 ->
9669         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9670     | name, FUInt32 ->
9671         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9672     | name, FInt32 ->
9673         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9674     | name, FOptPercent ->
9675         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9676     | name, FChar -> (* XXX wrong? *)
9677         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9678   ) cols;
9679   pr "    rb_ary_push (rv, hv);\n";
9680   pr "  }\n";
9681   pr "  guestfs_free_%s_list (r);\n" typ;
9682   pr "  return rv;\n"
9683
9684 (* Generate Java bindings GuestFS.java file. *)
9685 and generate_java_java () =
9686   generate_header CStyle LGPLv2plus;
9687
9688   pr "\
9689 package com.redhat.et.libguestfs;
9690
9691 import java.util.HashMap;
9692 import com.redhat.et.libguestfs.LibGuestFSException;
9693 import com.redhat.et.libguestfs.PV;
9694 import com.redhat.et.libguestfs.VG;
9695 import com.redhat.et.libguestfs.LV;
9696 import com.redhat.et.libguestfs.Stat;
9697 import com.redhat.et.libguestfs.StatVFS;
9698 import com.redhat.et.libguestfs.IntBool;
9699 import com.redhat.et.libguestfs.Dirent;
9700
9701 /**
9702  * The GuestFS object is a libguestfs handle.
9703  *
9704  * @author rjones
9705  */
9706 public class GuestFS {
9707   // Load the native code.
9708   static {
9709     System.loadLibrary (\"guestfs_jni\");
9710   }
9711
9712   /**
9713    * The native guestfs_h pointer.
9714    */
9715   long g;
9716
9717   /**
9718    * Create a libguestfs handle.
9719    *
9720    * @throws LibGuestFSException
9721    */
9722   public GuestFS () throws LibGuestFSException
9723   {
9724     g = _create ();
9725   }
9726   private native long _create () throws LibGuestFSException;
9727
9728   /**
9729    * Close a libguestfs handle.
9730    *
9731    * You can also leave handles to be collected by the garbage
9732    * collector, but this method ensures that the resources used
9733    * by the handle are freed up immediately.  If you call any
9734    * other methods after closing the handle, you will get an
9735    * exception.
9736    *
9737    * @throws LibGuestFSException
9738    */
9739   public void close () throws LibGuestFSException
9740   {
9741     if (g != 0)
9742       _close (g);
9743     g = 0;
9744   }
9745   private native void _close (long g) throws LibGuestFSException;
9746
9747   public void finalize () throws LibGuestFSException
9748   {
9749     close ();
9750   }
9751
9752 ";
9753
9754   List.iter (
9755     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9756       if not (List.mem NotInDocs flags); then (
9757         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9758         let doc =
9759           if List.mem ProtocolLimitWarning flags then
9760             doc ^ "\n\n" ^ protocol_limit_warning
9761           else doc in
9762         let doc =
9763           if List.mem DangerWillRobinson flags then
9764             doc ^ "\n\n" ^ danger_will_robinson
9765           else doc in
9766         let doc =
9767           match deprecation_notice flags with
9768           | None -> doc
9769           | Some txt -> doc ^ "\n\n" ^ txt in
9770         let doc = pod2text ~width:60 name doc in
9771         let doc = List.map (            (* RHBZ#501883 *)
9772           function
9773           | "" -> "<p>"
9774           | nonempty -> nonempty
9775         ) doc in
9776         let doc = String.concat "\n   * " doc in
9777
9778         pr "  /**\n";
9779         pr "   * %s\n" shortdesc;
9780         pr "   * <p>\n";
9781         pr "   * %s\n" doc;
9782         pr "   * @throws LibGuestFSException\n";
9783         pr "   */\n";
9784         pr "  ";
9785       );
9786       generate_java_prototype ~public:true ~semicolon:false name style;
9787       pr "\n";
9788       pr "  {\n";
9789       pr "    if (g == 0)\n";
9790       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9791         name;
9792       pr "    ";
9793       if fst style <> RErr then pr "return ";
9794       pr "_%s " name;
9795       generate_java_call_args ~handle:"g" (snd style);
9796       pr ";\n";
9797       pr "  }\n";
9798       pr "  ";
9799       generate_java_prototype ~privat:true ~native:true name style;
9800       pr "\n";
9801       pr "\n";
9802   ) all_functions;
9803
9804   pr "}\n"
9805
9806 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9807 and generate_java_call_args ~handle args =
9808   pr "(%s" handle;
9809   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9810   pr ")"
9811
9812 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9813     ?(semicolon=true) name style =
9814   if privat then pr "private ";
9815   if public then pr "public ";
9816   if native then pr "native ";
9817
9818   (* return type *)
9819   (match fst style with
9820    | RErr -> pr "void ";
9821    | RInt _ -> pr "int ";
9822    | RInt64 _ -> pr "long ";
9823    | RBool _ -> pr "boolean ";
9824    | RConstString _ | RConstOptString _ | RString _
9825    | RBufferOut _ -> pr "String ";
9826    | RStringList _ -> pr "String[] ";
9827    | RStruct (_, typ) ->
9828        let name = java_name_of_struct typ in
9829        pr "%s " name;
9830    | RStructList (_, typ) ->
9831        let name = java_name_of_struct typ in
9832        pr "%s[] " name;
9833    | RHashtable _ -> pr "HashMap<String,String> ";
9834   );
9835
9836   if native then pr "_%s " name else pr "%s " name;
9837   pr "(";
9838   let needs_comma = ref false in
9839   if native then (
9840     pr "long g";
9841     needs_comma := true
9842   );
9843
9844   (* args *)
9845   List.iter (
9846     fun arg ->
9847       if !needs_comma then pr ", ";
9848       needs_comma := true;
9849
9850       match arg with
9851       | Pathname n
9852       | Device n | Dev_or_Path n
9853       | String n
9854       | OptString n
9855       | FileIn n
9856       | FileOut n ->
9857           pr "String %s" n
9858       | StringList n | DeviceList n ->
9859           pr "String[] %s" n
9860       | Bool n ->
9861           pr "boolean %s" n
9862       | Int n ->
9863           pr "int %s" n
9864       | Int64 n ->
9865           pr "long %s" n
9866   ) (snd style);
9867
9868   pr ")\n";
9869   pr "    throws LibGuestFSException";
9870   if semicolon then pr ";"
9871
9872 and generate_java_struct jtyp cols () =
9873   generate_header CStyle LGPLv2plus;
9874
9875   pr "\
9876 package com.redhat.et.libguestfs;
9877
9878 /**
9879  * Libguestfs %s structure.
9880  *
9881  * @author rjones
9882  * @see GuestFS
9883  */
9884 public class %s {
9885 " jtyp jtyp;
9886
9887   List.iter (
9888     function
9889     | name, FString
9890     | name, FUUID
9891     | name, FBuffer -> pr "  public String %s;\n" name
9892     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9893     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9894     | name, FChar -> pr "  public char %s;\n" name
9895     | name, FOptPercent ->
9896         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9897         pr "  public float %s;\n" name
9898   ) cols;
9899
9900   pr "}\n"
9901
9902 and generate_java_c () =
9903   generate_header CStyle LGPLv2plus;
9904
9905   pr "\
9906 #include <stdio.h>
9907 #include <stdlib.h>
9908 #include <string.h>
9909
9910 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9911 #include \"guestfs.h\"
9912
9913 /* Note that this function returns.  The exception is not thrown
9914  * until after the wrapper function returns.
9915  */
9916 static void
9917 throw_exception (JNIEnv *env, const char *msg)
9918 {
9919   jclass cl;
9920   cl = (*env)->FindClass (env,
9921                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9922   (*env)->ThrowNew (env, cl, msg);
9923 }
9924
9925 JNIEXPORT jlong JNICALL
9926 Java_com_redhat_et_libguestfs_GuestFS__1create
9927   (JNIEnv *env, jobject obj)
9928 {
9929   guestfs_h *g;
9930
9931   g = guestfs_create ();
9932   if (g == NULL) {
9933     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9934     return 0;
9935   }
9936   guestfs_set_error_handler (g, NULL, NULL);
9937   return (jlong) (long) g;
9938 }
9939
9940 JNIEXPORT void JNICALL
9941 Java_com_redhat_et_libguestfs_GuestFS__1close
9942   (JNIEnv *env, jobject obj, jlong jg)
9943 {
9944   guestfs_h *g = (guestfs_h *) (long) jg;
9945   guestfs_close (g);
9946 }
9947
9948 ";
9949
9950   List.iter (
9951     fun (name, style, _, _, _, _, _) ->
9952       pr "JNIEXPORT ";
9953       (match fst style with
9954        | RErr -> pr "void ";
9955        | RInt _ -> pr "jint ";
9956        | RInt64 _ -> pr "jlong ";
9957        | RBool _ -> pr "jboolean ";
9958        | RConstString _ | RConstOptString _ | RString _
9959        | RBufferOut _ -> pr "jstring ";
9960        | RStruct _ | RHashtable _ ->
9961            pr "jobject ";
9962        | RStringList _ | RStructList _ ->
9963            pr "jobjectArray ";
9964       );
9965       pr "JNICALL\n";
9966       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9967       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9968       pr "\n";
9969       pr "  (JNIEnv *env, jobject obj, jlong jg";
9970       List.iter (
9971         function
9972         | Pathname n
9973         | Device n | Dev_or_Path n
9974         | String n
9975         | OptString n
9976         | FileIn n
9977         | FileOut n ->
9978             pr ", jstring j%s" n
9979         | StringList n | DeviceList n ->
9980             pr ", jobjectArray j%s" n
9981         | Bool n ->
9982             pr ", jboolean j%s" n
9983         | Int n ->
9984             pr ", jint j%s" n
9985         | Int64 n ->
9986             pr ", jlong j%s" n
9987       ) (snd style);
9988       pr ")\n";
9989       pr "{\n";
9990       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9991       let error_code, no_ret =
9992         match fst style with
9993         | RErr -> pr "  int r;\n"; "-1", ""
9994         | RBool _
9995         | RInt _ -> pr "  int r;\n"; "-1", "0"
9996         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9997         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9998         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9999         | RString _ ->
10000             pr "  jstring jr;\n";
10001             pr "  char *r;\n"; "NULL", "NULL"
10002         | RStringList _ ->
10003             pr "  jobjectArray jr;\n";
10004             pr "  int r_len;\n";
10005             pr "  jclass cl;\n";
10006             pr "  jstring jstr;\n";
10007             pr "  char **r;\n"; "NULL", "NULL"
10008         | RStruct (_, typ) ->
10009             pr "  jobject jr;\n";
10010             pr "  jclass cl;\n";
10011             pr "  jfieldID fl;\n";
10012             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10013         | RStructList (_, typ) ->
10014             pr "  jobjectArray jr;\n";
10015             pr "  jclass cl;\n";
10016             pr "  jfieldID fl;\n";
10017             pr "  jobject jfl;\n";
10018             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10019         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10020         | RBufferOut _ ->
10021             pr "  jstring jr;\n";
10022             pr "  char *r;\n";
10023             pr "  size_t size;\n";
10024             "NULL", "NULL" in
10025       List.iter (
10026         function
10027         | Pathname n
10028         | Device n | Dev_or_Path n
10029         | String n
10030         | OptString n
10031         | FileIn n
10032         | FileOut n ->
10033             pr "  const char *%s;\n" n
10034         | StringList n | DeviceList n ->
10035             pr "  int %s_len;\n" n;
10036             pr "  const char **%s;\n" n
10037         | Bool n
10038         | Int n ->
10039             pr "  int %s;\n" n
10040         | Int64 n ->
10041             pr "  int64_t %s;\n" n
10042       ) (snd style);
10043
10044       let needs_i =
10045         (match fst style with
10046          | RStringList _ | RStructList _ -> true
10047          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10048          | RConstOptString _
10049          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10050           List.exists (function
10051                        | StringList _ -> true
10052                        | DeviceList _ -> true
10053                        | _ -> false) (snd style) in
10054       if needs_i then
10055         pr "  int i;\n";
10056
10057       pr "\n";
10058
10059       (* Get the parameters. *)
10060       List.iter (
10061         function
10062         | Pathname n
10063         | Device n | Dev_or_Path n
10064         | String n
10065         | FileIn n
10066         | FileOut n ->
10067             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10068         | OptString n ->
10069             (* This is completely undocumented, but Java null becomes
10070              * a NULL parameter.
10071              *)
10072             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10073         | StringList n | DeviceList n ->
10074             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10075             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10076             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10077             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10078               n;
10079             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10080             pr "  }\n";
10081             pr "  %s[%s_len] = NULL;\n" n n;
10082         | Bool n
10083         | Int n
10084         | Int64 n ->
10085             pr "  %s = j%s;\n" n n
10086       ) (snd style);
10087
10088       (* Make the call. *)
10089       pr "  r = guestfs_%s " name;
10090       generate_c_call_args ~handle:"g" style;
10091       pr ";\n";
10092
10093       (* Release the parameters. *)
10094       List.iter (
10095         function
10096         | Pathname n
10097         | Device n | Dev_or_Path n
10098         | String n
10099         | FileIn n
10100         | FileOut n ->
10101             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10102         | OptString n ->
10103             pr "  if (j%s)\n" n;
10104             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10105         | StringList n | DeviceList n ->
10106             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10107             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10108               n;
10109             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10110             pr "  }\n";
10111             pr "  free (%s);\n" n
10112         | Bool n
10113         | Int n
10114         | Int64 n -> ()
10115       ) (snd style);
10116
10117       (* Check for errors. *)
10118       pr "  if (r == %s) {\n" error_code;
10119       pr "    throw_exception (env, guestfs_last_error (g));\n";
10120       pr "    return %s;\n" no_ret;
10121       pr "  }\n";
10122
10123       (* Return value. *)
10124       (match fst style with
10125        | RErr -> ()
10126        | RInt _ -> pr "  return (jint) r;\n"
10127        | RBool _ -> pr "  return (jboolean) r;\n"
10128        | RInt64 _ -> pr "  return (jlong) r;\n"
10129        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10130        | RConstOptString _ ->
10131            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10132        | RString _ ->
10133            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10134            pr "  free (r);\n";
10135            pr "  return jr;\n"
10136        | RStringList _ ->
10137            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10138            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10139            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10140            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10141            pr "  for (i = 0; i < r_len; ++i) {\n";
10142            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10143            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10144            pr "    free (r[i]);\n";
10145            pr "  }\n";
10146            pr "  free (r);\n";
10147            pr "  return jr;\n"
10148        | RStruct (_, typ) ->
10149            let jtyp = java_name_of_struct typ in
10150            let cols = cols_of_struct typ in
10151            generate_java_struct_return typ jtyp cols
10152        | RStructList (_, typ) ->
10153            let jtyp = java_name_of_struct typ in
10154            let cols = cols_of_struct typ in
10155            generate_java_struct_list_return typ jtyp cols
10156        | RHashtable _ ->
10157            (* XXX *)
10158            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10159            pr "  return NULL;\n"
10160        | RBufferOut _ ->
10161            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10162            pr "  free (r);\n";
10163            pr "  return jr;\n"
10164       );
10165
10166       pr "}\n";
10167       pr "\n"
10168   ) all_functions
10169
10170 and generate_java_struct_return typ jtyp cols =
10171   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10172   pr "  jr = (*env)->AllocObject (env, cl);\n";
10173   List.iter (
10174     function
10175     | name, FString ->
10176         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10177         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10178     | name, FUUID ->
10179         pr "  {\n";
10180         pr "    char s[33];\n";
10181         pr "    memcpy (s, r->%s, 32);\n" name;
10182         pr "    s[32] = 0;\n";
10183         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10184         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10185         pr "  }\n";
10186     | name, FBuffer ->
10187         pr "  {\n";
10188         pr "    int len = r->%s_len;\n" name;
10189         pr "    char s[len+1];\n";
10190         pr "    memcpy (s, r->%s, len);\n" name;
10191         pr "    s[len] = 0;\n";
10192         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10193         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10194         pr "  }\n";
10195     | name, (FBytes|FUInt64|FInt64) ->
10196         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10197         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10198     | name, (FUInt32|FInt32) ->
10199         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10200         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10201     | name, FOptPercent ->
10202         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10203         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10204     | name, FChar ->
10205         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10206         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10207   ) cols;
10208   pr "  free (r);\n";
10209   pr "  return jr;\n"
10210
10211 and generate_java_struct_list_return typ jtyp cols =
10212   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10213   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10214   pr "  for (i = 0; i < r->len; ++i) {\n";
10215   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10216   List.iter (
10217     function
10218     | name, FString ->
10219         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10220         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10221     | name, FUUID ->
10222         pr "    {\n";
10223         pr "      char s[33];\n";
10224         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10225         pr "      s[32] = 0;\n";
10226         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10227         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10228         pr "    }\n";
10229     | name, FBuffer ->
10230         pr "    {\n";
10231         pr "      int len = r->val[i].%s_len;\n" name;
10232         pr "      char s[len+1];\n";
10233         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10234         pr "      s[len] = 0;\n";
10235         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10236         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10237         pr "    }\n";
10238     | name, (FBytes|FUInt64|FInt64) ->
10239         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10240         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10241     | name, (FUInt32|FInt32) ->
10242         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10243         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10244     | name, FOptPercent ->
10245         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10246         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10247     | name, FChar ->
10248         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10249         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10250   ) cols;
10251   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10252   pr "  }\n";
10253   pr "  guestfs_free_%s_list (r);\n" typ;
10254   pr "  return jr;\n"
10255
10256 and generate_java_makefile_inc () =
10257   generate_header HashStyle GPLv2plus;
10258
10259   pr "java_built_sources = \\\n";
10260   List.iter (
10261     fun (typ, jtyp) ->
10262         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10263   ) java_structs;
10264   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10265
10266 and generate_haskell_hs () =
10267   generate_header HaskellStyle LGPLv2plus;
10268
10269   (* XXX We only know how to generate partial FFI for Haskell
10270    * at the moment.  Please help out!
10271    *)
10272   let can_generate style =
10273     match style with
10274     | RErr, _
10275     | RInt _, _
10276     | RInt64 _, _ -> true
10277     | RBool _, _
10278     | RConstString _, _
10279     | RConstOptString _, _
10280     | RString _, _
10281     | RStringList _, _
10282     | RStruct _, _
10283     | RStructList _, _
10284     | RHashtable _, _
10285     | RBufferOut _, _ -> false in
10286
10287   pr "\
10288 {-# INCLUDE <guestfs.h> #-}
10289 {-# LANGUAGE ForeignFunctionInterface #-}
10290
10291 module Guestfs (
10292   create";
10293
10294   (* List out the names of the actions we want to export. *)
10295   List.iter (
10296     fun (name, style, _, _, _, _, _) ->
10297       if can_generate style then pr ",\n  %s" name
10298   ) all_functions;
10299
10300   pr "
10301   ) where
10302
10303 -- Unfortunately some symbols duplicate ones already present
10304 -- in Prelude.  We don't know which, so we hard-code a list
10305 -- here.
10306 import Prelude hiding (truncate)
10307
10308 import Foreign
10309 import Foreign.C
10310 import Foreign.C.Types
10311 import IO
10312 import Control.Exception
10313 import Data.Typeable
10314
10315 data GuestfsS = GuestfsS            -- represents the opaque C struct
10316 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10317 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10318
10319 -- XXX define properly later XXX
10320 data PV = PV
10321 data VG = VG
10322 data LV = LV
10323 data IntBool = IntBool
10324 data Stat = Stat
10325 data StatVFS = StatVFS
10326 data Hashtable = Hashtable
10327
10328 foreign import ccall unsafe \"guestfs_create\" c_create
10329   :: IO GuestfsP
10330 foreign import ccall unsafe \"&guestfs_close\" c_close
10331   :: FunPtr (GuestfsP -> IO ())
10332 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10333   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10334
10335 create :: IO GuestfsH
10336 create = do
10337   p <- c_create
10338   c_set_error_handler p nullPtr nullPtr
10339   h <- newForeignPtr c_close p
10340   return h
10341
10342 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10343   :: GuestfsP -> IO CString
10344
10345 -- last_error :: GuestfsH -> IO (Maybe String)
10346 -- last_error h = do
10347 --   str <- withForeignPtr h (\\p -> c_last_error p)
10348 --   maybePeek peekCString str
10349
10350 last_error :: GuestfsH -> IO (String)
10351 last_error h = do
10352   str <- withForeignPtr h (\\p -> c_last_error p)
10353   if (str == nullPtr)
10354     then return \"no error\"
10355     else peekCString str
10356
10357 ";
10358
10359   (* Generate wrappers for each foreign function. *)
10360   List.iter (
10361     fun (name, style, _, _, _, _, _) ->
10362       if can_generate style then (
10363         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10364         pr "  :: ";
10365         generate_haskell_prototype ~handle:"GuestfsP" style;
10366         pr "\n";
10367         pr "\n";
10368         pr "%s :: " name;
10369         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10370         pr "\n";
10371         pr "%s %s = do\n" name
10372           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10373         pr "  r <- ";
10374         (* Convert pointer arguments using with* functions. *)
10375         List.iter (
10376           function
10377           | FileIn n
10378           | FileOut n
10379           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10380           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10381           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10382           | Bool _ | Int _ | Int64 _ -> ()
10383         ) (snd style);
10384         (* Convert integer arguments. *)
10385         let args =
10386           List.map (
10387             function
10388             | Bool n -> sprintf "(fromBool %s)" n
10389             | Int n -> sprintf "(fromIntegral %s)" n
10390             | Int64 n -> sprintf "(fromIntegral %s)" n
10391             | FileIn n | FileOut n
10392             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10393           ) (snd style) in
10394         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10395           (String.concat " " ("p" :: args));
10396         (match fst style with
10397          | RErr | RInt _ | RInt64 _ | RBool _ ->
10398              pr "  if (r == -1)\n";
10399              pr "    then do\n";
10400              pr "      err <- last_error h\n";
10401              pr "      fail err\n";
10402          | RConstString _ | RConstOptString _ | RString _
10403          | RStringList _ | RStruct _
10404          | RStructList _ | RHashtable _ | RBufferOut _ ->
10405              pr "  if (r == nullPtr)\n";
10406              pr "    then do\n";
10407              pr "      err <- last_error h\n";
10408              pr "      fail err\n";
10409         );
10410         (match fst style with
10411          | RErr ->
10412              pr "    else return ()\n"
10413          | RInt _ ->
10414              pr "    else return (fromIntegral r)\n"
10415          | RInt64 _ ->
10416              pr "    else return (fromIntegral r)\n"
10417          | RBool _ ->
10418              pr "    else return (toBool r)\n"
10419          | RConstString _
10420          | RConstOptString _
10421          | RString _
10422          | RStringList _
10423          | RStruct _
10424          | RStructList _
10425          | RHashtable _
10426          | RBufferOut _ ->
10427              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10428         );
10429         pr "\n";
10430       )
10431   ) all_functions
10432
10433 and generate_haskell_prototype ~handle ?(hs = false) style =
10434   pr "%s -> " handle;
10435   let string = if hs then "String" else "CString" in
10436   let int = if hs then "Int" else "CInt" in
10437   let bool = if hs then "Bool" else "CInt" in
10438   let int64 = if hs then "Integer" else "Int64" in
10439   List.iter (
10440     fun arg ->
10441       (match arg with
10442        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10443        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10444        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10445        | Bool _ -> pr "%s" bool
10446        | Int _ -> pr "%s" int
10447        | Int64 _ -> pr "%s" int
10448        | FileIn _ -> pr "%s" string
10449        | FileOut _ -> pr "%s" string
10450       );
10451       pr " -> ";
10452   ) (snd style);
10453   pr "IO (";
10454   (match fst style with
10455    | RErr -> if not hs then pr "CInt"
10456    | RInt _ -> pr "%s" int
10457    | RInt64 _ -> pr "%s" int64
10458    | RBool _ -> pr "%s" bool
10459    | RConstString _ -> pr "%s" string
10460    | RConstOptString _ -> pr "Maybe %s" string
10461    | RString _ -> pr "%s" string
10462    | RStringList _ -> pr "[%s]" string
10463    | RStruct (_, typ) ->
10464        let name = java_name_of_struct typ in
10465        pr "%s" name
10466    | RStructList (_, typ) ->
10467        let name = java_name_of_struct typ in
10468        pr "[%s]" name
10469    | RHashtable _ -> pr "Hashtable"
10470    | RBufferOut _ -> pr "%s" string
10471   );
10472   pr ")"
10473
10474 and generate_csharp () =
10475   generate_header CPlusPlusStyle LGPLv2plus;
10476
10477   (* XXX Make this configurable by the C# assembly users. *)
10478   let library = "libguestfs.so.0" in
10479
10480   pr "\
10481 // These C# bindings are highly experimental at present.
10482 //
10483 // Firstly they only work on Linux (ie. Mono).  In order to get them
10484 // to work on Windows (ie. .Net) you would need to port the library
10485 // itself to Windows first.
10486 //
10487 // The second issue is that some calls are known to be incorrect and
10488 // can cause Mono to segfault.  Particularly: calls which pass or
10489 // return string[], or return any structure value.  This is because
10490 // we haven't worked out the correct way to do this from C#.
10491 //
10492 // The third issue is that when compiling you get a lot of warnings.
10493 // We are not sure whether the warnings are important or not.
10494 //
10495 // Fourthly we do not routinely build or test these bindings as part
10496 // of the make && make check cycle, which means that regressions might
10497 // go unnoticed.
10498 //
10499 // Suggestions and patches are welcome.
10500
10501 // To compile:
10502 //
10503 // gmcs Libguestfs.cs
10504 // mono Libguestfs.exe
10505 //
10506 // (You'll probably want to add a Test class / static main function
10507 // otherwise this won't do anything useful).
10508
10509 using System;
10510 using System.IO;
10511 using System.Runtime.InteropServices;
10512 using System.Runtime.Serialization;
10513 using System.Collections;
10514
10515 namespace Guestfs
10516 {
10517   class Error : System.ApplicationException
10518   {
10519     public Error (string message) : base (message) {}
10520     protected Error (SerializationInfo info, StreamingContext context) {}
10521   }
10522
10523   class Guestfs
10524   {
10525     IntPtr _handle;
10526
10527     [DllImport (\"%s\")]
10528     static extern IntPtr guestfs_create ();
10529
10530     public Guestfs ()
10531     {
10532       _handle = guestfs_create ();
10533       if (_handle == IntPtr.Zero)
10534         throw new Error (\"could not create guestfs handle\");
10535     }
10536
10537     [DllImport (\"%s\")]
10538     static extern void guestfs_close (IntPtr h);
10539
10540     ~Guestfs ()
10541     {
10542       guestfs_close (_handle);
10543     }
10544
10545     [DllImport (\"%s\")]
10546     static extern string guestfs_last_error (IntPtr h);
10547
10548 " library library library;
10549
10550   (* Generate C# structure bindings.  We prefix struct names with
10551    * underscore because C# cannot have conflicting struct names and
10552    * method names (eg. "class stat" and "stat").
10553    *)
10554   List.iter (
10555     fun (typ, cols) ->
10556       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10557       pr "    public class _%s {\n" typ;
10558       List.iter (
10559         function
10560         | name, FChar -> pr "      char %s;\n" name
10561         | name, FString -> pr "      string %s;\n" name
10562         | name, FBuffer ->
10563             pr "      uint %s_len;\n" name;
10564             pr "      string %s;\n" name
10565         | name, FUUID ->
10566             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10567             pr "      string %s;\n" name
10568         | name, FUInt32 -> pr "      uint %s;\n" name
10569         | name, FInt32 -> pr "      int %s;\n" name
10570         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10571         | name, FInt64 -> pr "      long %s;\n" name
10572         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10573       ) cols;
10574       pr "    }\n";
10575       pr "\n"
10576   ) structs;
10577
10578   (* Generate C# function bindings. *)
10579   List.iter (
10580     fun (name, style, _, _, _, shortdesc, _) ->
10581       let rec csharp_return_type () =
10582         match fst style with
10583         | RErr -> "void"
10584         | RBool n -> "bool"
10585         | RInt n -> "int"
10586         | RInt64 n -> "long"
10587         | RConstString n
10588         | RConstOptString n
10589         | RString n
10590         | RBufferOut n -> "string"
10591         | RStruct (_,n) -> "_" ^ n
10592         | RHashtable n -> "Hashtable"
10593         | RStringList n -> "string[]"
10594         | RStructList (_,n) -> sprintf "_%s[]" n
10595
10596       and c_return_type () =
10597         match fst style with
10598         | RErr
10599         | RBool _
10600         | RInt _ -> "int"
10601         | RInt64 _ -> "long"
10602         | RConstString _
10603         | RConstOptString _
10604         | RString _
10605         | RBufferOut _ -> "string"
10606         | RStruct (_,n) -> "_" ^ n
10607         | RHashtable _
10608         | RStringList _ -> "string[]"
10609         | RStructList (_,n) -> sprintf "_%s[]" n
10610
10611       and c_error_comparison () =
10612         match fst style with
10613         | RErr
10614         | RBool _
10615         | RInt _
10616         | RInt64 _ -> "== -1"
10617         | RConstString _
10618         | RConstOptString _
10619         | RString _
10620         | RBufferOut _
10621         | RStruct (_,_)
10622         | RHashtable _
10623         | RStringList _
10624         | RStructList (_,_) -> "== null"
10625
10626       and generate_extern_prototype () =
10627         pr "    static extern %s guestfs_%s (IntPtr h"
10628           (c_return_type ()) name;
10629         List.iter (
10630           function
10631           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10632           | FileIn n | FileOut n ->
10633               pr ", [In] string %s" n
10634           | StringList n | DeviceList n ->
10635               pr ", [In] string[] %s" n
10636           | Bool n ->
10637               pr ", bool %s" n
10638           | Int n ->
10639               pr ", int %s" n
10640           | Int64 n ->
10641               pr ", long %s" n
10642         ) (snd style);
10643         pr ");\n"
10644
10645       and generate_public_prototype () =
10646         pr "    public %s %s (" (csharp_return_type ()) name;
10647         let comma = ref false in
10648         let next () =
10649           if !comma then pr ", ";
10650           comma := true
10651         in
10652         List.iter (
10653           function
10654           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10655           | FileIn n | FileOut n ->
10656               next (); pr "string %s" n
10657           | StringList n | DeviceList n ->
10658               next (); pr "string[] %s" n
10659           | Bool n ->
10660               next (); pr "bool %s" n
10661           | Int n ->
10662               next (); pr "int %s" n
10663           | Int64 n ->
10664               next (); pr "long %s" n
10665         ) (snd style);
10666         pr ")\n"
10667
10668       and generate_call () =
10669         pr "guestfs_%s (_handle" name;
10670         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10671         pr ");\n";
10672       in
10673
10674       pr "    [DllImport (\"%s\")]\n" library;
10675       generate_extern_prototype ();
10676       pr "\n";
10677       pr "    /// <summary>\n";
10678       pr "    /// %s\n" shortdesc;
10679       pr "    /// </summary>\n";
10680       generate_public_prototype ();
10681       pr "    {\n";
10682       pr "      %s r;\n" (c_return_type ());
10683       pr "      r = ";
10684       generate_call ();
10685       pr "      if (r %s)\n" (c_error_comparison ());
10686       pr "        throw new Error (guestfs_last_error (_handle));\n";
10687       (match fst style with
10688        | RErr -> ()
10689        | RBool _ ->
10690            pr "      return r != 0 ? true : false;\n"
10691        | RHashtable _ ->
10692            pr "      Hashtable rr = new Hashtable ();\n";
10693            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10694            pr "        rr.Add (r[i], r[i+1]);\n";
10695            pr "      return rr;\n"
10696        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10697        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10698        | RStructList _ ->
10699            pr "      return r;\n"
10700       );
10701       pr "    }\n";
10702       pr "\n";
10703   ) all_functions_sorted;
10704
10705   pr "  }
10706 }
10707 "
10708
10709 and generate_bindtests () =
10710   generate_header CStyle LGPLv2plus;
10711
10712   pr "\
10713 #include <stdio.h>
10714 #include <stdlib.h>
10715 #include <inttypes.h>
10716 #include <string.h>
10717
10718 #include \"guestfs.h\"
10719 #include \"guestfs-internal.h\"
10720 #include \"guestfs-internal-actions.h\"
10721 #include \"guestfs_protocol.h\"
10722
10723 #define error guestfs_error
10724 #define safe_calloc guestfs_safe_calloc
10725 #define safe_malloc guestfs_safe_malloc
10726
10727 static void
10728 print_strings (char *const *argv)
10729 {
10730   int argc;
10731
10732   printf (\"[\");
10733   for (argc = 0; argv[argc] != NULL; ++argc) {
10734     if (argc > 0) printf (\", \");
10735     printf (\"\\\"%%s\\\"\", argv[argc]);
10736   }
10737   printf (\"]\\n\");
10738 }
10739
10740 /* The test0 function prints its parameters to stdout. */
10741 ";
10742
10743   let test0, tests =
10744     match test_functions with
10745     | [] -> assert false
10746     | test0 :: tests -> test0, tests in
10747
10748   let () =
10749     let (name, style, _, _, _, _, _) = test0 in
10750     generate_prototype ~extern:false ~semicolon:false ~newline:true
10751       ~handle:"g" ~prefix:"guestfs__" name style;
10752     pr "{\n";
10753     List.iter (
10754       function
10755       | Pathname n
10756       | Device n | Dev_or_Path n
10757       | String n
10758       | FileIn n
10759       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10760       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10761       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10762       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10763       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10764       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10765     ) (snd style);
10766     pr "  /* Java changes stdout line buffering so we need this: */\n";
10767     pr "  fflush (stdout);\n";
10768     pr "  return 0;\n";
10769     pr "}\n";
10770     pr "\n" in
10771
10772   List.iter (
10773     fun (name, style, _, _, _, _, _) ->
10774       if String.sub name (String.length name - 3) 3 <> "err" then (
10775         pr "/* Test normal return. */\n";
10776         generate_prototype ~extern:false ~semicolon:false ~newline:true
10777           ~handle:"g" ~prefix:"guestfs__" name style;
10778         pr "{\n";
10779         (match fst style with
10780          | RErr ->
10781              pr "  return 0;\n"
10782          | RInt _ ->
10783              pr "  int r;\n";
10784              pr "  sscanf (val, \"%%d\", &r);\n";
10785              pr "  return r;\n"
10786          | RInt64 _ ->
10787              pr "  int64_t r;\n";
10788              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10789              pr "  return r;\n"
10790          | RBool _ ->
10791              pr "  return STREQ (val, \"true\");\n"
10792          | RConstString _
10793          | RConstOptString _ ->
10794              (* Can't return the input string here.  Return a static
10795               * string so we ensure we get a segfault if the caller
10796               * tries to free it.
10797               *)
10798              pr "  return \"static string\";\n"
10799          | RString _ ->
10800              pr "  return strdup (val);\n"
10801          | RStringList _ ->
10802              pr "  char **strs;\n";
10803              pr "  int n, i;\n";
10804              pr "  sscanf (val, \"%%d\", &n);\n";
10805              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10806              pr "  for (i = 0; i < n; ++i) {\n";
10807              pr "    strs[i] = safe_malloc (g, 16);\n";
10808              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10809              pr "  }\n";
10810              pr "  strs[n] = NULL;\n";
10811              pr "  return strs;\n"
10812          | RStruct (_, typ) ->
10813              pr "  struct guestfs_%s *r;\n" typ;
10814              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10815              pr "  return r;\n"
10816          | RStructList (_, typ) ->
10817              pr "  struct guestfs_%s_list *r;\n" typ;
10818              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10819              pr "  sscanf (val, \"%%d\", &r->len);\n";
10820              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10821              pr "  return r;\n"
10822          | RHashtable _ ->
10823              pr "  char **strs;\n";
10824              pr "  int n, i;\n";
10825              pr "  sscanf (val, \"%%d\", &n);\n";
10826              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10827              pr "  for (i = 0; i < n; ++i) {\n";
10828              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10829              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10830              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10831              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10832              pr "  }\n";
10833              pr "  strs[n*2] = NULL;\n";
10834              pr "  return strs;\n"
10835          | RBufferOut _ ->
10836              pr "  return strdup (val);\n"
10837         );
10838         pr "}\n";
10839         pr "\n"
10840       ) else (
10841         pr "/* Test error return. */\n";
10842         generate_prototype ~extern:false ~semicolon:false ~newline:true
10843           ~handle:"g" ~prefix:"guestfs__" name style;
10844         pr "{\n";
10845         pr "  error (g, \"error\");\n";
10846         (match fst style with
10847          | RErr | RInt _ | RInt64 _ | RBool _ ->
10848              pr "  return -1;\n"
10849          | RConstString _ | RConstOptString _
10850          | RString _ | RStringList _ | RStruct _
10851          | RStructList _
10852          | RHashtable _
10853          | RBufferOut _ ->
10854              pr "  return NULL;\n"
10855         );
10856         pr "}\n";
10857         pr "\n"
10858       )
10859   ) tests
10860
10861 and generate_ocaml_bindtests () =
10862   generate_header OCamlStyle GPLv2plus;
10863
10864   pr "\
10865 let () =
10866   let g = Guestfs.create () in
10867 ";
10868
10869   let mkargs args =
10870     String.concat " " (
10871       List.map (
10872         function
10873         | CallString s -> "\"" ^ s ^ "\""
10874         | CallOptString None -> "None"
10875         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10876         | CallStringList xs ->
10877             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10878         | CallInt i when i >= 0 -> string_of_int i
10879         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10880         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10881         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10882         | CallBool b -> string_of_bool b
10883       ) args
10884     )
10885   in
10886
10887   generate_lang_bindtests (
10888     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10889   );
10890
10891   pr "print_endline \"EOF\"\n"
10892
10893 and generate_perl_bindtests () =
10894   pr "#!/usr/bin/perl -w\n";
10895   generate_header HashStyle GPLv2plus;
10896
10897   pr "\
10898 use strict;
10899
10900 use Sys::Guestfs;
10901
10902 my $g = Sys::Guestfs->new ();
10903 ";
10904
10905   let mkargs args =
10906     String.concat ", " (
10907       List.map (
10908         function
10909         | CallString s -> "\"" ^ s ^ "\""
10910         | CallOptString None -> "undef"
10911         | CallOptString (Some s) -> sprintf "\"%s\"" s
10912         | CallStringList xs ->
10913             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10914         | CallInt i -> string_of_int i
10915         | CallInt64 i -> Int64.to_string i
10916         | CallBool b -> if b then "1" else "0"
10917       ) args
10918     )
10919   in
10920
10921   generate_lang_bindtests (
10922     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10923   );
10924
10925   pr "print \"EOF\\n\"\n"
10926
10927 and generate_python_bindtests () =
10928   generate_header HashStyle GPLv2plus;
10929
10930   pr "\
10931 import guestfs
10932
10933 g = guestfs.GuestFS ()
10934 ";
10935
10936   let mkargs args =
10937     String.concat ", " (
10938       List.map (
10939         function
10940         | CallString s -> "\"" ^ s ^ "\""
10941         | CallOptString None -> "None"
10942         | CallOptString (Some s) -> sprintf "\"%s\"" s
10943         | CallStringList xs ->
10944             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10945         | CallInt i -> string_of_int i
10946         | CallInt64 i -> Int64.to_string i
10947         | CallBool b -> if b then "1" else "0"
10948       ) args
10949     )
10950   in
10951
10952   generate_lang_bindtests (
10953     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10954   );
10955
10956   pr "print \"EOF\"\n"
10957
10958 and generate_ruby_bindtests () =
10959   generate_header HashStyle GPLv2plus;
10960
10961   pr "\
10962 require 'guestfs'
10963
10964 g = Guestfs::create()
10965 ";
10966
10967   let mkargs args =
10968     String.concat ", " (
10969       List.map (
10970         function
10971         | CallString s -> "\"" ^ s ^ "\""
10972         | CallOptString None -> "nil"
10973         | CallOptString (Some s) -> sprintf "\"%s\"" s
10974         | CallStringList xs ->
10975             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10976         | CallInt i -> string_of_int i
10977         | CallInt64 i -> Int64.to_string i
10978         | CallBool b -> string_of_bool b
10979       ) args
10980     )
10981   in
10982
10983   generate_lang_bindtests (
10984     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10985   );
10986
10987   pr "print \"EOF\\n\"\n"
10988
10989 and generate_java_bindtests () =
10990   generate_header CStyle GPLv2plus;
10991
10992   pr "\
10993 import com.redhat.et.libguestfs.*;
10994
10995 public class Bindtests {
10996     public static void main (String[] argv)
10997     {
10998         try {
10999             GuestFS g = new GuestFS ();
11000 ";
11001
11002   let mkargs args =
11003     String.concat ", " (
11004       List.map (
11005         function
11006         | CallString s -> "\"" ^ s ^ "\""
11007         | CallOptString None -> "null"
11008         | CallOptString (Some s) -> sprintf "\"%s\"" s
11009         | CallStringList xs ->
11010             "new String[]{" ^
11011               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11012         | CallInt i -> string_of_int i
11013         | CallInt64 i -> Int64.to_string i
11014         | CallBool b -> string_of_bool b
11015       ) args
11016     )
11017   in
11018
11019   generate_lang_bindtests (
11020     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11021   );
11022
11023   pr "
11024             System.out.println (\"EOF\");
11025         }
11026         catch (Exception exn) {
11027             System.err.println (exn);
11028             System.exit (1);
11029         }
11030     }
11031 }
11032 "
11033
11034 and generate_haskell_bindtests () =
11035   generate_header HaskellStyle GPLv2plus;
11036
11037   pr "\
11038 module Bindtests where
11039 import qualified Guestfs
11040
11041 main = do
11042   g <- Guestfs.create
11043 ";
11044
11045   let mkargs args =
11046     String.concat " " (
11047       List.map (
11048         function
11049         | CallString s -> "\"" ^ s ^ "\""
11050         | CallOptString None -> "Nothing"
11051         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11052         | CallStringList xs ->
11053             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11054         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11055         | CallInt i -> string_of_int i
11056         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11057         | CallInt64 i -> Int64.to_string i
11058         | CallBool true -> "True"
11059         | CallBool false -> "False"
11060       ) args
11061     )
11062   in
11063
11064   generate_lang_bindtests (
11065     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11066   );
11067
11068   pr "  putStrLn \"EOF\"\n"
11069
11070 (* Language-independent bindings tests - we do it this way to
11071  * ensure there is parity in testing bindings across all languages.
11072  *)
11073 and generate_lang_bindtests call =
11074   call "test0" [CallString "abc"; CallOptString (Some "def");
11075                 CallStringList []; CallBool false;
11076                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11077   call "test0" [CallString "abc"; CallOptString None;
11078                 CallStringList []; CallBool false;
11079                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11080   call "test0" [CallString ""; CallOptString (Some "def");
11081                 CallStringList []; CallBool false;
11082                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11083   call "test0" [CallString ""; CallOptString (Some "");
11084                 CallStringList []; CallBool false;
11085                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11086   call "test0" [CallString "abc"; CallOptString (Some "def");
11087                 CallStringList ["1"]; CallBool false;
11088                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11089   call "test0" [CallString "abc"; CallOptString (Some "def");
11090                 CallStringList ["1"; "2"]; CallBool false;
11091                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092   call "test0" [CallString "abc"; CallOptString (Some "def");
11093                 CallStringList ["1"]; CallBool true;
11094                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095   call "test0" [CallString "abc"; CallOptString (Some "def");
11096                 CallStringList ["1"]; CallBool false;
11097                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11098   call "test0" [CallString "abc"; CallOptString (Some "def");
11099                 CallStringList ["1"]; CallBool false;
11100                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11101   call "test0" [CallString "abc"; CallOptString (Some "def");
11102                 CallStringList ["1"]; CallBool false;
11103                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11104   call "test0" [CallString "abc"; CallOptString (Some "def");
11105                 CallStringList ["1"]; CallBool false;
11106                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11107   call "test0" [CallString "abc"; CallOptString (Some "def");
11108                 CallStringList ["1"]; CallBool false;
11109                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11110   call "test0" [CallString "abc"; CallOptString (Some "def");
11111                 CallStringList ["1"]; CallBool false;
11112                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11113
11114 (* XXX Add here tests of the return and error functions. *)
11115
11116 (* Code to generator bindings for virt-inspector.  Currently only
11117  * implemented for OCaml code (for virt-p2v 2.0).
11118  *)
11119 let rng_input = "inspector/virt-inspector.rng"
11120
11121 (* Read the input file and parse it into internal structures.  This is
11122  * by no means a complete RELAX NG parser, but is just enough to be
11123  * able to parse the specific input file.
11124  *)
11125 type rng =
11126   | Element of string * rng list        (* <element name=name/> *)
11127   | Attribute of string * rng list        (* <attribute name=name/> *)
11128   | Interleave of rng list                (* <interleave/> *)
11129   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11130   | OneOrMore of rng                        (* <oneOrMore/> *)
11131   | Optional of rng                        (* <optional/> *)
11132   | Choice of string list                (* <choice><value/>*</choice> *)
11133   | Value of string                        (* <value>str</value> *)
11134   | Text                                (* <text/> *)
11135
11136 let rec string_of_rng = function
11137   | Element (name, xs) ->
11138       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11139   | Attribute (name, xs) ->
11140       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11141   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11142   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11143   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11144   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11145   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11146   | Value value -> "Value \"" ^ value ^ "\""
11147   | Text -> "Text"
11148
11149 and string_of_rng_list xs =
11150   String.concat ", " (List.map string_of_rng xs)
11151
11152 let rec parse_rng ?defines context = function
11153   | [] -> []
11154   | Xml.Element ("element", ["name", name], children) :: rest ->
11155       Element (name, parse_rng ?defines context children)
11156       :: parse_rng ?defines context rest
11157   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11158       Attribute (name, parse_rng ?defines context children)
11159       :: parse_rng ?defines context rest
11160   | Xml.Element ("interleave", [], children) :: rest ->
11161       Interleave (parse_rng ?defines context children)
11162       :: parse_rng ?defines context rest
11163   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11164       let rng = parse_rng ?defines context [child] in
11165       (match rng with
11166        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11167        | _ ->
11168            failwithf "%s: <zeroOrMore> contains more than one child element"
11169              context
11170       )
11171   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11172       let rng = parse_rng ?defines context [child] in
11173       (match rng with
11174        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11175        | _ ->
11176            failwithf "%s: <oneOrMore> contains more than one child element"
11177              context
11178       )
11179   | Xml.Element ("optional", [], [child]) :: rest ->
11180       let rng = parse_rng ?defines context [child] in
11181       (match rng with
11182        | [child] -> Optional child :: parse_rng ?defines context rest
11183        | _ ->
11184            failwithf "%s: <optional> contains more than one child element"
11185              context
11186       )
11187   | Xml.Element ("choice", [], children) :: rest ->
11188       let values = List.map (
11189         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11190         | _ ->
11191             failwithf "%s: can't handle anything except <value> in <choice>"
11192               context
11193       ) children in
11194       Choice values
11195       :: parse_rng ?defines context rest
11196   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11197       Value value :: parse_rng ?defines context rest
11198   | Xml.Element ("text", [], []) :: rest ->
11199       Text :: parse_rng ?defines context rest
11200   | Xml.Element ("ref", ["name", name], []) :: rest ->
11201       (* Look up the reference.  Because of limitations in this parser,
11202        * we can't handle arbitrarily nested <ref> yet.  You can only
11203        * use <ref> from inside <start>.
11204        *)
11205       (match defines with
11206        | None ->
11207            failwithf "%s: contains <ref>, but no refs are defined yet" context
11208        | Some map ->
11209            let rng = StringMap.find name map in
11210            rng @ parse_rng ?defines context rest
11211       )
11212   | x :: _ ->
11213       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11214
11215 let grammar =
11216   let xml = Xml.parse_file rng_input in
11217   match xml with
11218   | Xml.Element ("grammar", _,
11219                  Xml.Element ("start", _, gram) :: defines) ->
11220       (* The <define/> elements are referenced in the <start> section,
11221        * so build a map of those first.
11222        *)
11223       let defines = List.fold_left (
11224         fun map ->
11225           function Xml.Element ("define", ["name", name], defn) ->
11226             StringMap.add name defn map
11227           | _ ->
11228               failwithf "%s: expected <define name=name/>" rng_input
11229       ) StringMap.empty defines in
11230       let defines = StringMap.mapi parse_rng defines in
11231
11232       (* Parse the <start> clause, passing the defines. *)
11233       parse_rng ~defines "<start>" gram
11234   | _ ->
11235       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11236         rng_input
11237
11238 let name_of_field = function
11239   | Element (name, _) | Attribute (name, _)
11240   | ZeroOrMore (Element (name, _))
11241   | OneOrMore (Element (name, _))
11242   | Optional (Element (name, _)) -> name
11243   | Optional (Attribute (name, _)) -> name
11244   | Text -> (* an unnamed field in an element *)
11245       "data"
11246   | rng ->
11247       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11248
11249 (* At the moment this function only generates OCaml types.  However we
11250  * should parameterize it later so it can generate types/structs in a
11251  * variety of languages.
11252  *)
11253 let generate_types xs =
11254   (* A simple type is one that can be printed out directly, eg.
11255    * "string option".  A complex type is one which has a name and has
11256    * to be defined via another toplevel definition, eg. a struct.
11257    *
11258    * generate_type generates code for either simple or complex types.
11259    * In the simple case, it returns the string ("string option").  In
11260    * the complex case, it returns the name ("mountpoint").  In the
11261    * complex case it has to print out the definition before returning,
11262    * so it should only be called when we are at the beginning of a
11263    * new line (BOL context).
11264    *)
11265   let rec generate_type = function
11266     | Text ->                                (* string *)
11267         "string", true
11268     | Choice values ->                        (* [`val1|`val2|...] *)
11269         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11270     | ZeroOrMore rng ->                        (* <rng> list *)
11271         let t, is_simple = generate_type rng in
11272         t ^ " list (* 0 or more *)", is_simple
11273     | OneOrMore rng ->                        (* <rng> list *)
11274         let t, is_simple = generate_type rng in
11275         t ^ " list (* 1 or more *)", is_simple
11276                                         (* virt-inspector hack: bool *)
11277     | Optional (Attribute (name, [Value "1"])) ->
11278         "bool", true
11279     | Optional rng ->                        (* <rng> list *)
11280         let t, is_simple = generate_type rng in
11281         t ^ " option", is_simple
11282                                         (* type name = { fields ... } *)
11283     | Element (name, fields) when is_attrs_interleave fields ->
11284         generate_type_struct name (get_attrs_interleave fields)
11285     | Element (name, [field])                (* type name = field *)
11286     | Attribute (name, [field]) ->
11287         let t, is_simple = generate_type field in
11288         if is_simple then (t, true)
11289         else (
11290           pr "type %s = %s\n" name t;
11291           name, false
11292         )
11293     | Element (name, fields) ->              (* type name = { fields ... } *)
11294         generate_type_struct name fields
11295     | rng ->
11296         failwithf "generate_type failed at: %s" (string_of_rng rng)
11297
11298   and is_attrs_interleave = function
11299     | [Interleave _] -> true
11300     | Attribute _ :: fields -> is_attrs_interleave fields
11301     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11302     | _ -> false
11303
11304   and get_attrs_interleave = function
11305     | [Interleave fields] -> fields
11306     | ((Attribute _) as field) :: fields
11307     | ((Optional (Attribute _)) as field) :: fields ->
11308         field :: get_attrs_interleave fields
11309     | _ -> assert false
11310
11311   and generate_types xs =
11312     List.iter (fun x -> ignore (generate_type x)) xs
11313
11314   and generate_type_struct name fields =
11315     (* Calculate the types of the fields first.  We have to do this
11316      * before printing anything so we are still in BOL context.
11317      *)
11318     let types = List.map fst (List.map generate_type fields) in
11319
11320     (* Special case of a struct containing just a string and another
11321      * field.  Turn it into an assoc list.
11322      *)
11323     match types with
11324     | ["string"; other] ->
11325         let fname1, fname2 =
11326           match fields with
11327           | [f1; f2] -> name_of_field f1, name_of_field f2
11328           | _ -> assert false in
11329         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11330         name, false
11331
11332     | types ->
11333         pr "type %s = {\n" name;
11334         List.iter (
11335           fun (field, ftype) ->
11336             let fname = name_of_field field in
11337             pr "  %s_%s : %s;\n" name fname ftype
11338         ) (List.combine fields types);
11339         pr "}\n";
11340         (* Return the name of this type, and
11341          * false because it's not a simple type.
11342          *)
11343         name, false
11344   in
11345
11346   generate_types xs
11347
11348 let generate_parsers xs =
11349   (* As for generate_type above, generate_parser makes a parser for
11350    * some type, and returns the name of the parser it has generated.
11351    * Because it (may) need to print something, it should always be
11352    * called in BOL context.
11353    *)
11354   let rec generate_parser = function
11355     | Text ->                                (* string *)
11356         "string_child_or_empty"
11357     | Choice values ->                        (* [`val1|`val2|...] *)
11358         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11359           (String.concat "|"
11360              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11361     | ZeroOrMore rng ->                        (* <rng> list *)
11362         let pa = generate_parser rng in
11363         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11364     | OneOrMore rng ->                        (* <rng> list *)
11365         let pa = generate_parser rng in
11366         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11367                                         (* virt-inspector hack: bool *)
11368     | Optional (Attribute (name, [Value "1"])) ->
11369         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11370     | Optional rng ->                        (* <rng> list *)
11371         let pa = generate_parser rng in
11372         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11373                                         (* type name = { fields ... } *)
11374     | Element (name, fields) when is_attrs_interleave fields ->
11375         generate_parser_struct name (get_attrs_interleave fields)
11376     | Element (name, [field]) ->        (* type name = field *)
11377         let pa = generate_parser field in
11378         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11379         pr "let %s =\n" parser_name;
11380         pr "  %s\n" pa;
11381         pr "let parse_%s = %s\n" name parser_name;
11382         parser_name
11383     | Attribute (name, [field]) ->
11384         let pa = generate_parser field in
11385         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11386         pr "let %s =\n" parser_name;
11387         pr "  %s\n" pa;
11388         pr "let parse_%s = %s\n" name parser_name;
11389         parser_name
11390     | Element (name, fields) ->              (* type name = { fields ... } *)
11391         generate_parser_struct name ([], fields)
11392     | rng ->
11393         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11394
11395   and is_attrs_interleave = function
11396     | [Interleave _] -> true
11397     | Attribute _ :: fields -> is_attrs_interleave fields
11398     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11399     | _ -> false
11400
11401   and get_attrs_interleave = function
11402     | [Interleave fields] -> [], fields
11403     | ((Attribute _) as field) :: fields
11404     | ((Optional (Attribute _)) as field) :: fields ->
11405         let attrs, interleaves = get_attrs_interleave fields in
11406         (field :: attrs), interleaves
11407     | _ -> assert false
11408
11409   and generate_parsers xs =
11410     List.iter (fun x -> ignore (generate_parser x)) xs
11411
11412   and generate_parser_struct name (attrs, interleaves) =
11413     (* Generate parsers for the fields first.  We have to do this
11414      * before printing anything so we are still in BOL context.
11415      *)
11416     let fields = attrs @ interleaves in
11417     let pas = List.map generate_parser fields in
11418
11419     (* Generate an intermediate tuple from all the fields first.
11420      * If the type is just a string + another field, then we will
11421      * return this directly, otherwise it is turned into a record.
11422      *
11423      * RELAX NG note: This code treats <interleave> and plain lists of
11424      * fields the same.  In other words, it doesn't bother enforcing
11425      * any ordering of fields in the XML.
11426      *)
11427     pr "let parse_%s x =\n" name;
11428     pr "  let t = (\n    ";
11429     let comma = ref false in
11430     List.iter (
11431       fun x ->
11432         if !comma then pr ",\n    ";
11433         comma := true;
11434         match x with
11435         | Optional (Attribute (fname, [field])), pa ->
11436             pr "%s x" pa
11437         | Optional (Element (fname, [field])), pa ->
11438             pr "%s (optional_child %S x)" pa fname
11439         | Attribute (fname, [Text]), _ ->
11440             pr "attribute %S x" fname
11441         | (ZeroOrMore _ | OneOrMore _), pa ->
11442             pr "%s x" pa
11443         | Text, pa ->
11444             pr "%s x" pa
11445         | (field, pa) ->
11446             let fname = name_of_field field in
11447             pr "%s (child %S x)" pa fname
11448     ) (List.combine fields pas);
11449     pr "\n  ) in\n";
11450
11451     (match fields with
11452      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11453          pr "  t\n"
11454
11455      | _ ->
11456          pr "  (Obj.magic t : %s)\n" name
11457 (*
11458          List.iter (
11459            function
11460            | (Optional (Attribute (fname, [field])), pa) ->
11461                pr "  %s_%s =\n" name fname;
11462                pr "    %s x;\n" pa
11463            | (Optional (Element (fname, [field])), pa) ->
11464                pr "  %s_%s =\n" name fname;
11465                pr "    (let x = optional_child %S x in\n" fname;
11466                pr "     %s x);\n" pa
11467            | (field, pa) ->
11468                let fname = name_of_field field in
11469                pr "  %s_%s =\n" name fname;
11470                pr "    (let x = child %S x in\n" fname;
11471                pr "     %s x);\n" pa
11472          ) (List.combine fields pas);
11473          pr "}\n"
11474 *)
11475     );
11476     sprintf "parse_%s" name
11477   in
11478
11479   generate_parsers xs
11480
11481 (* Generate ocaml/guestfs_inspector.mli. *)
11482 let generate_ocaml_inspector_mli () =
11483   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11484
11485   pr "\
11486 (** This is an OCaml language binding to the external [virt-inspector]
11487     program.
11488
11489     For more information, please read the man page [virt-inspector(1)].
11490 *)
11491
11492 ";
11493
11494   generate_types grammar;
11495   pr "(** The nested information returned from the {!inspect} function. *)\n";
11496   pr "\n";
11497
11498   pr "\
11499 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11500 (** To inspect a libvirt domain called [name], pass a singleton
11501     list: [inspect [name]].  When using libvirt only, you may
11502     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11503
11504     To inspect a disk image or images, pass a list of the filenames
11505     of the disk images: [inspect filenames]
11506
11507     This function inspects the given guest or disk images and
11508     returns a list of operating system(s) found and a large amount
11509     of information about them.  In the vast majority of cases,
11510     a virtual machine only contains a single operating system.
11511
11512     If the optional [~xml] parameter is given, then this function
11513     skips running the external virt-inspector program and just
11514     parses the given XML directly (which is expected to be XML
11515     produced from a previous run of virt-inspector).  The list of
11516     names and connect URI are ignored in this case.
11517
11518     This function can throw a wide variety of exceptions, for example
11519     if the external virt-inspector program cannot be found, or if
11520     it doesn't generate valid XML.
11521 *)
11522 "
11523
11524 (* Generate ocaml/guestfs_inspector.ml. *)
11525 let generate_ocaml_inspector_ml () =
11526   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11527
11528   pr "open Unix\n";
11529   pr "\n";
11530
11531   generate_types grammar;
11532   pr "\n";
11533
11534   pr "\
11535 (* Misc functions which are used by the parser code below. *)
11536 let first_child = function
11537   | Xml.Element (_, _, c::_) -> c
11538   | Xml.Element (name, _, []) ->
11539       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11540   | Xml.PCData str ->
11541       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11542
11543 let string_child_or_empty = function
11544   | Xml.Element (_, _, [Xml.PCData s]) -> s
11545   | Xml.Element (_, _, []) -> \"\"
11546   | Xml.Element (x, _, _) ->
11547       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11548                 x ^ \" instead\")
11549   | Xml.PCData str ->
11550       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11551
11552 let optional_child name xml =
11553   let children = Xml.children xml in
11554   try
11555     Some (List.find (function
11556                      | Xml.Element (n, _, _) when n = name -> true
11557                      | _ -> false) children)
11558   with
11559     Not_found -> None
11560
11561 let child name xml =
11562   match optional_child name xml with
11563   | Some c -> c
11564   | None ->
11565       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11566
11567 let attribute name xml =
11568   try Xml.attrib xml name
11569   with Xml.No_attribute _ ->
11570     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11571
11572 ";
11573
11574   generate_parsers grammar;
11575   pr "\n";
11576
11577   pr "\
11578 (* Run external virt-inspector, then use parser to parse the XML. *)
11579 let inspect ?connect ?xml names =
11580   let xml =
11581     match xml with
11582     | None ->
11583         if names = [] then invalid_arg \"inspect: no names given\";
11584         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11585           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11586           names in
11587         let cmd = List.map Filename.quote cmd in
11588         let cmd = String.concat \" \" cmd in
11589         let chan = open_process_in cmd in
11590         let xml = Xml.parse_in chan in
11591         (match close_process_in chan with
11592          | WEXITED 0 -> ()
11593          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11594          | WSIGNALED i | WSTOPPED i ->
11595              failwith (\"external virt-inspector command died or stopped on sig \" ^
11596                        string_of_int i)
11597         );
11598         xml
11599     | Some doc ->
11600         Xml.parse_string doc in
11601   parse_operatingsystems xml
11602 "
11603
11604 (* This is used to generate the src/MAX_PROC_NR file which
11605  * contains the maximum procedure number, a surrogate for the
11606  * ABI version number.  See src/Makefile.am for the details.
11607  *)
11608 and generate_max_proc_nr () =
11609   let proc_nrs = List.map (
11610     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11611   ) daemon_functions in
11612
11613   let max_proc_nr = List.fold_left max 0 proc_nrs in
11614
11615   pr "%d\n" max_proc_nr
11616
11617 let output_to filename k =
11618   let filename_new = filename ^ ".new" in
11619   chan := open_out filename_new;
11620   k ();
11621   close_out !chan;
11622   chan := Pervasives.stdout;
11623
11624   (* Is the new file different from the current file? *)
11625   if Sys.file_exists filename && files_equal filename filename_new then
11626     unlink filename_new                 (* same, so skip it *)
11627   else (
11628     (* different, overwrite old one *)
11629     (try chmod filename 0o644 with Unix_error _ -> ());
11630     rename filename_new filename;
11631     chmod filename 0o444;
11632     printf "written %s\n%!" filename;
11633   )
11634
11635 let perror msg = function
11636   | Unix_error (err, _, _) ->
11637       eprintf "%s: %s\n" msg (error_message err)
11638   | exn ->
11639       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11640
11641 (* Main program. *)
11642 let () =
11643   let lock_fd =
11644     try openfile "HACKING" [O_RDWR] 0
11645     with
11646     | Unix_error (ENOENT, _, _) ->
11647         eprintf "\
11648 You are probably running this from the wrong directory.
11649 Run it from the top source directory using the command
11650   src/generator.ml
11651 ";
11652         exit 1
11653     | exn ->
11654         perror "open: HACKING" exn;
11655         exit 1 in
11656
11657   (* Acquire a lock so parallel builds won't try to run the generator
11658    * twice at the same time.  Subsequent builds will wait for the first
11659    * one to finish.  Note the lock is released implicitly when the
11660    * program exits.
11661    *)
11662   (try lockf lock_fd F_LOCK 1
11663    with exn ->
11664      perror "lock: HACKING" exn;
11665      exit 1);
11666
11667   check_functions ();
11668
11669   output_to "src/guestfs_protocol.x" generate_xdr;
11670   output_to "src/guestfs-structs.h" generate_structs_h;
11671   output_to "src/guestfs-actions.h" generate_actions_h;
11672   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11673   output_to "src/guestfs-actions.c" generate_client_actions;
11674   output_to "src/guestfs-bindtests.c" generate_bindtests;
11675   output_to "src/guestfs-structs.pod" generate_structs_pod;
11676   output_to "src/guestfs-actions.pod" generate_actions_pod;
11677   output_to "src/guestfs-availability.pod" generate_availability_pod;
11678   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11679   output_to "src/libguestfs.syms" generate_linker_script;
11680   output_to "daemon/actions.h" generate_daemon_actions_h;
11681   output_to "daemon/stubs.c" generate_daemon_actions;
11682   output_to "daemon/names.c" generate_daemon_names;
11683   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11684   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11685   output_to "capitests/tests.c" generate_tests;
11686   output_to "fish/cmds.c" generate_fish_cmds;
11687   output_to "fish/completion.c" generate_fish_completion;
11688   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11689   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11690   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11691   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11692   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11693   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11694   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11695   output_to "perl/Guestfs.xs" generate_perl_xs;
11696   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11697   output_to "perl/bindtests.pl" generate_perl_bindtests;
11698   output_to "python/guestfs-py.c" generate_python_c;
11699   output_to "python/guestfs.py" generate_python_py;
11700   output_to "python/bindtests.py" generate_python_bindtests;
11701   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11702   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11703   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11704
11705   List.iter (
11706     fun (typ, jtyp) ->
11707       let cols = cols_of_struct typ in
11708       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11709       output_to filename (generate_java_struct jtyp cols);
11710   ) java_structs;
11711
11712   output_to "java/Makefile.inc" generate_java_makefile_inc;
11713   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11714   output_to "java/Bindtests.java" generate_java_bindtests;
11715   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11716   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11717   output_to "csharp/Libguestfs.cs" generate_csharp;
11718
11719   (* Always generate this file last, and unconditionally.  It's used
11720    * by the Makefile to know when we must re-run the generator.
11721    *)
11722   let chan = open_out "src/stamp-generator" in
11723   fprintf chan "1\n";
11724   close_out chan;
11725
11726   printf "generated %d lines of code\n" !lines