c6a12627199ea342ccfc56a88642e27993c69671
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
811
812 I<Note:> Don't use this call to test for availability
813 of features.  In enterprise distributions we backport
814 features from later versions into earlier versions,
815 making this an unreliable way to test for features.
816 Use C<guestfs_available> instead.");
817
818   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
819    [InitNone, Always, TestOutputTrue (
820       [["set_selinux"; "true"];
821        ["get_selinux"]])],
822    "set SELinux enabled or disabled at appliance boot",
823    "\
824 This sets the selinux flag that is passed to the appliance
825 at boot time.  The default is C<selinux=0> (disabled).
826
827 Note that if SELinux is enabled, it is always in
828 Permissive mode (C<enforcing=0>).
829
830 For more information on the architecture of libguestfs,
831 see L<guestfs(3)>.");
832
833   ("get_selinux", (RBool "selinux", []), -1, [],
834    [],
835    "get SELinux enabled flag",
836    "\
837 This returns the current setting of the selinux flag which
838 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
839
840 For more information on the architecture of libguestfs,
841 see L<guestfs(3)>.");
842
843   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
844    [InitNone, Always, TestOutputFalse (
845       [["set_trace"; "false"];
846        ["get_trace"]])],
847    "enable or disable command traces",
848    "\
849 If the command trace flag is set to 1, then commands are
850 printed on stdout before they are executed in a format
851 which is very similar to the one used by guestfish.  In
852 other words, you can run a program with this enabled, and
853 you will get out a script which you can feed to guestfish
854 to perform the same set of actions.
855
856 If you want to trace C API calls into libguestfs (and
857 other libraries) then possibly a better way is to use
858 the external ltrace(1) command.
859
860 Command traces are disabled unless the environment variable
861 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
862
863   ("get_trace", (RBool "trace", []), -1, [],
864    [],
865    "get command trace enabled flag",
866    "\
867 Return the command trace flag.");
868
869   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
870    [InitNone, Always, TestOutputFalse (
871       [["set_direct"; "false"];
872        ["get_direct"]])],
873    "enable or disable direct appliance mode",
874    "\
875 If the direct appliance mode flag is enabled, then stdin and
876 stdout are passed directly through to the appliance once it
877 is launched.
878
879 One consequence of this is that log messages aren't caught
880 by the library and handled by C<guestfs_set_log_message_callback>,
881 but go straight to stdout.
882
883 You probably don't want to use this unless you know what you
884 are doing.
885
886 The default is disabled.");
887
888   ("get_direct", (RBool "direct", []), -1, [],
889    [],
890    "get direct appliance mode flag",
891    "\
892 Return the direct appliance mode flag.");
893
894   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
895    [InitNone, Always, TestOutputTrue (
896       [["set_recovery_proc"; "true"];
897        ["get_recovery_proc"]])],
898    "enable or disable the recovery process",
899    "\
900 If this is called with the parameter C<false> then
901 C<guestfs_launch> does not create a recovery process.  The
902 purpose of the recovery process is to stop runaway qemu
903 processes in the case where the main program aborts abruptly.
904
905 This only has any effect if called before C<guestfs_launch>,
906 and the default is true.
907
908 About the only time when you would want to disable this is
909 if the main process will fork itself into the background
910 (\"daemonize\" itself).  In this case the recovery process
911 thinks that the main program has disappeared and so kills
912 qemu, which is not very helpful.");
913
914   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
915    [],
916    "get recovery process enabled flag",
917    "\
918 Return the recovery process enabled flag.");
919
920   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
928    [],
929    "add a drive read-only specifying the QEMU block emulation to use",
930    "\
931 This is the same as C<guestfs_add_drive_ro> but it allows you
932 to specify the QEMU interface emulation to use at run time.");
933
934 ]
935
936 (* daemon_functions are any functions which cause some action
937  * to take place in the daemon.
938  *)
939
940 let daemon_functions = [
941   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
942    [InitEmpty, Always, TestOutput (
943       [["part_disk"; "/dev/sda"; "mbr"];
944        ["mkfs"; "ext2"; "/dev/sda1"];
945        ["mount"; "/dev/sda1"; "/"];
946        ["write"; "/new"; "new file contents"];
947        ["cat"; "/new"]], "new file contents")],
948    "mount a guest disk at a position in the filesystem",
949    "\
950 Mount a guest disk at a position in the filesystem.  Block devices
951 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
952 the guest.  If those block devices contain partitions, they will have
953 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
954 names can be used.
955
956 The rules are the same as for L<mount(2)>:  A filesystem must
957 first be mounted on C</> before others can be mounted.  Other
958 filesystems can only be mounted on directories which already
959 exist.
960
961 The mounted filesystem is writable, if we have sufficient permissions
962 on the underlying device.
963
964 B<Important note:>
965 When you use this call, the filesystem options C<sync> and C<noatime>
966 are set implicitly.  This was originally done because we thought it
967 would improve reliability, but it turns out that I<-o sync> has a
968 very large negative performance impact and negligible effect on
969 reliability.  Therefore we recommend that you avoid using
970 C<guestfs_mount> in any code that needs performance, and instead
971 use C<guestfs_mount_options> (use an empty string for the first
972 parameter if you don't want any options).");
973
974   ("sync", (RErr, []), 2, [],
975    [ InitEmpty, Always, TestRun [["sync"]]],
976    "sync disks, writes are flushed through to the disk image",
977    "\
978 This syncs the disk, so that any writes are flushed through to the
979 underlying disk image.
980
981 You should always call this if you have modified a disk image, before
982 closing the handle.");
983
984   ("touch", (RErr, [Pathname "path"]), 3, [],
985    [InitBasicFS, Always, TestOutputTrue (
986       [["touch"; "/new"];
987        ["exists"; "/new"]])],
988    "update file timestamps or create a new file",
989    "\
990 Touch acts like the L<touch(1)> command.  It can be used to
991 update the timestamps on a file, or, if the file does not exist,
992 to create a new zero-length file.");
993
994   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
995    [InitISOFS, Always, TestOutput (
996       [["cat"; "/known-2"]], "abcdef\n")],
997    "list the contents of a file",
998    "\
999 Return the contents of the file named C<path>.
1000
1001 Note that this function cannot correctly handle binary files
1002 (specifically, files containing C<\\0> character which is treated
1003 as end of string).  For those you need to use the C<guestfs_read_file>
1004 or C<guestfs_download> functions which have a more complex interface.");
1005
1006   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1007    [], (* XXX Tricky to test because it depends on the exact format
1008         * of the 'ls -l' command, which changes between F10 and F11.
1009         *)
1010    "list the files in a directory (long format)",
1011    "\
1012 List the files in C<directory> (relative to the root directory,
1013 there is no cwd) in the format of 'ls -la'.
1014
1015 This command is mostly useful for interactive sessions.  It
1016 is I<not> intended that you try to parse the output string.");
1017
1018   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1019    [InitBasicFS, Always, TestOutputList (
1020       [["touch"; "/new"];
1021        ["touch"; "/newer"];
1022        ["touch"; "/newest"];
1023        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1024    "list the files in a directory",
1025    "\
1026 List the files in C<directory> (relative to the root directory,
1027 there is no cwd).  The '.' and '..' entries are not returned, but
1028 hidden files are shown.
1029
1030 This command is mostly useful for interactive sessions.  Programs
1031 should probably use C<guestfs_readdir> instead.");
1032
1033   ("list_devices", (RStringList "devices", []), 7, [],
1034    [InitEmpty, Always, TestOutputListOfDevices (
1035       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1036    "list the block devices",
1037    "\
1038 List all the block devices.
1039
1040 The full block device names are returned, eg. C</dev/sda>");
1041
1042   ("list_partitions", (RStringList "partitions", []), 8, [],
1043    [InitBasicFS, Always, TestOutputListOfDevices (
1044       [["list_partitions"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048    "list the partitions",
1049    "\
1050 List all the partitions detected on all block devices.
1051
1052 The full partition device names are returned, eg. C</dev/sda1>
1053
1054 This does not return logical volumes.  For that you will need to
1055 call C<guestfs_lvs>.");
1056
1057   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1058    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1059       [["pvs"]], ["/dev/sda1"]);
1060     InitEmpty, Always, TestOutputListOfDevices (
1061       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1062        ["pvcreate"; "/dev/sda1"];
1063        ["pvcreate"; "/dev/sda2"];
1064        ["pvcreate"; "/dev/sda3"];
1065        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1066    "list the LVM physical volumes (PVs)",
1067    "\
1068 List all the physical volumes detected.  This is the equivalent
1069 of the L<pvs(8)> command.
1070
1071 This returns a list of just the device names that contain
1072 PVs (eg. C</dev/sda2>).
1073
1074 See also C<guestfs_pvs_full>.");
1075
1076   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1077    [InitBasicFSonLVM, Always, TestOutputList (
1078       [["vgs"]], ["VG"]);
1079     InitEmpty, Always, TestOutputList (
1080       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1081        ["pvcreate"; "/dev/sda1"];
1082        ["pvcreate"; "/dev/sda2"];
1083        ["pvcreate"; "/dev/sda3"];
1084        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1085        ["vgcreate"; "VG2"; "/dev/sda3"];
1086        ["vgs"]], ["VG1"; "VG2"])],
1087    "list the LVM volume groups (VGs)",
1088    "\
1089 List all the volumes groups detected.  This is the equivalent
1090 of the L<vgs(8)> command.
1091
1092 This returns a list of just the volume group names that were
1093 detected (eg. C<VolGroup00>).
1094
1095 See also C<guestfs_vgs_full>.");
1096
1097   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1098    [InitBasicFSonLVM, Always, TestOutputList (
1099       [["lvs"]], ["/dev/VG/LV"]);
1100     InitEmpty, Always, TestOutputList (
1101       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1102        ["pvcreate"; "/dev/sda1"];
1103        ["pvcreate"; "/dev/sda2"];
1104        ["pvcreate"; "/dev/sda3"];
1105        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1106        ["vgcreate"; "VG2"; "/dev/sda3"];
1107        ["lvcreate"; "LV1"; "VG1"; "50"];
1108        ["lvcreate"; "LV2"; "VG1"; "50"];
1109        ["lvcreate"; "LV3"; "VG2"; "50"];
1110        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1111    "list the LVM logical volumes (LVs)",
1112    "\
1113 List all the logical volumes detected.  This is the equivalent
1114 of the L<lvs(8)> command.
1115
1116 This returns a list of the logical volume device names
1117 (eg. C</dev/VolGroup00/LogVol00>).
1118
1119 See also C<guestfs_lvs_full>.");
1120
1121   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM physical volumes (PVs)",
1124    "\
1125 List all the physical volumes detected.  This is the equivalent
1126 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM volume groups (VGs)",
1131    "\
1132 List all the volumes groups detected.  This is the equivalent
1133 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1136    [], (* XXX how to test? *)
1137    "list the LVM logical volumes (LVs)",
1138    "\
1139 List all the logical volumes detected.  This is the equivalent
1140 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1141
1142   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1143    [InitISOFS, Always, TestOutputList (
1144       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1145     InitISOFS, Always, TestOutputList (
1146       [["read_lines"; "/empty"]], [])],
1147    "read file as lines",
1148    "\
1149 Return the contents of the file named C<path>.
1150
1151 The file contents are returned as a list of lines.  Trailing
1152 C<LF> and C<CRLF> character sequences are I<not> returned.
1153
1154 Note that this function cannot correctly handle binary files
1155 (specifically, files containing C<\\0> character which is treated
1156 as end of line).  For those you need to use the C<guestfs_read_file>
1157 function which has a more complex interface.");
1158
1159   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1160    [], (* XXX Augeas code needs tests. *)
1161    "create a new Augeas handle",
1162    "\
1163 Create a new Augeas handle for editing configuration files.
1164 If there was any previous Augeas handle associated with this
1165 guestfs session, then it is closed.
1166
1167 You must call this before using any other C<guestfs_aug_*>
1168 commands.
1169
1170 C<root> is the filesystem root.  C<root> must not be NULL,
1171 use C</> instead.
1172
1173 The flags are the same as the flags defined in
1174 E<lt>augeas.hE<gt>, the logical I<or> of the following
1175 integers:
1176
1177 =over 4
1178
1179 =item C<AUG_SAVE_BACKUP> = 1
1180
1181 Keep the original file with a C<.augsave> extension.
1182
1183 =item C<AUG_SAVE_NEWFILE> = 2
1184
1185 Save changes into a file with extension C<.augnew>, and
1186 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1187
1188 =item C<AUG_TYPE_CHECK> = 4
1189
1190 Typecheck lenses (can be expensive).
1191
1192 =item C<AUG_NO_STDINC> = 8
1193
1194 Do not use standard load path for modules.
1195
1196 =item C<AUG_SAVE_NOOP> = 16
1197
1198 Make save a no-op, just record what would have been changed.
1199
1200 =item C<AUG_NO_LOAD> = 32
1201
1202 Do not load the tree in C<guestfs_aug_init>.
1203
1204 =back
1205
1206 To close the handle, you can call C<guestfs_aug_close>.
1207
1208 To find out more about Augeas, see L<http://augeas.net/>.");
1209
1210   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1211    [], (* XXX Augeas code needs tests. *)
1212    "close the current Augeas handle",
1213    "\
1214 Close the current Augeas handle and free up any resources
1215 used by it.  After calling this, you have to call
1216 C<guestfs_aug_init> again before you can use any other
1217 Augeas functions.");
1218
1219   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "define an Augeas variable",
1222    "\
1223 Defines an Augeas variable C<name> whose value is the result
1224 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1225 undefined.
1226
1227 On success this returns the number of nodes in C<expr>, or
1228 C<0> if C<expr> evaluates to something which is not a nodeset.");
1229
1230   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "define an Augeas node",
1233    "\
1234 Defines a variable C<name> whose value is the result of
1235 evaluating C<expr>.
1236
1237 If C<expr> evaluates to an empty nodeset, a node is created,
1238 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1239 C<name> will be the nodeset containing that single node.
1240
1241 On success this returns a pair containing the
1242 number of nodes in the nodeset, and a boolean flag
1243 if a node was created.");
1244
1245   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "look up the value of an Augeas path",
1248    "\
1249 Look up the value associated with C<path>.  If C<path>
1250 matches exactly one node, the C<value> is returned.");
1251
1252   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "set Augeas path to value",
1255    "\
1256 Set the value associated with C<path> to C<val>.
1257
1258 In the Augeas API, it is possible to clear a node by setting
1259 the value to NULL.  Due to an oversight in the libguestfs API
1260 you cannot do that with this call.  Instead you must use the
1261 C<guestfs_aug_clear> call.");
1262
1263   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "insert a sibling Augeas node",
1266    "\
1267 Create a new sibling C<label> for C<path>, inserting it into
1268 the tree before or after C<path> (depending on the boolean
1269 flag C<before>).
1270
1271 C<path> must match exactly one existing node in the tree, and
1272 C<label> must be a label, ie. not contain C</>, C<*> or end
1273 with a bracketed index C<[N]>.");
1274
1275   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "remove an Augeas path",
1278    "\
1279 Remove C<path> and all of its children.
1280
1281 On success this returns the number of entries which were removed.");
1282
1283   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1284    [], (* XXX Augeas code needs tests. *)
1285    "move Augeas node",
1286    "\
1287 Move the node C<src> to C<dest>.  C<src> must match exactly
1288 one node.  C<dest> is overwritten if it exists.");
1289
1290   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "return Augeas nodes which match augpath",
1293    "\
1294 Returns a list of paths which match the path expression C<path>.
1295 The returned paths are sufficiently qualified so that they match
1296 exactly one node in the current tree.");
1297
1298   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1299    [], (* XXX Augeas code needs tests. *)
1300    "write all pending Augeas changes to disk",
1301    "\
1302 This writes all pending changes to disk.
1303
1304 The flags which were passed to C<guestfs_aug_init> affect exactly
1305 how files are saved.");
1306
1307   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1308    [], (* XXX Augeas code needs tests. *)
1309    "load files into the tree",
1310    "\
1311 Load files into the tree.
1312
1313 See C<aug_load> in the Augeas documentation for the full gory
1314 details.");
1315
1316   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1317    [], (* XXX Augeas code needs tests. *)
1318    "list Augeas nodes under augpath",
1319    "\
1320 This is just a shortcut for listing C<guestfs_aug_match>
1321 C<path/*> and sorting the resulting nodes into alphabetical order.");
1322
1323   ("rm", (RErr, [Pathname "path"]), 29, [],
1324    [InitBasicFS, Always, TestRun
1325       [["touch"; "/new"];
1326        ["rm"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["rm"; "/new"]];
1329     InitBasicFS, Always, TestLastFail
1330       [["mkdir"; "/new"];
1331        ["rm"; "/new"]]],
1332    "remove a file",
1333    "\
1334 Remove the single file C<path>.");
1335
1336   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1337    [InitBasicFS, Always, TestRun
1338       [["mkdir"; "/new"];
1339        ["rmdir"; "/new"]];
1340     InitBasicFS, Always, TestLastFail
1341       [["rmdir"; "/new"]];
1342     InitBasicFS, Always, TestLastFail
1343       [["touch"; "/new"];
1344        ["rmdir"; "/new"]]],
1345    "remove a directory",
1346    "\
1347 Remove the single directory C<path>.");
1348
1349   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1350    [InitBasicFS, Always, TestOutputFalse
1351       [["mkdir"; "/new"];
1352        ["mkdir"; "/new/foo"];
1353        ["touch"; "/new/foo/bar"];
1354        ["rm_rf"; "/new"];
1355        ["exists"; "/new"]]],
1356    "remove a file or directory recursively",
1357    "\
1358 Remove the file or directory C<path>, recursively removing the
1359 contents if its a directory.  This is like the C<rm -rf> shell
1360 command.");
1361
1362   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir"; "/new"];
1365        ["is_dir"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["mkdir"; "/new/foo/bar"]]],
1368    "create a directory",
1369    "\
1370 Create a directory named C<path>.");
1371
1372   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1373    [InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo/bar"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new/foo"]];
1379     InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new"]];
1382     (* Regression tests for RHBZ#503133: *)
1383     InitBasicFS, Always, TestRun
1384       [["mkdir"; "/new"];
1385        ["mkdir_p"; "/new"]];
1386     InitBasicFS, Always, TestLastFail
1387       [["touch"; "/new"];
1388        ["mkdir_p"; "/new"]]],
1389    "create a directory and parents",
1390    "\
1391 Create a directory named C<path>, creating any parent directories
1392 as necessary.  This is like the C<mkdir -p> shell command.");
1393
1394   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1395    [], (* XXX Need stat command to test *)
1396    "change file mode",
1397    "\
1398 Change the mode (permissions) of C<path> to C<mode>.  Only
1399 numeric modes are supported.
1400
1401 I<Note>: When using this command from guestfish, C<mode>
1402 by default would be decimal, unless you prefix it with
1403 C<0> to get octal, ie. use C<0700> not C<700>.
1404
1405 The mode actually set is affected by the umask.");
1406
1407   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1408    [], (* XXX Need stat command to test *)
1409    "change file owner and group",
1410    "\
1411 Change the file owner to C<owner> and group to C<group>.
1412
1413 Only numeric uid and gid are supported.  If you want to use
1414 names, you will need to locate and parse the password file
1415 yourself (Augeas support makes this relatively easy).");
1416
1417   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["exists"; "/empty"]]);
1420     InitISOFS, Always, TestOutputTrue (
1421       [["exists"; "/directory"]])],
1422    "test if file or directory exists",
1423    "\
1424 This returns C<true> if and only if there is a file, directory
1425 (or anything) with the given C<path> name.
1426
1427 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1428
1429   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1430    [InitISOFS, Always, TestOutputTrue (
1431       [["is_file"; "/known-1"]]);
1432     InitISOFS, Always, TestOutputFalse (
1433       [["is_file"; "/directory"]])],
1434    "test if file exists",
1435    "\
1436 This returns C<true> if and only if there is a file
1437 with the given C<path> name.  Note that it returns false for
1438 other objects like directories.
1439
1440 See also C<guestfs_stat>.");
1441
1442   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1443    [InitISOFS, Always, TestOutputFalse (
1444       [["is_dir"; "/known-3"]]);
1445     InitISOFS, Always, TestOutputTrue (
1446       [["is_dir"; "/directory"]])],
1447    "test if file exists",
1448    "\
1449 This returns C<true> if and only if there is a directory
1450 with the given C<path> name.  Note that it returns false for
1451 other objects like files.
1452
1453 See also C<guestfs_stat>.");
1454
1455   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1456    [InitEmpty, Always, TestOutputListOfDevices (
1457       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458        ["pvcreate"; "/dev/sda1"];
1459        ["pvcreate"; "/dev/sda2"];
1460        ["pvcreate"; "/dev/sda3"];
1461        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1462    "create an LVM physical volume",
1463    "\
1464 This creates an LVM physical volume on the named C<device>,
1465 where C<device> should usually be a partition name such
1466 as C</dev/sda1>.");
1467
1468   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1469    [InitEmpty, Always, TestOutputList (
1470       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1471        ["pvcreate"; "/dev/sda1"];
1472        ["pvcreate"; "/dev/sda2"];
1473        ["pvcreate"; "/dev/sda3"];
1474        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1475        ["vgcreate"; "VG2"; "/dev/sda3"];
1476        ["vgs"]], ["VG1"; "VG2"])],
1477    "create an LVM volume group",
1478    "\
1479 This creates an LVM volume group called C<volgroup>
1480 from the non-empty list of physical volumes C<physvols>.");
1481
1482   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1483    [InitEmpty, Always, TestOutputList (
1484       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1485        ["pvcreate"; "/dev/sda1"];
1486        ["pvcreate"; "/dev/sda2"];
1487        ["pvcreate"; "/dev/sda3"];
1488        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1489        ["vgcreate"; "VG2"; "/dev/sda3"];
1490        ["lvcreate"; "LV1"; "VG1"; "50"];
1491        ["lvcreate"; "LV2"; "VG1"; "50"];
1492        ["lvcreate"; "LV3"; "VG2"; "50"];
1493        ["lvcreate"; "LV4"; "VG2"; "50"];
1494        ["lvcreate"; "LV5"; "VG2"; "50"];
1495        ["lvs"]],
1496       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1497        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1498    "create an LVM logical volume",
1499    "\
1500 This creates an LVM logical volume called C<logvol>
1501 on the volume group C<volgroup>, with C<size> megabytes.");
1502
1503   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1504    [InitEmpty, Always, TestOutput (
1505       [["part_disk"; "/dev/sda"; "mbr"];
1506        ["mkfs"; "ext2"; "/dev/sda1"];
1507        ["mount_options"; ""; "/dev/sda1"; "/"];
1508        ["write"; "/new"; "new file contents"];
1509        ["cat"; "/new"]], "new file contents")],
1510    "make a filesystem",
1511    "\
1512 This creates a filesystem on C<device> (usually a partition
1513 or LVM logical volume).  The filesystem type is C<fstype>, for
1514 example C<ext3>.");
1515
1516   ("sfdisk", (RErr, [Device "device";
1517                      Int "cyls"; Int "heads"; Int "sectors";
1518                      StringList "lines"]), 43, [DangerWillRobinson],
1519    [],
1520    "create partitions on a block device",
1521    "\
1522 This is a direct interface to the L<sfdisk(8)> program for creating
1523 partitions on block devices.
1524
1525 C<device> should be a block device, for example C</dev/sda>.
1526
1527 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1528 and sectors on the device, which are passed directly to sfdisk as
1529 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1530 of these, then the corresponding parameter is omitted.  Usually for
1531 'large' disks, you can just pass C<0> for these, but for small
1532 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1533 out the right geometry and you will need to tell it.
1534
1535 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1536 information refer to the L<sfdisk(8)> manpage.
1537
1538 To create a single partition occupying the whole disk, you would
1539 pass C<lines> as a single element list, when the single element being
1540 the string C<,> (comma).
1541
1542 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1543 C<guestfs_part_init>");
1544
1545   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1546    [],
1547    "create a file",
1548    "\
1549 This call creates a file called C<path>.  The contents of the
1550 file is the string C<content> (which can contain any 8 bit data),
1551 with length C<size>.
1552
1553 As a special case, if C<size> is C<0>
1554 then the length is calculated using C<strlen> (so in this case
1555 the content cannot contain embedded ASCII NULs).
1556
1557 I<NB.> Owing to a bug, writing content containing ASCII NUL
1558 characters does I<not> work, even if the length is specified.");
1559
1560   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1561    [InitEmpty, Always, TestOutputListOfDevices (
1562       [["part_disk"; "/dev/sda"; "mbr"];
1563        ["mkfs"; "ext2"; "/dev/sda1"];
1564        ["mount_options"; ""; "/dev/sda1"; "/"];
1565        ["mounts"]], ["/dev/sda1"]);
1566     InitEmpty, Always, TestOutputList (
1567       [["part_disk"; "/dev/sda"; "mbr"];
1568        ["mkfs"; "ext2"; "/dev/sda1"];
1569        ["mount_options"; ""; "/dev/sda1"; "/"];
1570        ["umount"; "/"];
1571        ["mounts"]], [])],
1572    "unmount a filesystem",
1573    "\
1574 This unmounts the given filesystem.  The filesystem may be
1575 specified either by its mountpoint (path) or the device which
1576 contains the filesystem.");
1577
1578   ("mounts", (RStringList "devices", []), 46, [],
1579    [InitBasicFS, Always, TestOutputListOfDevices (
1580       [["mounts"]], ["/dev/sda1"])],
1581    "show mounted filesystems",
1582    "\
1583 This returns the list of currently mounted filesystems.  It returns
1584 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1585
1586 Some internal mounts are not shown.
1587
1588 See also: C<guestfs_mountpoints>");
1589
1590   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1591    [InitBasicFS, Always, TestOutputList (
1592       [["umount_all"];
1593        ["mounts"]], []);
1594     (* check that umount_all can unmount nested mounts correctly: *)
1595     InitEmpty, Always, TestOutputList (
1596       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1597        ["mkfs"; "ext2"; "/dev/sda1"];
1598        ["mkfs"; "ext2"; "/dev/sda2"];
1599        ["mkfs"; "ext2"; "/dev/sda3"];
1600        ["mount_options"; ""; "/dev/sda1"; "/"];
1601        ["mkdir"; "/mp1"];
1602        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1603        ["mkdir"; "/mp1/mp2"];
1604        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1605        ["mkdir"; "/mp1/mp2/mp3"];
1606        ["umount_all"];
1607        ["mounts"]], [])],
1608    "unmount all filesystems",
1609    "\
1610 This unmounts all mounted filesystems.
1611
1612 Some internal mounts are not unmounted by this call.");
1613
1614   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1615    [],
1616    "remove all LVM LVs, VGs and PVs",
1617    "\
1618 This command removes all LVM logical volumes, volume groups
1619 and physical volumes.");
1620
1621   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1622    [InitISOFS, Always, TestOutput (
1623       [["file"; "/empty"]], "empty");
1624     InitISOFS, Always, TestOutput (
1625       [["file"; "/known-1"]], "ASCII text");
1626     InitISOFS, Always, TestLastFail (
1627       [["file"; "/notexists"]])],
1628    "determine file type",
1629    "\
1630 This call uses the standard L<file(1)> command to determine
1631 the type or contents of the file.  This also works on devices,
1632 for example to find out whether a partition contains a filesystem.
1633
1634 This call will also transparently look inside various types
1635 of compressed file.
1636
1637 The exact command which runs is C<file -zbsL path>.  Note in
1638 particular that the filename is not prepended to the output
1639 (the C<-b> option).");
1640
1641   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1642    [InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 1"]], "Result1");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 2"]], "Result2\n");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 3"]], "\nResult3");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 4"]], "\nResult4\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 5"]], "\nResult5\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 7"]], "");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 8"]], "\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 9"]], "\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1686     InitBasicFS, Always, TestLastFail (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command"]])],
1690    "run a command from the guest filesystem",
1691    "\
1692 This call runs a command from the guest filesystem.  The
1693 filesystem must be mounted, and must contain a compatible
1694 operating system (ie. something Linux, with the same
1695 or compatible processor architecture).
1696
1697 The single parameter is an argv-style list of arguments.
1698 The first element is the name of the program to run.
1699 Subsequent elements are parameters.  The list must be
1700 non-empty (ie. must contain a program name).  Note that
1701 the command runs directly, and is I<not> invoked via
1702 the shell (see C<guestfs_sh>).
1703
1704 The return value is anything printed to I<stdout> by
1705 the command.
1706
1707 If the command returns a non-zero exit status, then
1708 this function returns an error message.  The error message
1709 string is the content of I<stderr> from the command.
1710
1711 The C<$PATH> environment variable will contain at least
1712 C</usr/bin> and C</bin>.  If you require a program from
1713 another location, you should provide the full path in the
1714 first parameter.
1715
1716 Shared libraries and data files required by the program
1717 must be available on filesystems which are mounted in the
1718 correct places.  It is the caller's responsibility to ensure
1719 all filesystems that are needed are mounted at the right
1720 locations.");
1721
1722   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1723    [InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 1"]], ["Result1"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 2"]], ["Result2"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 7"]], []);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 8"]], [""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 9"]], ["";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1767    "run a command, returning lines",
1768    "\
1769 This is the same as C<guestfs_command>, but splits the
1770 result into a list of lines.
1771
1772 See also: C<guestfs_sh_lines>");
1773
1774   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1775    [InitISOFS, Always, TestOutputStruct (
1776       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1777    "get file information",
1778    "\
1779 Returns file information for the given C<path>.
1780
1781 This is the same as the C<stat(2)> system call.");
1782
1783   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information for a symbolic link",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as C<guestfs_stat> except that if C<path>
1791 is a symbolic link, then the link is stat-ed, not the file it
1792 refers to.
1793
1794 This is the same as the C<lstat(2)> system call.");
1795
1796   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1797    [InitISOFS, Always, TestOutputStruct (
1798       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1799    "get file system statistics",
1800    "\
1801 Returns file system statistics for any mounted file system.
1802 C<path> should be a file or directory in the mounted file system
1803 (typically it is the mount point itself, but it doesn't need to be).
1804
1805 This is the same as the C<statvfs(2)> system call.");
1806
1807   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1808    [], (* XXX test *)
1809    "get ext2/ext3/ext4 superblock details",
1810    "\
1811 This returns the contents of the ext2, ext3 or ext4 filesystem
1812 superblock on C<device>.
1813
1814 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1815 manpage for more details.  The list of fields returned isn't
1816 clearly defined, and depends on both the version of C<tune2fs>
1817 that libguestfs was built against, and the filesystem itself.");
1818
1819   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1820    [InitEmpty, Always, TestOutputTrue (
1821       [["blockdev_setro"; "/dev/sda"];
1822        ["blockdev_getro"; "/dev/sda"]])],
1823    "set block device to read-only",
1824    "\
1825 Sets the block device named C<device> to read-only.
1826
1827 This uses the L<blockdev(8)> command.");
1828
1829   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1830    [InitEmpty, Always, TestOutputFalse (
1831       [["blockdev_setrw"; "/dev/sda"];
1832        ["blockdev_getro"; "/dev/sda"]])],
1833    "set block device to read-write",
1834    "\
1835 Sets the block device named C<device> to read-write.
1836
1837 This uses the L<blockdev(8)> command.");
1838
1839   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1840    [InitEmpty, Always, TestOutputTrue (
1841       [["blockdev_setro"; "/dev/sda"];
1842        ["blockdev_getro"; "/dev/sda"]])],
1843    "is block device set to read-only",
1844    "\
1845 Returns a boolean indicating if the block device is read-only
1846 (true if read-only, false if not).
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1851    [InitEmpty, Always, TestOutputInt (
1852       [["blockdev_getss"; "/dev/sda"]], 512)],
1853    "get sectorsize of block device",
1854    "\
1855 This returns the size of sectors on a block device.
1856 Usually 512, but can be larger for modern devices.
1857
1858 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1859 for that).
1860
1861 This uses the L<blockdev(8)> command.");
1862
1863   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1864    [InitEmpty, Always, TestOutputInt (
1865       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1866    "get blocksize of block device",
1867    "\
1868 This returns the block size of a device.
1869
1870 (Note this is different from both I<size in blocks> and
1871 I<filesystem block size>).
1872
1873 This uses the L<blockdev(8)> command.");
1874
1875   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1876    [], (* XXX test *)
1877    "set blocksize of block device",
1878    "\
1879 This sets the block size of a device.
1880
1881 (Note this is different from both I<size in blocks> and
1882 I<filesystem block size>).
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1887    [InitEmpty, Always, TestOutputInt (
1888       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1889    "get total size of device in 512-byte sectors",
1890    "\
1891 This returns the size of the device in units of 512-byte sectors
1892 (even if the sectorsize isn't 512 bytes ... weird).
1893
1894 See also C<guestfs_blockdev_getss> for the real sector size of
1895 the device, and C<guestfs_blockdev_getsize64> for the more
1896 useful I<size in bytes>.
1897
1898 This uses the L<blockdev(8)> command.");
1899
1900   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1901    [InitEmpty, Always, TestOutputInt (
1902       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1903    "get total size of device in bytes",
1904    "\
1905 This returns the size of the device in bytes.
1906
1907 See also C<guestfs_blockdev_getsz>.
1908
1909 This uses the L<blockdev(8)> command.");
1910
1911   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1912    [InitEmpty, Always, TestRun
1913       [["blockdev_flushbufs"; "/dev/sda"]]],
1914    "flush device buffers",
1915    "\
1916 This tells the kernel to flush internal buffers associated
1917 with C<device>.
1918
1919 This uses the L<blockdev(8)> command.");
1920
1921   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1922    [InitEmpty, Always, TestRun
1923       [["blockdev_rereadpt"; "/dev/sda"]]],
1924    "reread partition table",
1925    "\
1926 Reread the partition table on C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1931    [InitBasicFS, Always, TestOutput (
1932       (* Pick a file from cwd which isn't likely to change. *)
1933       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1934        ["checksum"; "md5"; "/COPYING.LIB"]],
1935       Digest.to_hex (Digest.file "COPYING.LIB"))],
1936    "upload a file from the local machine",
1937    "\
1938 Upload local file C<filename> to C<remotefilename> on the
1939 filesystem.
1940
1941 C<filename> can also be a named pipe.
1942
1943 See also C<guestfs_download>.");
1944
1945   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1946    [InitBasicFS, Always, TestOutput (
1947       (* Pick a file from cwd which isn't likely to change. *)
1948       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1949        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1950        ["upload"; "testdownload.tmp"; "/upload"];
1951        ["checksum"; "md5"; "/upload"]],
1952       Digest.to_hex (Digest.file "COPYING.LIB"))],
1953    "download a file to the local machine",
1954    "\
1955 Download file C<remotefilename> and save it as C<filename>
1956 on the local machine.
1957
1958 C<filename> can also be a named pipe.
1959
1960 See also C<guestfs_upload>, C<guestfs_cat>.");
1961
1962   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1963    [InitISOFS, Always, TestOutput (
1964       [["checksum"; "crc"; "/known-3"]], "2891671662");
1965     InitISOFS, Always, TestLastFail (
1966       [["checksum"; "crc"; "/notexists"]]);
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1979     (* Test for RHBZ#579608, absolute symbolic links. *)
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1982    "compute MD5, SHAx or CRC checksum of file",
1983    "\
1984 This call computes the MD5, SHAx or CRC checksum of the
1985 file named C<path>.
1986
1987 The type of checksum to compute is given by the C<csumtype>
1988 parameter which must have one of the following values:
1989
1990 =over 4
1991
1992 =item C<crc>
1993
1994 Compute the cyclic redundancy check (CRC) specified by POSIX
1995 for the C<cksum> command.
1996
1997 =item C<md5>
1998
1999 Compute the MD5 hash (using the C<md5sum> program).
2000
2001 =item C<sha1>
2002
2003 Compute the SHA1 hash (using the C<sha1sum> program).
2004
2005 =item C<sha224>
2006
2007 Compute the SHA224 hash (using the C<sha224sum> program).
2008
2009 =item C<sha256>
2010
2011 Compute the SHA256 hash (using the C<sha256sum> program).
2012
2013 =item C<sha384>
2014
2015 Compute the SHA384 hash (using the C<sha384sum> program).
2016
2017 =item C<sha512>
2018
2019 Compute the SHA512 hash (using the C<sha512sum> program).
2020
2021 =back
2022
2023 The checksum is returned as a printable string.
2024
2025 To get the checksum for a device, use C<guestfs_checksum_device>.
2026
2027 To get the checksums for many files, use C<guestfs_checksums_out>.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2040
2041   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042    [],
2043    "pack directory into tarfile",
2044    "\
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2047
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write"; "/new"; "data"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.
2093
2094 If the C<options> parameter is an empty string, then
2095 no options are passed (all options default to whatever
2096 the filesystem uses).");
2097
2098   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2099    [],
2100    "mount a guest disk with mount options and vfstype",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2105
2106   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2107    [],
2108    "debugging and internals",
2109    "\
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2112 qemu subprocess.
2113
2114 There is no comprehensive help for this command.  You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2117
2118   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119    [InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG/LV1"];
2126        ["lvs"]], ["/dev/VG/LV2"]);
2127     InitEmpty, Always, TestOutputList (
2128       [["part_disk"; "/dev/sda"; "mbr"];
2129        ["pvcreate"; "/dev/sda1"];
2130        ["vgcreate"; "VG"; "/dev/sda1"];
2131        ["lvcreate"; "LV1"; "VG"; "50"];
2132        ["lvcreate"; "LV2"; "VG"; "50"];
2133        ["lvremove"; "/dev/VG"];
2134        ["lvs"]], []);
2135     InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG"];
2142        ["vgs"]], ["VG"])],
2143    "remove an LVM logical volume",
2144    "\
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2147
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2150
2151   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152    [InitEmpty, Always, TestOutputList (
2153       [["part_disk"; "/dev/sda"; "mbr"];
2154        ["pvcreate"; "/dev/sda1"];
2155        ["vgcreate"; "VG"; "/dev/sda1"];
2156        ["lvcreate"; "LV1"; "VG"; "50"];
2157        ["lvcreate"; "LV2"; "VG"; "50"];
2158        ["vgremove"; "VG"];
2159        ["lvs"]], []);
2160     InitEmpty, Always, TestOutputList (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["vgs"]], [])],
2168    "remove an LVM volume group",
2169    "\
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2171
2172 This also forcibly removes all logical volumes in the volume
2173 group (if any).");
2174
2175   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2176    [InitEmpty, Always, TestOutputListOfDevices (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["pvremove"; "/dev/sda1"];
2184        ["lvs"]], []);
2185     InitEmpty, Always, TestOutputListOfDevices (
2186       [["part_disk"; "/dev/sda"; "mbr"];
2187        ["pvcreate"; "/dev/sda1"];
2188        ["vgcreate"; "VG"; "/dev/sda1"];
2189        ["lvcreate"; "LV1"; "VG"; "50"];
2190        ["lvcreate"; "LV2"; "VG"; "50"];
2191        ["vgremove"; "VG"];
2192        ["pvremove"; "/dev/sda1"];
2193        ["vgs"]], []);
2194     InitEmpty, Always, TestOutputListOfDevices (
2195       [["part_disk"; "/dev/sda"; "mbr"];
2196        ["pvcreate"; "/dev/sda1"];
2197        ["vgcreate"; "VG"; "/dev/sda1"];
2198        ["lvcreate"; "LV1"; "VG"; "50"];
2199        ["lvcreate"; "LV2"; "VG"; "50"];
2200        ["vgremove"; "VG"];
2201        ["pvremove"; "/dev/sda1"];
2202        ["pvs"]], [])],
2203    "remove an LVM physical volume",
2204    "\
2205 This wipes a physical volume C<device> so that LVM will no longer
2206 recognise it.
2207
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2211
2212   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213    [InitBasicFS, Always, TestOutput (
2214       [["set_e2label"; "/dev/sda1"; "testlabel"];
2215        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216    "set the ext2/3/4 filesystem label",
2217    "\
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>.  Filesystem labels are limited to
2220 16 characters.
2221
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2224
2225   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2226    [],
2227    "get the ext2/3/4 filesystem label",
2228    "\
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2230 C<device>.");
2231
2232   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233    (let uuid = uuidgen () in
2234     [InitBasicFS, Always, TestOutput (
2235        [["set_e2uuid"; "/dev/sda1"; uuid];
2236         ["get_e2uuid"; "/dev/sda1"]], uuid);
2237      InitBasicFS, Always, TestOutput (
2238        [["set_e2uuid"; "/dev/sda1"; "clear"];
2239         ["get_e2uuid"; "/dev/sda1"]], "");
2240      (* We can't predict what UUIDs will be, so just check the commands run. *)
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245    "set the ext2/3/4 filesystem UUID",
2246    "\
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>.  The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2251
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2254
2255   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2256    [],
2257    "get the ext2/3/4 filesystem UUID",
2258    "\
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 C<device>.");
2261
2262   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2263    [InitBasicFS, Always, TestOutputInt (
2264       [["umount"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266     InitBasicFS, Always, TestOutputInt (
2267       [["umount"; "/dev/sda1"];
2268        ["zero"; "/dev/sda1"];
2269        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270    "run the filesystem checker",
2271    "\
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2274
2275 The returned integer is the status.  See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2277
2278 Notes:
2279
2280 =over 4
2281
2282 =item *
2283
2284 Multiple status codes can be summed together.
2285
2286 =item *
2287
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2290
2291 =item *
2292
2293 Checking or repairing NTFS volumes is not supported
2294 (by linux-ntfs).
2295
2296 =back
2297
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2299
2300   ("zero", (RErr, [Device "device"]), 85, [],
2301    [InitBasicFS, Always, TestOutput (
2302       [["umount"; "/dev/sda1"];
2303        ["zero"; "/dev/sda1"];
2304        ["file"; "/dev/sda1"]], "data")],
2305    "write zeroes to the device",
2306    "\
2307 This command writes zeroes over the first few blocks of C<device>.
2308
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device).  It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2312
2313 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2314
2315   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316    (* Test disabled because grub-install incompatible with virtio-blk driver.
2317     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2318     *)
2319    [InitBasicFS, Disabled, TestOutputTrue (
2320       [["grub_install"; "/"; "/dev/sda1"];
2321        ["is_dir"; "/boot"]])],
2322    "install GRUB",
2323    "\
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2326
2327   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328    [InitBasicFS, Always, TestOutput (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["cat"; "/new"]], "file content");
2332     InitBasicFS, Always, TestOutputTrue (
2333       [["write"; "/old"; "file content"];
2334        ["cp"; "/old"; "/new"];
2335        ["is_file"; "/old"]]);
2336     InitBasicFS, Always, TestOutput (
2337       [["write"; "/old"; "file content"];
2338        ["mkdir"; "/dir"];
2339        ["cp"; "/old"; "/dir/new"];
2340        ["cat"; "/dir/new"]], "file content")],
2341    "copy a file",
2342    "\
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2345
2346   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347    [InitBasicFS, Always, TestOutput (
2348       [["mkdir"; "/olddir"];
2349        ["mkdir"; "/newdir"];
2350        ["write"; "/olddir/file"; "file content"];
2351        ["cp_a"; "/olddir"; "/newdir"];
2352        ["cat"; "/newdir/olddir/file"]], "file content")],
2353    "copy a file or directory recursively",
2354    "\
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2357
2358   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359    [InitBasicFS, Always, TestOutput (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["cat"; "/new"]], "file content");
2363     InitBasicFS, Always, TestOutputFalse (
2364       [["write"; "/old"; "file content"];
2365        ["mv"; "/old"; "/new"];
2366        ["is_file"; "/old"]])],
2367    "move a file",
2368    "\
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2371
2372   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373    [InitEmpty, Always, TestRun (
2374       [["drop_caches"; "3"]])],
2375    "drop kernel page cache, dentries and inodes",
2376    "\
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches.  The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2381
2382 Setting C<whattodrop> to 3 should drop everything.
2383
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2386
2387   ("dmesg", (RString "kmsgs", []), 91, [],
2388    [InitEmpty, Always, TestRun (
2389       [["dmesg"]])],
2390    "return kernel messages",
2391    "\
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel.  This is sometimes useful for extended
2394 debugging of problems.
2395
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2400
2401   ("ping_daemon", (RErr, []), 92, [],
2402    [InitEmpty, Always, TestRun (
2403       [["ping_daemon"]])],
2404    "ping the guest daemon",
2405    "\
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess.  Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2410
2411   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412    [InitBasicFS, Always, TestOutputTrue (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["cp"; "/file1"; "/file2"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestOutputFalse (
2417       [["write"; "/file1"; "contents of a file"];
2418        ["write"; "/file2"; "contents of another file"];
2419        ["equal"; "/file1"; "/file2"]]);
2420     InitBasicFS, Always, TestLastFail (
2421       [["equal"; "/file1"; "/file2"]])],
2422    "test if two files have equal contents",
2423    "\
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2426
2427 The external L<cmp(1)> program is used for the comparison.");
2428
2429   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430    [InitISOFS, Always, TestOutputList (
2431       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432     InitISOFS, Always, TestOutputList (
2433       [["strings"; "/empty"]], []);
2434     (* Test for RHBZ#579608, absolute symbolic links. *)
2435     InitISOFS, Always, TestRun (
2436       [["strings"; "/abssymlink"]])],
2437    "print the printable strings in a file",
2438    "\
2439 This runs the L<strings(1)> command on a file and returns
2440 the list of printable strings found.");
2441
2442   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2443    [InitISOFS, Always, TestOutputList (
2444       [["strings_e"; "b"; "/known-5"]], []);
2445     InitBasicFS, Always, TestOutputList (
2446       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2447        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2448    "print the printable strings in a file",
2449    "\
2450 This is like the C<guestfs_strings> command, but allows you to
2451 specify the encoding of strings that are looked for in
2452 the source file C<path>.
2453
2454 Allowed encodings are:
2455
2456 =over 4
2457
2458 =item s
2459
2460 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2461 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2462
2463 =item S
2464
2465 Single 8-bit-byte characters.
2466
2467 =item b
2468
2469 16-bit big endian strings such as those encoded in
2470 UTF-16BE or UCS-2BE.
2471
2472 =item l (lower case letter L)
2473
2474 16-bit little endian such as UTF-16LE and UCS-2LE.
2475 This is useful for examining binaries in Windows guests.
2476
2477 =item B
2478
2479 32-bit big endian such as UCS-4BE.
2480
2481 =item L
2482
2483 32-bit little endian such as UCS-4LE.
2484
2485 =back
2486
2487 The returned strings are transcoded to UTF-8.");
2488
2489   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2490    [InitISOFS, Always, TestOutput (
2491       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2492     (* Test for RHBZ#501888c2 regression which caused large hexdump
2493      * commands to segfault.
2494      *)
2495     InitISOFS, Always, TestRun (
2496       [["hexdump"; "/100krandom"]]);
2497     (* Test for RHBZ#579608, absolute symbolic links. *)
2498     InitISOFS, Always, TestRun (
2499       [["hexdump"; "/abssymlink"]])],
2500    "dump a file in hexadecimal",
2501    "\
2502 This runs C<hexdump -C> on the given C<path>.  The result is
2503 the human-readable, canonical hex dump of the file.");
2504
2505   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2506    [InitNone, Always, TestOutput (
2507       [["part_disk"; "/dev/sda"; "mbr"];
2508        ["mkfs"; "ext3"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["write"; "/new"; "test file"];
2511        ["umount"; "/dev/sda1"];
2512        ["zerofree"; "/dev/sda1"];
2513        ["mount_options"; ""; "/dev/sda1"; "/"];
2514        ["cat"; "/new"]], "test file")],
2515    "zero unused inodes and disk blocks on ext2/3 filesystem",
2516    "\
2517 This runs the I<zerofree> program on C<device>.  This program
2518 claims to zero unused inodes and disk blocks on an ext2/3
2519 filesystem, thus making it possible to compress the filesystem
2520 more effectively.
2521
2522 You should B<not> run this program if the filesystem is
2523 mounted.
2524
2525 It is possible that using this program can damage the filesystem
2526 or data on the filesystem.");
2527
2528   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2529    [],
2530    "resize an LVM physical volume",
2531    "\
2532 This resizes (expands or shrinks) an existing LVM physical
2533 volume to match the new size of the underlying device.");
2534
2535   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2536                        Int "cyls"; Int "heads"; Int "sectors";
2537                        String "line"]), 99, [DangerWillRobinson],
2538    [],
2539    "modify a single partition on a block device",
2540    "\
2541 This runs L<sfdisk(8)> option to modify just the single
2542 partition C<n> (note: C<n> counts from 1).
2543
2544 For other parameters, see C<guestfs_sfdisk>.  You should usually
2545 pass C<0> for the cyls/heads/sectors parameters.
2546
2547 See also: C<guestfs_part_add>");
2548
2549   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2550    [],
2551    "display the partition table",
2552    "\
2553 This displays the partition table on C<device>, in the
2554 human-readable output of the L<sfdisk(8)> command.  It is
2555 not intended to be parsed.
2556
2557 See also: C<guestfs_part_list>");
2558
2559   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2560    [],
2561    "display the kernel geometry",
2562    "\
2563 This displays the kernel's idea of the geometry of C<device>.
2564
2565 The result is in human-readable format, and not designed to
2566 be parsed.");
2567
2568   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2569    [],
2570    "display the disk geometry from the partition table",
2571    "\
2572 This displays the disk geometry of C<device> read from the
2573 partition table.  Especially in the case where the underlying
2574 block device has been resized, this can be different from the
2575 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2576
2577 The result is in human-readable format, and not designed to
2578 be parsed.");
2579
2580   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2581    [],
2582    "activate or deactivate all volume groups",
2583    "\
2584 This command activates or (if C<activate> is false) deactivates
2585 all logical volumes in all volume groups.
2586 If activated, then they are made known to the
2587 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2588 then those devices disappear.
2589
2590 This command is the same as running C<vgchange -a y|n>");
2591
2592   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2593    [],
2594    "activate or deactivate some volume groups",
2595    "\
2596 This command activates or (if C<activate> is false) deactivates
2597 all logical volumes in the listed volume groups C<volgroups>.
2598 If activated, then they are made known to the
2599 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2600 then those devices disappear.
2601
2602 This command is the same as running C<vgchange -a y|n volgroups...>
2603
2604 Note that if C<volgroups> is an empty list then B<all> volume groups
2605 are activated or deactivated.");
2606
2607   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2608    [InitNone, Always, TestOutput (
2609       [["part_disk"; "/dev/sda"; "mbr"];
2610        ["pvcreate"; "/dev/sda1"];
2611        ["vgcreate"; "VG"; "/dev/sda1"];
2612        ["lvcreate"; "LV"; "VG"; "10"];
2613        ["mkfs"; "ext2"; "/dev/VG/LV"];
2614        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2615        ["write"; "/new"; "test content"];
2616        ["umount"; "/"];
2617        ["lvresize"; "/dev/VG/LV"; "20"];
2618        ["e2fsck_f"; "/dev/VG/LV"];
2619        ["resize2fs"; "/dev/VG/LV"];
2620        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2621        ["cat"; "/new"]], "test content");
2622     InitNone, Always, TestRun (
2623       (* Make an LV smaller to test RHBZ#587484. *)
2624       [["part_disk"; "/dev/sda"; "mbr"];
2625        ["pvcreate"; "/dev/sda1"];
2626        ["vgcreate"; "VG"; "/dev/sda1"];
2627        ["lvcreate"; "LV"; "VG"; "20"];
2628        ["lvresize"; "/dev/VG/LV"; "10"]])],
2629    "resize an LVM logical volume",
2630    "\
2631 This resizes (expands or shrinks) an existing LVM logical
2632 volume to C<mbytes>.  When reducing, data in the reduced part
2633 is lost.");
2634
2635   ("resize2fs", (RErr, [Device "device"]), 106, [],
2636    [], (* lvresize tests this *)
2637    "resize an ext2/ext3 filesystem",
2638    "\
2639 This resizes an ext2 or ext3 filesystem to match the size of
2640 the underlying device.
2641
2642 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2643 on the C<device> before calling this command.  For unknown reasons
2644 C<resize2fs> sometimes gives an error about this and sometimes not.
2645 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2646 calling this function.");
2647
2648   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2649    [InitBasicFS, Always, TestOutputList (
2650       [["find"; "/"]], ["lost+found"]);
2651     InitBasicFS, Always, TestOutputList (
2652       [["touch"; "/a"];
2653        ["mkdir"; "/b"];
2654        ["touch"; "/b/c"];
2655        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2656     InitBasicFS, Always, TestOutputList (
2657       [["mkdir_p"; "/a/b/c"];
2658        ["touch"; "/a/b/c/d"];
2659        ["find"; "/a/b/"]], ["c"; "c/d"])],
2660    "find all files and directories",
2661    "\
2662 This command lists out all files and directories, recursively,
2663 starting at C<directory>.  It is essentially equivalent to
2664 running the shell command C<find directory -print> but some
2665 post-processing happens on the output, described below.
2666
2667 This returns a list of strings I<without any prefix>.  Thus
2668 if the directory structure was:
2669
2670  /tmp/a
2671  /tmp/b
2672  /tmp/c/d
2673
2674 then the returned list from C<guestfs_find> C</tmp> would be
2675 4 elements:
2676
2677  a
2678  b
2679  c
2680  c/d
2681
2682 If C<directory> is not a directory, then this command returns
2683 an error.
2684
2685 The returned list is sorted.
2686
2687 See also C<guestfs_find0>.");
2688
2689   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2690    [], (* lvresize tests this *)
2691    "check an ext2/ext3 filesystem",
2692    "\
2693 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2694 filesystem checker on C<device>, noninteractively (C<-p>),
2695 even if the filesystem appears to be clean (C<-f>).
2696
2697 This command is only needed because of C<guestfs_resize2fs>
2698 (q.v.).  Normally you should use C<guestfs_fsck>.");
2699
2700   ("sleep", (RErr, [Int "secs"]), 109, [],
2701    [InitNone, Always, TestRun (
2702       [["sleep"; "1"]])],
2703    "sleep for some seconds",
2704    "\
2705 Sleep for C<secs> seconds.");
2706
2707   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2708    [InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ntfs"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2712     InitNone, Always, TestOutputInt (
2713       [["part_disk"; "/dev/sda"; "mbr"];
2714        ["mkfs"; "ext2"; "/dev/sda1"];
2715        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2716    "probe NTFS volume",
2717    "\
2718 This command runs the L<ntfs-3g.probe(8)> command which probes
2719 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2720 be mounted read-write, and some cannot be mounted at all).
2721
2722 C<rw> is a boolean flag.  Set it to true if you want to test
2723 if the volume can be mounted read-write.  Set it to false if
2724 you want to test if the volume can be mounted read-only.
2725
2726 The return value is an integer which C<0> if the operation
2727 would succeed, or some non-zero value documented in the
2728 L<ntfs-3g.probe(8)> manual page.");
2729
2730   ("sh", (RString "output", [String "command"]), 111, [],
2731    [], (* XXX needs tests *)
2732    "run a command via the shell",
2733    "\
2734 This call runs a command from the guest filesystem via the
2735 guest's C</bin/sh>.
2736
2737 This is like C<guestfs_command>, but passes the command to:
2738
2739  /bin/sh -c \"command\"
2740
2741 Depending on the guest's shell, this usually results in
2742 wildcards being expanded, shell expressions being interpolated
2743 and so on.
2744
2745 All the provisos about C<guestfs_command> apply to this call.");
2746
2747   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2748    [], (* XXX needs tests *)
2749    "run a command via the shell returning lines",
2750    "\
2751 This is the same as C<guestfs_sh>, but splits the result
2752 into a list of lines.
2753
2754 See also: C<guestfs_command_lines>");
2755
2756   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2757    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2758     * code in stubs.c, since all valid glob patterns must start with "/".
2759     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2760     *)
2761    [InitBasicFS, Always, TestOutputList (
2762       [["mkdir_p"; "/a/b/c"];
2763        ["touch"; "/a/b/c/d"];
2764        ["touch"; "/a/b/c/e"];
2765        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2766     InitBasicFS, Always, TestOutputList (
2767       [["mkdir_p"; "/a/b/c"];
2768        ["touch"; "/a/b/c/d"];
2769        ["touch"; "/a/b/c/e"];
2770        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2771     InitBasicFS, Always, TestOutputList (
2772       [["mkdir_p"; "/a/b/c"];
2773        ["touch"; "/a/b/c/d"];
2774        ["touch"; "/a/b/c/e"];
2775        ["glob_expand"; "/a/*/x/*"]], [])],
2776    "expand a wildcard path",
2777    "\
2778 This command searches for all the pathnames matching
2779 C<pattern> according to the wildcard expansion rules
2780 used by the shell.
2781
2782 If no paths match, then this returns an empty list
2783 (note: not an error).
2784
2785 It is just a wrapper around the C L<glob(3)> function
2786 with flags C<GLOB_MARK|GLOB_BRACE>.
2787 See that manual page for more details.");
2788
2789   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2790    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2791       [["scrub_device"; "/dev/sdc"]])],
2792    "scrub (securely wipe) a device",
2793    "\
2794 This command writes patterns over C<device> to make data retrieval
2795 more difficult.
2796
2797 It is an interface to the L<scrub(1)> program.  See that
2798 manual page for more details.");
2799
2800   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2801    [InitBasicFS, Always, TestRun (
2802       [["write"; "/file"; "content"];
2803        ["scrub_file"; "/file"]])],
2804    "scrub (securely wipe) a file",
2805    "\
2806 This command writes patterns over a file to make data retrieval
2807 more difficult.
2808
2809 The file is I<removed> after scrubbing.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2815    [], (* XXX needs testing *)
2816    "scrub (securely wipe) free space",
2817    "\
2818 This command creates the directory C<dir> and then fills it
2819 with files until the filesystem is full, and scrubs the files
2820 as for C<guestfs_scrub_file>, and deletes them.
2821 The intention is to scrub any free space on the partition
2822 containing C<dir>.
2823
2824 It is an interface to the L<scrub(1)> program.  See that
2825 manual page for more details.");
2826
2827   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2828    [InitBasicFS, Always, TestRun (
2829       [["mkdir"; "/tmp"];
2830        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2831    "create a temporary directory",
2832    "\
2833 This command creates a temporary directory.  The
2834 C<template> parameter should be a full pathname for the
2835 temporary directory name with the final six characters being
2836 \"XXXXXX\".
2837
2838 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2839 the second one being suitable for Windows filesystems.
2840
2841 The name of the temporary directory that was created
2842 is returned.
2843
2844 The temporary directory is created with mode 0700
2845 and is owned by root.
2846
2847 The caller is responsible for deleting the temporary
2848 directory and its contents after use.
2849
2850 See also: L<mkdtemp(3)>");
2851
2852   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_l"; "/10klines"]], 10000);
2855     (* Test for RHBZ#579608, absolute symbolic links. *)
2856     InitISOFS, Always, TestOutputInt (
2857       [["wc_l"; "/abssymlink"]], 10000)],
2858    "count lines in a file",
2859    "\
2860 This command counts the lines in a file, using the
2861 C<wc -l> external command.");
2862
2863   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2864    [InitISOFS, Always, TestOutputInt (
2865       [["wc_w"; "/10klines"]], 10000)],
2866    "count words in a file",
2867    "\
2868 This command counts the words in a file, using the
2869 C<wc -w> external command.");
2870
2871   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2872    [InitISOFS, Always, TestOutputInt (
2873       [["wc_c"; "/100kallspaces"]], 102400)],
2874    "count characters in a file",
2875    "\
2876 This command counts the characters in a file, using the
2877 C<wc -c> external command.");
2878
2879   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2880    [InitISOFS, Always, TestOutputList (
2881       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2882     (* Test for RHBZ#579608, absolute symbolic links. *)
2883     InitISOFS, Always, TestOutputList (
2884       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2885    "return first 10 lines of a file",
2886    "\
2887 This command returns up to the first 10 lines of a file as
2888 a list of strings.");
2889
2890   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2891    [InitISOFS, Always, TestOutputList (
2892       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2893     InitISOFS, Always, TestOutputList (
2894       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2895     InitISOFS, Always, TestOutputList (
2896       [["head_n"; "0"; "/10klines"]], [])],
2897    "return first N lines of a file",
2898    "\
2899 If the parameter C<nrlines> is a positive number, this returns the first
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>, excluding the last C<nrlines> lines.
2904
2905 If the parameter C<nrlines> is zero, this returns an empty list.");
2906
2907   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2908    [InitISOFS, Always, TestOutputList (
2909       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2910    "return last 10 lines of a file",
2911    "\
2912 This command returns up to the last 10 lines of a file as
2913 a list of strings.");
2914
2915   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2916    [InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2918     InitISOFS, Always, TestOutputList (
2919       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2920     InitISOFS, Always, TestOutputList (
2921       [["tail_n"; "0"; "/10klines"]], [])],
2922    "return last N lines of a file",
2923    "\
2924 If the parameter C<nrlines> is a positive number, this returns the last
2925 C<nrlines> lines of the file C<path>.
2926
2927 If the parameter C<nrlines> is a negative number, this returns lines
2928 from the file C<path>, starting with the C<-nrlines>th line.
2929
2930 If the parameter C<nrlines> is zero, this returns an empty list.");
2931
2932   ("df", (RString "output", []), 125, [],
2933    [], (* XXX Tricky to test because it depends on the exact format
2934         * of the 'df' command and other imponderables.
2935         *)
2936    "report file system disk space usage",
2937    "\
2938 This command runs the C<df> command to report disk space used.
2939
2940 This command is mostly useful for interactive sessions.  It
2941 is I<not> intended that you try to parse the output string.
2942 Use C<statvfs> from programs.");
2943
2944   ("df_h", (RString "output", []), 126, [],
2945    [], (* XXX Tricky to test because it depends on the exact format
2946         * of the 'df' command and other imponderables.
2947         *)
2948    "report file system disk space usage (human readable)",
2949    "\
2950 This command runs the C<df -h> command to report disk space used
2951 in human-readable format.
2952
2953 This command is mostly useful for interactive sessions.  It
2954 is I<not> intended that you try to parse the output string.
2955 Use C<statvfs> from programs.");
2956
2957   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2958    [InitISOFS, Always, TestOutputInt (
2959       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2960    "estimate file space usage",
2961    "\
2962 This command runs the C<du -s> command to estimate file space
2963 usage for C<path>.
2964
2965 C<path> can be a file or a directory.  If C<path> is a directory
2966 then the estimate includes the contents of the directory and all
2967 subdirectories (recursively).
2968
2969 The result is the estimated size in I<kilobytes>
2970 (ie. units of 1024 bytes).");
2971
2972   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2973    [InitISOFS, Always, TestOutputList (
2974       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2975    "list files in an initrd",
2976    "\
2977 This command lists out files contained in an initrd.
2978
2979 The files are listed without any initial C</> character.  The
2980 files are listed in the order they appear (not necessarily
2981 alphabetical).  Directory names are listed as separate items.
2982
2983 Old Linux kernels (2.4 and earlier) used a compressed ext2
2984 filesystem as initrd.  We I<only> support the newer initramfs
2985 format (compressed cpio files).");
2986
2987   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2988    [],
2989    "mount a file using the loop device",
2990    "\
2991 This command lets you mount C<file> (a filesystem image
2992 in a file) on a mount point.  It is entirely equivalent to
2993 the command C<mount -o loop file mountpoint>.");
2994
2995   ("mkswap", (RErr, [Device "device"]), 130, [],
2996    [InitEmpty, Always, TestRun (
2997       [["part_disk"; "/dev/sda"; "mbr"];
2998        ["mkswap"; "/dev/sda1"]])],
2999    "create a swap partition",
3000    "\
3001 Create a swap partition on C<device>.");
3002
3003   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3004    [InitEmpty, Always, TestRun (
3005       [["part_disk"; "/dev/sda"; "mbr"];
3006        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3007    "create a swap partition with a label",
3008    "\
3009 Create a swap partition on C<device> with label C<label>.
3010
3011 Note that you cannot attach a swap label to a block device
3012 (eg. C</dev/sda>), just to a partition.  This appears to be
3013 a limitation of the kernel or swap tools.");
3014
3015   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3016    (let uuid = uuidgen () in
3017     [InitEmpty, Always, TestRun (
3018        [["part_disk"; "/dev/sda"; "mbr"];
3019         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3020    "create a swap partition with an explicit UUID",
3021    "\
3022 Create a swap partition on C<device> with UUID C<uuid>.");
3023
3024   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3025    [InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3027        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3028        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3029     InitBasicFS, Always, TestOutputStruct (
3030       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3031        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3032    "make block, character or FIFO devices",
3033    "\
3034 This call creates block or character special devices, or
3035 named pipes (FIFOs).
3036
3037 The C<mode> parameter should be the mode, using the standard
3038 constants.  C<devmajor> and C<devminor> are the
3039 device major and minor numbers, only used when creating block
3040 and character special devices.
3041
3042 Note that, just like L<mknod(2)>, the mode must be bitwise
3043 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3044 just creates a regular file).  These constants are
3045 available in the standard Linux header files, or you can use
3046 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3047 which are wrappers around this command which bitwise OR
3048 in the appropriate constant for you.
3049
3050 The mode actually set is affected by the umask.");
3051
3052   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3053    [InitBasicFS, Always, TestOutputStruct (
3054       [["mkfifo"; "0o777"; "/node"];
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3056    "make FIFO (named pipe)",
3057    "\
3058 This call creates a FIFO (named pipe) called C<path> with
3059 mode C<mode>.  It is just a convenient wrapper around
3060 C<guestfs_mknod>.
3061
3062 The mode actually set is affected by the umask.");
3063
3064   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3065    [InitBasicFS, Always, TestOutputStruct (
3066       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3067        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3068    "make block device node",
3069    "\
3070 This call creates a block device node called C<path> with
3071 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3072 It is just a convenient wrapper around C<guestfs_mknod>.
3073
3074 The mode actually set is affected by the umask.");
3075
3076   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3077    [InitBasicFS, Always, TestOutputStruct (
3078       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3079        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3080    "make char device node",
3081    "\
3082 This call creates a char device node called C<path> with
3083 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3084 It is just a convenient wrapper around C<guestfs_mknod>.
3085
3086 The mode actually set is affected by the umask.");
3087
3088   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3089    [InitEmpty, Always, TestOutputInt (
3090       [["umask"; "0o22"]], 0o22)],
3091    "set file mode creation mask (umask)",
3092    "\
3093 This function sets the mask used for creating new files and
3094 device nodes to C<mask & 0777>.
3095
3096 Typical umask values would be C<022> which creates new files
3097 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3098 C<002> which creates new files with permissions like
3099 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3100
3101 The default umask is C<022>.  This is important because it
3102 means that directories and device nodes will be created with
3103 C<0644> or C<0755> mode even if you specify C<0777>.
3104
3105 See also C<guestfs_get_umask>,
3106 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3107
3108 This call returns the previous umask.");
3109
3110   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3111    [],
3112    "read directories entries",
3113    "\
3114 This returns the list of directory entries in directory C<dir>.
3115
3116 All entries in the directory are returned, including C<.> and
3117 C<..>.  The entries are I<not> sorted, but returned in the same
3118 order as the underlying filesystem.
3119
3120 Also this call returns basic file type information about each
3121 file.  The C<ftyp> field will contain one of the following characters:
3122
3123 =over 4
3124
3125 =item 'b'
3126
3127 Block special
3128
3129 =item 'c'
3130
3131 Char special
3132
3133 =item 'd'
3134
3135 Directory
3136
3137 =item 'f'
3138
3139 FIFO (named pipe)
3140
3141 =item 'l'
3142
3143 Symbolic link
3144
3145 =item 'r'
3146
3147 Regular file
3148
3149 =item 's'
3150
3151 Socket
3152
3153 =item 'u'
3154
3155 Unknown file type
3156
3157 =item '?'
3158
3159 The L<readdir(3)> call returned a C<d_type> field with an
3160 unexpected value
3161
3162 =back
3163
3164 This function is primarily intended for use by programs.  To
3165 get a simple list of names, use C<guestfs_ls>.  To get a printable
3166 directory for human consumption, use C<guestfs_ll>.");
3167
3168   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3169    [],
3170    "create partitions on a block device",
3171    "\
3172 This is a simplified interface to the C<guestfs_sfdisk>
3173 command, where partition sizes are specified in megabytes
3174 only (rounded to the nearest cylinder) and you don't need
3175 to specify the cyls, heads and sectors parameters which
3176 were rarely if ever used anyway.
3177
3178 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3179 and C<guestfs_part_disk>");
3180
3181   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3182    [],
3183    "determine file type inside a compressed file",
3184    "\
3185 This command runs C<file> after first decompressing C<path>
3186 using C<method>.
3187
3188 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3189
3190 Since 1.0.63, use C<guestfs_file> instead which can now
3191 process compressed files.");
3192
3193   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3194    [],
3195    "list extended attributes of a file or directory",
3196    "\
3197 This call lists the extended attributes of the file or directory
3198 C<path>.
3199
3200 At the system call level, this is a combination of the
3201 L<listxattr(2)> and L<getxattr(2)> calls.
3202
3203 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3204
3205   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3206    [],
3207    "list extended attributes of a file or directory",
3208    "\
3209 This is the same as C<guestfs_getxattrs>, but if C<path>
3210 is a symbolic link, then it returns the extended attributes
3211 of the link itself.");
3212
3213   ("setxattr", (RErr, [String "xattr";
3214                        String "val"; Int "vallen"; (* will be BufferIn *)
3215                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3216    [],
3217    "set extended attribute of a file or directory",
3218    "\
3219 This call sets the extended attribute named C<xattr>
3220 of the file C<path> to the value C<val> (of length C<vallen>).
3221 The value is arbitrary 8 bit data.
3222
3223 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3224
3225   ("lsetxattr", (RErr, [String "xattr";
3226                         String "val"; Int "vallen"; (* will be BufferIn *)
3227                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3228    [],
3229    "set extended attribute of a file or directory",
3230    "\
3231 This is the same as C<guestfs_setxattr>, but if C<path>
3232 is a symbolic link, then it sets an extended attribute
3233 of the link itself.");
3234
3235   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3236    [],
3237    "remove extended attribute of a file or directory",
3238    "\
3239 This call removes the extended attribute named C<xattr>
3240 of the file C<path>.
3241
3242 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3243
3244   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3245    [],
3246    "remove extended attribute of a file or directory",
3247    "\
3248 This is the same as C<guestfs_removexattr>, but if C<path>
3249 is a symbolic link, then it removes an extended attribute
3250 of the link itself.");
3251
3252   ("mountpoints", (RHashtable "mps", []), 147, [],
3253    [],
3254    "show mountpoints",
3255    "\
3256 This call is similar to C<guestfs_mounts>.  That call returns
3257 a list of devices.  This one returns a hash table (map) of
3258 device name to directory where the device is mounted.");
3259
3260   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3261    (* This is a special case: while you would expect a parameter
3262     * of type "Pathname", that doesn't work, because it implies
3263     * NEED_ROOT in the generated calling code in stubs.c, and
3264     * this function cannot use NEED_ROOT.
3265     *)
3266    [],
3267    "create a mountpoint",
3268    "\
3269 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3270 specialized calls that can be used to create extra mountpoints
3271 before mounting the first filesystem.
3272
3273 These calls are I<only> necessary in some very limited circumstances,
3274 mainly the case where you want to mount a mix of unrelated and/or
3275 read-only filesystems together.
3276
3277 For example, live CDs often contain a \"Russian doll\" nest of
3278 filesystems, an ISO outer layer, with a squashfs image inside, with
3279 an ext2/3 image inside that.  You can unpack this as follows
3280 in guestfish:
3281
3282  add-ro Fedora-11-i686-Live.iso
3283  run
3284  mkmountpoint /cd
3285  mkmountpoint /squash
3286  mkmountpoint /ext3
3287  mount /dev/sda /cd
3288  mount-loop /cd/LiveOS/squashfs.img /squash
3289  mount-loop /squash/LiveOS/ext3fs.img /ext3
3290
3291 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3292
3293   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3294    [],
3295    "remove a mountpoint",
3296    "\
3297 This calls removes a mountpoint that was previously created
3298 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3299 for full details.");
3300
3301   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputBuffer (
3303       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3304     (* Test various near large, large and too large files (RHBZ#589039). *)
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3312        ["read_file"; "/a"]]);
3313     InitBasicFS, Always, TestLastFail (
3314       [["touch"; "/a"];
3315        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3316        ["read_file"; "/a"]])],
3317    "read a file",
3318    "\
3319 This calls returns the contents of the file C<path> as a
3320 buffer.
3321
3322 Unlike C<guestfs_cat>, this function can correctly
3323 handle files that contain embedded ASCII NUL characters.
3324 However unlike C<guestfs_download>, this function is limited
3325 in the total size of file that can be handled.");
3326
3327   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3328    [InitISOFS, Always, TestOutputList (
3329       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3330     InitISOFS, Always, TestOutputList (
3331       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3332     (* Test for RHBZ#579608, absolute symbolic links. *)
3333     InitISOFS, Always, TestOutputList (
3334       [["grep"; "nomatch"; "/abssymlink"]], [])],
3335    "return lines matching a pattern",
3336    "\
3337 This calls the external C<grep> program and returns the
3338 matching lines.");
3339
3340   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3341    [InitISOFS, Always, TestOutputList (
3342       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3343    "return lines matching a pattern",
3344    "\
3345 This calls the external C<egrep> program and returns the
3346 matching lines.");
3347
3348   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3351    "return lines matching a pattern",
3352    "\
3353 This calls the external C<fgrep> program and returns the
3354 matching lines.");
3355
3356   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3357    [InitISOFS, Always, TestOutputList (
3358       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<grep -i> program and returns the
3362 matching lines.");
3363
3364   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3365    [InitISOFS, Always, TestOutputList (
3366       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3367    "return lines matching a pattern",
3368    "\
3369 This calls the external C<egrep -i> program and returns the
3370 matching lines.");
3371
3372   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3373    [InitISOFS, Always, TestOutputList (
3374       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<fgrep -i> program and returns the
3378 matching lines.");
3379
3380   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<zgrep> program and returns the
3386 matching lines.");
3387
3388   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<zegrep> program and returns the
3394 matching lines.");
3395
3396   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<zfgrep> program and returns the
3402 matching lines.");
3403
3404   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<zgrep -i> program and returns the
3410 matching lines.");
3411
3412   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3413    [InitISOFS, Always, TestOutputList (
3414       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3415    "return lines matching a pattern",
3416    "\
3417 This calls the external C<zegrep -i> program and returns the
3418 matching lines.");
3419
3420   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3421    [InitISOFS, Always, TestOutputList (
3422       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3423    "return lines matching a pattern",
3424    "\
3425 This calls the external C<zfgrep -i> program and returns the
3426 matching lines.");
3427
3428   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3429    [InitISOFS, Always, TestOutput (
3430       [["realpath"; "/../directory"]], "/directory")],
3431    "canonicalized absolute pathname",
3432    "\
3433 Return the canonicalized absolute pathname of C<path>.  The
3434 returned path has no C<.>, C<..> or symbolic link path elements.");
3435
3436   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3437    [InitBasicFS, Always, TestOutputStruct (
3438       [["touch"; "/a"];
3439        ["ln"; "/a"; "/b"];
3440        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3441    "create a hard link",
3442    "\
3443 This command creates a hard link using the C<ln> command.");
3444
3445   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3446    [InitBasicFS, Always, TestOutputStruct (
3447       [["touch"; "/a"];
3448        ["touch"; "/b"];
3449        ["ln_f"; "/a"; "/b"];
3450        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3451    "create a hard link",
3452    "\
3453 This command creates a hard link using the C<ln -f> command.
3454 The C<-f> option removes the link (C<linkname>) if it exists already.");
3455
3456   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3457    [InitBasicFS, Always, TestOutputStruct (
3458       [["touch"; "/a"];
3459        ["ln_s"; "a"; "/b"];
3460        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3461    "create a symbolic link",
3462    "\
3463 This command creates a symbolic link using the C<ln -s> command.");
3464
3465   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3466    [InitBasicFS, Always, TestOutput (
3467       [["mkdir_p"; "/a/b"];
3468        ["touch"; "/a/b/c"];
3469        ["ln_sf"; "../d"; "/a/b/c"];
3470        ["readlink"; "/a/b/c"]], "../d")],
3471    "create a symbolic link",
3472    "\
3473 This command creates a symbolic link using the C<ln -sf> command,
3474 The C<-f> option removes the link (C<linkname>) if it exists already.");
3475
3476   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3477    [] (* XXX tested above *),
3478    "read the target of a symbolic link",
3479    "\
3480 This command reads the target of a symbolic link.");
3481
3482   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3483    [InitBasicFS, Always, TestOutputStruct (
3484       [["fallocate"; "/a"; "1000000"];
3485        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3486    "preallocate a file in the guest filesystem",
3487    "\
3488 This command preallocates a file (containing zero bytes) named
3489 C<path> of size C<len> bytes.  If the file exists already, it
3490 is overwritten.
3491
3492 Do not confuse this with the guestfish-specific
3493 C<alloc> command which allocates a file in the host and
3494 attaches it as a device.");
3495
3496   ("swapon_device", (RErr, [Device "device"]), 170, [],
3497    [InitPartition, Always, TestRun (
3498       [["mkswap"; "/dev/sda1"];
3499        ["swapon_device"; "/dev/sda1"];
3500        ["swapoff_device"; "/dev/sda1"]])],
3501    "enable swap on device",
3502    "\
3503 This command enables the libguestfs appliance to use the
3504 swap device or partition named C<device>.  The increased
3505 memory is made available for all commands, for example
3506 those run using C<guestfs_command> or C<guestfs_sh>.
3507
3508 Note that you should not swap to existing guest swap
3509 partitions unless you know what you are doing.  They may
3510 contain hibernation information, or other information that
3511 the guest doesn't want you to trash.  You also risk leaking
3512 information about the host to the guest this way.  Instead,
3513 attach a new host device to the guest and swap on that.");
3514
3515   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3516    [], (* XXX tested by swapon_device *)
3517    "disable swap on device",
3518    "\
3519 This command disables the libguestfs appliance swap
3520 device or partition named C<device>.
3521 See C<guestfs_swapon_device>.");
3522
3523   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3524    [InitBasicFS, Always, TestRun (
3525       [["fallocate"; "/swap"; "8388608"];
3526        ["mkswap_file"; "/swap"];
3527        ["swapon_file"; "/swap"];
3528        ["swapoff_file"; "/swap"]])],
3529    "enable swap on file",
3530    "\
3531 This command enables swap to a file.
3532 See C<guestfs_swapon_device> for other notes.");
3533
3534   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3535    [], (* XXX tested by swapon_file *)
3536    "disable swap on file",
3537    "\
3538 This command disables the libguestfs appliance swap on file.");
3539
3540   ("swapon_label", (RErr, [String "label"]), 174, [],
3541    [InitEmpty, Always, TestRun (
3542       [["part_disk"; "/dev/sdb"; "mbr"];
3543        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3544        ["swapon_label"; "swapit"];
3545        ["swapoff_label"; "swapit"];
3546        ["zero"; "/dev/sdb"];
3547        ["blockdev_rereadpt"; "/dev/sdb"]])],
3548    "enable swap on labeled swap partition",
3549    "\
3550 This command enables swap to a labeled swap partition.
3551 See C<guestfs_swapon_device> for other notes.");
3552
3553   ("swapoff_label", (RErr, [String "label"]), 175, [],
3554    [], (* XXX tested by swapon_label *)
3555    "disable swap on labeled swap partition",
3556    "\
3557 This command disables the libguestfs appliance swap on
3558 labeled swap partition.");
3559
3560   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3561    (let uuid = uuidgen () in
3562     [InitEmpty, Always, TestRun (
3563        [["mkswap_U"; uuid; "/dev/sdb"];
3564         ["swapon_uuid"; uuid];
3565         ["swapoff_uuid"; uuid]])]),
3566    "enable swap on swap partition by UUID",
3567    "\
3568 This command enables swap to a swap partition with the given UUID.
3569 See C<guestfs_swapon_device> for other notes.");
3570
3571   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3572    [], (* XXX tested by swapon_uuid *)
3573    "disable swap on swap partition by UUID",
3574    "\
3575 This command disables the libguestfs appliance swap partition
3576 with the given UUID.");
3577
3578   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3579    [InitBasicFS, Always, TestRun (
3580       [["fallocate"; "/swap"; "8388608"];
3581        ["mkswap_file"; "/swap"]])],
3582    "create a swap file",
3583    "\
3584 Create a swap file.
3585
3586 This command just writes a swap file signature to an existing
3587 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3588
3589   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3590    [InitISOFS, Always, TestRun (
3591       [["inotify_init"; "0"]])],
3592    "create an inotify handle",
3593    "\
3594 This command creates a new inotify handle.
3595 The inotify subsystem can be used to notify events which happen to
3596 objects in the guest filesystem.
3597
3598 C<maxevents> is the maximum number of events which will be
3599 queued up between calls to C<guestfs_inotify_read> or
3600 C<guestfs_inotify_files>.
3601 If this is passed as C<0>, then the kernel (or previously set)
3602 default is used.  For Linux 2.6.29 the default was 16384 events.
3603 Beyond this limit, the kernel throws away events, but records
3604 the fact that it threw them away by setting a flag
3605 C<IN_Q_OVERFLOW> in the returned structure list (see
3606 C<guestfs_inotify_read>).
3607
3608 Before any events are generated, you have to add some
3609 watches to the internal watch list.  See:
3610 C<guestfs_inotify_add_watch>,
3611 C<guestfs_inotify_rm_watch> and
3612 C<guestfs_inotify_watch_all>.
3613
3614 Queued up events should be read periodically by calling
3615 C<guestfs_inotify_read>
3616 (or C<guestfs_inotify_files> which is just a helpful
3617 wrapper around C<guestfs_inotify_read>).  If you don't
3618 read the events out often enough then you risk the internal
3619 queue overflowing.
3620
3621 The handle should be closed after use by calling
3622 C<guestfs_inotify_close>.  This also removes any
3623 watches automatically.
3624
3625 See also L<inotify(7)> for an overview of the inotify interface
3626 as exposed by the Linux kernel, which is roughly what we expose
3627 via libguestfs.  Note that there is one global inotify handle
3628 per libguestfs instance.");
3629
3630   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3631    [InitBasicFS, Always, TestOutputList (
3632       [["inotify_init"; "0"];
3633        ["inotify_add_watch"; "/"; "1073741823"];
3634        ["touch"; "/a"];
3635        ["touch"; "/b"];
3636        ["inotify_files"]], ["a"; "b"])],
3637    "add an inotify watch",
3638    "\
3639 Watch C<path> for the events listed in C<mask>.
3640
3641 Note that if C<path> is a directory then events within that
3642 directory are watched, but this does I<not> happen recursively
3643 (in subdirectories).
3644
3645 Note for non-C or non-Linux callers: the inotify events are
3646 defined by the Linux kernel ABI and are listed in
3647 C</usr/include/sys/inotify.h>.");
3648
3649   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3650    [],
3651    "remove an inotify watch",
3652    "\
3653 Remove a previously defined inotify watch.
3654 See C<guestfs_inotify_add_watch>.");
3655
3656   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3657    [],
3658    "return list of inotify events",
3659    "\
3660 Return the complete queue of events that have happened
3661 since the previous read call.
3662
3663 If no events have happened, this returns an empty list.
3664
3665 I<Note>: In order to make sure that all events have been
3666 read, you must call this function repeatedly until it
3667 returns an empty list.  The reason is that the call will
3668 read events up to the maximum appliance-to-host message
3669 size and leave remaining events in the queue.");
3670
3671   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3672    [],
3673    "return list of watched files that had events",
3674    "\
3675 This function is a helpful wrapper around C<guestfs_inotify_read>
3676 which just returns a list of pathnames of objects that were
3677 touched.  The returned pathnames are sorted and deduplicated.");
3678
3679   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3680    [],
3681    "close the inotify handle",
3682    "\
3683 This closes the inotify handle which was previously
3684 opened by inotify_init.  It removes all watches, throws
3685 away any pending events, and deallocates all resources.");
3686
3687   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3688    [],
3689    "set SELinux security context",
3690    "\
3691 This sets the SELinux security context of the daemon
3692 to the string C<context>.
3693
3694 See the documentation about SELINUX in L<guestfs(3)>.");
3695
3696   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3697    [],
3698    "get SELinux security context",
3699    "\
3700 This gets the SELinux security context of the daemon.
3701
3702 See the documentation about SELINUX in L<guestfs(3)>,
3703 and C<guestfs_setcon>");
3704
3705   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["part_disk"; "/dev/sda"; "mbr"];
3708        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3709        ["mount_options"; ""; "/dev/sda1"; "/"];
3710        ["write"; "/new"; "new file contents"];
3711        ["cat"; "/new"]], "new file contents")],
3712    "make a filesystem with block size",
3713    "\
3714 This call is similar to C<guestfs_mkfs>, but it allows you to
3715 control the block size of the resulting filesystem.  Supported
3716 block sizes depend on the filesystem type, but typically they
3717 are C<1024>, C<2048> or C<4096> only.");
3718
3719   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3720    [InitEmpty, Always, TestOutput (
3721       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3722        ["mke2journal"; "4096"; "/dev/sda1"];
3723        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3724        ["mount_options"; ""; "/dev/sda2"; "/"];
3725        ["write"; "/new"; "new file contents"];
3726        ["cat"; "/new"]], "new file contents")],
3727    "make ext2/3/4 external journal",
3728    "\
3729 This creates an ext2 external journal on C<device>.  It is equivalent
3730 to the command:
3731
3732  mke2fs -O journal_dev -b blocksize device");
3733
3734   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3735    [InitEmpty, Always, TestOutput (
3736       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3738        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3739        ["mount_options"; ""; "/dev/sda2"; "/"];
3740        ["write"; "/new"; "new file contents"];
3741        ["cat"; "/new"]], "new file contents")],
3742    "make ext2/3/4 external journal with label",
3743    "\
3744 This creates an ext2 external journal on C<device> with label C<label>.");
3745
3746   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3747    (let uuid = uuidgen () in
3748     [InitEmpty, Always, TestOutput (
3749        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3750         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3751         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3752         ["mount_options"; ""; "/dev/sda2"; "/"];
3753         ["write"; "/new"; "new file contents"];
3754         ["cat"; "/new"]], "new file contents")]),
3755    "make ext2/3/4 external journal with UUID",
3756    "\
3757 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3758
3759   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3760    [],
3761    "make ext2/3/4 filesystem with external journal",
3762    "\
3763 This creates an ext2/3/4 filesystem on C<device> with
3764 an external journal on C<journal>.  It is equivalent
3765 to the command:
3766
3767  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3768
3769 See also C<guestfs_mke2journal>.");
3770
3771   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3772    [],
3773    "make ext2/3/4 filesystem with external journal",
3774    "\
3775 This creates an ext2/3/4 filesystem on C<device> with
3776 an external journal on the journal labeled C<label>.
3777
3778 See also C<guestfs_mke2journal_L>.");
3779
3780   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3781    [],
3782    "make ext2/3/4 filesystem with external journal",
3783    "\
3784 This creates an ext2/3/4 filesystem on C<device> with
3785 an external journal on the journal with UUID C<uuid>.
3786
3787 See also C<guestfs_mke2journal_U>.");
3788
3789   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3790    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3791    "load a kernel module",
3792    "\
3793 This loads a kernel module in the appliance.
3794
3795 The kernel module must have been whitelisted when libguestfs
3796 was built (see C<appliance/kmod.whitelist.in> in the source).");
3797
3798   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3799    [InitNone, Always, TestOutput (
3800       [["echo_daemon"; "This is a test"]], "This is a test"
3801     )],
3802    "echo arguments back to the client",
3803    "\
3804 This command concatenates the list of C<words> passed with single spaces
3805 between them and returns the resulting string.
3806
3807 You can use this command to test the connection through to the daemon.
3808
3809 See also C<guestfs_ping_daemon>.");
3810
3811   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3812    [], (* There is a regression test for this. *)
3813    "find all files and directories, returning NUL-separated list",
3814    "\
3815 This command lists out all files and directories, recursively,
3816 starting at C<directory>, placing the resulting list in the
3817 external file called C<files>.
3818
3819 This command works the same way as C<guestfs_find> with the
3820 following exceptions:
3821
3822 =over 4
3823
3824 =item *
3825
3826 The resulting list is written to an external file.
3827
3828 =item *
3829
3830 Items (filenames) in the result are separated
3831 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3832
3833 =item *
3834
3835 This command is not limited in the number of names that it
3836 can return.
3837
3838 =item *
3839
3840 The result list is not sorted.
3841
3842 =back");
3843
3844   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3845    [InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3847     InitISOFS, Always, TestOutput (
3848       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3849     InitISOFS, Always, TestOutput (
3850       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3851     InitISOFS, Always, TestLastFail (
3852       [["case_sensitive_path"; "/Known-1/"]]);
3853     InitBasicFS, Always, TestOutput (
3854       [["mkdir"; "/a"];
3855        ["mkdir"; "/a/bbb"];
3856        ["touch"; "/a/bbb/c"];
3857        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3858     InitBasicFS, Always, TestOutput (
3859       [["mkdir"; "/a"];
3860        ["mkdir"; "/a/bbb"];
3861        ["touch"; "/a/bbb/c"];
3862        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3863     InitBasicFS, Always, TestLastFail (
3864       [["mkdir"; "/a"];
3865        ["mkdir"; "/a/bbb"];
3866        ["touch"; "/a/bbb/c"];
3867        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3868    "return true path on case-insensitive filesystem",
3869    "\
3870 This can be used to resolve case insensitive paths on
3871 a filesystem which is case sensitive.  The use case is
3872 to resolve paths which you have read from Windows configuration
3873 files or the Windows Registry, to the true path.
3874
3875 The command handles a peculiarity of the Linux ntfs-3g
3876 filesystem driver (and probably others), which is that although
3877 the underlying filesystem is case-insensitive, the driver
3878 exports the filesystem to Linux as case-sensitive.
3879
3880 One consequence of this is that special directories such
3881 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3882 (or other things) depending on the precise details of how
3883 they were created.  In Windows itself this would not be
3884 a problem.
3885
3886 Bug or feature?  You decide:
3887 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3888
3889 This function resolves the true case of each element in the
3890 path and returns the case-sensitive path.
3891
3892 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3893 might return C<\"/WINDOWS/system32\"> (the exact return value
3894 would depend on details of how the directories were originally
3895 created under Windows).
3896
3897 I<Note>:
3898 This function does not handle drive names, backslashes etc.
3899
3900 See also C<guestfs_realpath>.");
3901
3902   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3903    [InitBasicFS, Always, TestOutput (
3904       [["vfs_type"; "/dev/sda1"]], "ext2")],
3905    "get the Linux VFS type corresponding to a mounted device",
3906    "\
3907 This command gets the block device type corresponding to
3908 a mounted device called C<device>.
3909
3910 Usually the result is the name of the Linux VFS module that
3911 is used to mount this device (probably determined automatically
3912 if you used the C<guestfs_mount> call).");
3913
3914   ("truncate", (RErr, [Pathname "path"]), 199, [],
3915    [InitBasicFS, Always, TestOutputStruct (
3916       [["write"; "/test"; "some stuff so size is not zero"];
3917        ["truncate"; "/test"];
3918        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3919    "truncate a file to zero size",
3920    "\
3921 This command truncates C<path> to a zero-length file.  The
3922 file must exist already.");
3923
3924   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3925    [InitBasicFS, Always, TestOutputStruct (
3926       [["touch"; "/test"];
3927        ["truncate_size"; "/test"; "1000"];
3928        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3929    "truncate a file to a particular size",
3930    "\
3931 This command truncates C<path> to size C<size> bytes.  The file
3932 must exist already.
3933
3934 If the current file size is less than C<size> then
3935 the file is extended to the required size with zero bytes.
3936 This creates a sparse file (ie. disk blocks are not allocated
3937 for the file until you write to it).  To create a non-sparse
3938 file of zeroes, use C<guestfs_fallocate64> instead.");
3939
3940   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3941    [InitBasicFS, Always, TestOutputStruct (
3942       [["touch"; "/test"];
3943        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3944        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3945    "set timestamp of a file with nanosecond precision",
3946    "\
3947 This command sets the timestamps of a file with nanosecond
3948 precision.
3949
3950 C<atsecs, atnsecs> are the last access time (atime) in secs and
3951 nanoseconds from the epoch.
3952
3953 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3954 secs and nanoseconds from the epoch.
3955
3956 If the C<*nsecs> field contains the special value C<-1> then
3957 the corresponding timestamp is set to the current time.  (The
3958 C<*secs> field is ignored in this case).
3959
3960 If the C<*nsecs> field contains the special value C<-2> then
3961 the corresponding timestamp is left unchanged.  (The
3962 C<*secs> field is ignored in this case).");
3963
3964   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3965    [InitBasicFS, Always, TestOutputStruct (
3966       [["mkdir_mode"; "/test"; "0o111"];
3967        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3968    "create a directory with a particular mode",
3969    "\
3970 This command creates a directory, setting the initial permissions
3971 of the directory to C<mode>.
3972
3973 For common Linux filesystems, the actual mode which is set will
3974 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3975 interpret the mode in other ways.
3976
3977 See also C<guestfs_mkdir>, C<guestfs_umask>");
3978
3979   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3980    [], (* XXX *)
3981    "change file owner and group",
3982    "\
3983 Change the file owner to C<owner> and group to C<group>.
3984 This is like C<guestfs_chown> but if C<path> is a symlink then
3985 the link itself is changed, not the target.
3986
3987 Only numeric uid and gid are supported.  If you want to use
3988 names, you will need to locate and parse the password file
3989 yourself (Augeas support makes this relatively easy).");
3990
3991   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3992    [], (* XXX *)
3993    "lstat on multiple files",
3994    "\
3995 This call allows you to perform the C<guestfs_lstat> operation
3996 on multiple files, where all files are in the directory C<path>.
3997 C<names> is the list of files from this directory.
3998
3999 On return you get a list of stat structs, with a one-to-one
4000 correspondence to the C<names> list.  If any name did not exist
4001 or could not be lstat'd, then the C<ino> field of that structure
4002 is set to C<-1>.
4003
4004 This call is intended for programs that want to efficiently
4005 list a directory contents without making many round-trips.
4006 See also C<guestfs_lxattrlist> for a similarly efficient call
4007 for getting extended attributes.  Very long directory listings
4008 might cause the protocol message size to be exceeded, causing
4009 this call to fail.  The caller must split up such requests
4010 into smaller groups of names.");
4011
4012   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4013    [], (* XXX *)
4014    "lgetxattr on multiple files",
4015    "\
4016 This call allows you to get the extended attributes
4017 of multiple files, where all files are in the directory C<path>.
4018 C<names> is the list of files from this directory.
4019
4020 On return you get a flat list of xattr structs which must be
4021 interpreted sequentially.  The first xattr struct always has a zero-length
4022 C<attrname>.  C<attrval> in this struct is zero-length
4023 to indicate there was an error doing C<lgetxattr> for this
4024 file, I<or> is a C string which is a decimal number
4025 (the number of following attributes for this file, which could
4026 be C<\"0\">).  Then after the first xattr struct are the
4027 zero or more attributes for the first named file.
4028 This repeats for the second and subsequent files.
4029
4030 This call is intended for programs that want to efficiently
4031 list a directory contents without making many round-trips.
4032 See also C<guestfs_lstatlist> for a similarly efficient call
4033 for getting standard stats.  Very long directory listings
4034 might cause the protocol message size to be exceeded, causing
4035 this call to fail.  The caller must split up such requests
4036 into smaller groups of names.");
4037
4038   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4039    [], (* XXX *)
4040    "readlink on multiple files",
4041    "\
4042 This call allows you to do a C<readlink> operation
4043 on multiple files, where all files are in the directory C<path>.
4044 C<names> is the list of files from this directory.
4045
4046 On return you get a list of strings, with a one-to-one
4047 correspondence to the C<names> list.  Each string is the
4048 value of the symbolic link.
4049
4050 If the C<readlink(2)> operation fails on any name, then
4051 the corresponding result string is the empty string C<\"\">.
4052 However the whole operation is completed even if there
4053 were C<readlink(2)> errors, and so you can call this
4054 function with names where you don't know if they are
4055 symbolic links already (albeit slightly less efficient).
4056
4057 This call is intended for programs that want to efficiently
4058 list a directory contents without making many round-trips.
4059 Very long directory listings might cause the protocol
4060 message size to be exceeded, causing
4061 this call to fail.  The caller must split up such requests
4062 into smaller groups of names.");
4063
4064   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4065    [InitISOFS, Always, TestOutputBuffer (
4066       [["pread"; "/known-4"; "1"; "3"]], "\n");
4067     InitISOFS, Always, TestOutputBuffer (
4068       [["pread"; "/empty"; "0"; "100"]], "")],
4069    "read part of a file",
4070    "\
4071 This command lets you read part of a file.  It reads C<count>
4072 bytes of the file, starting at C<offset>, from file C<path>.
4073
4074 This may read fewer bytes than requested.  For further details
4075 see the L<pread(2)> system call.
4076
4077 See also C<guestfs_pwrite>.");
4078
4079   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4080    [InitEmpty, Always, TestRun (
4081       [["part_init"; "/dev/sda"; "gpt"]])],
4082    "create an empty partition table",
4083    "\
4084 This creates an empty partition table on C<device> of one of the
4085 partition types listed below.  Usually C<parttype> should be
4086 either C<msdos> or C<gpt> (for large disks).
4087
4088 Initially there are no partitions.  Following this, you should
4089 call C<guestfs_part_add> for each partition required.
4090
4091 Possible values for C<parttype> are:
4092
4093 =over 4
4094
4095 =item B<efi> | B<gpt>
4096
4097 Intel EFI / GPT partition table.
4098
4099 This is recommended for >= 2 TB partitions that will be accessed
4100 from Linux and Intel-based Mac OS X.  It also has limited backwards
4101 compatibility with the C<mbr> format.
4102
4103 =item B<mbr> | B<msdos>
4104
4105 The standard PC \"Master Boot Record\" (MBR) format used
4106 by MS-DOS and Windows.  This partition type will B<only> work
4107 for device sizes up to 2 TB.  For large disks we recommend
4108 using C<gpt>.
4109
4110 =back
4111
4112 Other partition table types that may work but are not
4113 supported include:
4114
4115 =over 4
4116
4117 =item B<aix>
4118
4119 AIX disk labels.
4120
4121 =item B<amiga> | B<rdb>
4122
4123 Amiga \"Rigid Disk Block\" format.
4124
4125 =item B<bsd>
4126
4127 BSD disk labels.
4128
4129 =item B<dasd>
4130
4131 DASD, used on IBM mainframes.
4132
4133 =item B<dvh>
4134
4135 MIPS/SGI volumes.
4136
4137 =item B<mac>
4138
4139 Old Mac partition format.  Modern Macs use C<gpt>.
4140
4141 =item B<pc98>
4142
4143 NEC PC-98 format, common in Japan apparently.
4144
4145 =item B<sun>
4146
4147 Sun disk labels.
4148
4149 =back");
4150
4151   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4152    [InitEmpty, Always, TestRun (
4153       [["part_init"; "/dev/sda"; "mbr"];
4154        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4155     InitEmpty, Always, TestRun (
4156       [["part_init"; "/dev/sda"; "gpt"];
4157        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4158        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4159     InitEmpty, Always, TestRun (
4160       [["part_init"; "/dev/sda"; "mbr"];
4161        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4162        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4163        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4164        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4165    "add a partition to the device",
4166    "\
4167 This command adds a partition to C<device>.  If there is no partition
4168 table on the device, call C<guestfs_part_init> first.
4169
4170 The C<prlogex> parameter is the type of partition.  Normally you
4171 should pass C<p> or C<primary> here, but MBR partition tables also
4172 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4173 types.
4174
4175 C<startsect> and C<endsect> are the start and end of the partition
4176 in I<sectors>.  C<endsect> may be negative, which means it counts
4177 backwards from the end of the disk (C<-1> is the last sector).
4178
4179 Creating a partition which covers the whole disk is not so easy.
4180 Use C<guestfs_part_disk> to do that.");
4181
4182   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4183    [InitEmpty, Always, TestRun (
4184       [["part_disk"; "/dev/sda"; "mbr"]]);
4185     InitEmpty, Always, TestRun (
4186       [["part_disk"; "/dev/sda"; "gpt"]])],
4187    "partition whole disk with a single primary partition",
4188    "\
4189 This command is simply a combination of C<guestfs_part_init>
4190 followed by C<guestfs_part_add> to create a single primary partition
4191 covering the whole disk.
4192
4193 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4194 but other possible values are described in C<guestfs_part_init>.");
4195
4196   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4197    [InitEmpty, Always, TestRun (
4198       [["part_disk"; "/dev/sda"; "mbr"];
4199        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4200    "make a partition bootable",
4201    "\
4202 This sets the bootable flag on partition numbered C<partnum> on
4203 device C<device>.  Note that partitions are numbered from 1.
4204
4205 The bootable flag is used by some operating systems (notably
4206 Windows) to determine which partition to boot from.  It is by
4207 no means universally recognized.");
4208
4209   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4210    [InitEmpty, Always, TestRun (
4211       [["part_disk"; "/dev/sda"; "gpt"];
4212        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4213    "set partition name",
4214    "\
4215 This sets the partition name on partition numbered C<partnum> on
4216 device C<device>.  Note that partitions are numbered from 1.
4217
4218 The partition name can only be set on certain types of partition
4219 table.  This works on C<gpt> but not on C<mbr> partitions.");
4220
4221   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4222    [], (* XXX Add a regression test for this. *)
4223    "list partitions on a device",
4224    "\
4225 This command parses the partition table on C<device> and
4226 returns the list of partitions found.
4227
4228 The fields in the returned structure are:
4229
4230 =over 4
4231
4232 =item B<part_num>
4233
4234 Partition number, counting from 1.
4235
4236 =item B<part_start>
4237
4238 Start of the partition I<in bytes>.  To get sectors you have to
4239 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4240
4241 =item B<part_end>
4242
4243 End of the partition in bytes.
4244
4245 =item B<part_size>
4246
4247 Size of the partition in bytes.
4248
4249 =back");
4250
4251   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4252    [InitEmpty, Always, TestOutput (
4253       [["part_disk"; "/dev/sda"; "gpt"];
4254        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4255    "get the partition table type",
4256    "\
4257 This command examines the partition table on C<device> and
4258 returns the partition table type (format) being used.
4259
4260 Common return values include: C<msdos> (a DOS/Windows style MBR
4261 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4262 values are possible, although unusual.  See C<guestfs_part_init>
4263 for a full list.");
4264
4265   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4266    [InitBasicFS, Always, TestOutputBuffer (
4267       [["fill"; "0x63"; "10"; "/test"];
4268        ["read_file"; "/test"]], "cccccccccc")],
4269    "fill a file with octets",
4270    "\
4271 This command creates a new file called C<path>.  The initial
4272 content of the file is C<len> octets of C<c>, where C<c>
4273 must be a number in the range C<[0..255]>.
4274
4275 To fill a file with zero bytes (sparsely), it is
4276 much more efficient to use C<guestfs_truncate_size>.
4277 To create a file with a pattern of repeating bytes
4278 use C<guestfs_fill_pattern>.");
4279
4280   ("available", (RErr, [StringList "groups"]), 216, [],
4281    [InitNone, Always, TestRun [["available"; ""]]],
4282    "test availability of some parts of the API",
4283    "\
4284 This command is used to check the availability of some
4285 groups of functionality in the appliance, which not all builds of
4286 the libguestfs appliance will be able to provide.
4287
4288 The libguestfs groups, and the functions that those
4289 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4290 You can also fetch this list at runtime by calling
4291 C<guestfs_available_all_groups>.
4292
4293 The argument C<groups> is a list of group names, eg:
4294 C<[\"inotify\", \"augeas\"]> would check for the availability of
4295 the Linux inotify functions and Augeas (configuration file
4296 editing) functions.
4297
4298 The command returns no error if I<all> requested groups are available.
4299
4300 It fails with an error if one or more of the requested
4301 groups is unavailable in the appliance.
4302
4303 If an unknown group name is included in the
4304 list of groups then an error is always returned.
4305
4306 I<Notes:>
4307
4308 =over 4
4309
4310 =item *
4311
4312 You must call C<guestfs_launch> before calling this function.
4313
4314 The reason is because we don't know what groups are
4315 supported by the appliance/daemon until it is running and can
4316 be queried.
4317
4318 =item *
4319
4320 If a group of functions is available, this does not necessarily
4321 mean that they will work.  You still have to check for errors
4322 when calling individual API functions even if they are
4323 available.
4324
4325 =item *
4326
4327 It is usually the job of distro packagers to build
4328 complete functionality into the libguestfs appliance.
4329 Upstream libguestfs, if built from source with all
4330 requirements satisfied, will support everything.
4331
4332 =item *
4333
4334 This call was added in version C<1.0.80>.  In previous
4335 versions of libguestfs all you could do would be to speculatively
4336 execute a command to find out if the daemon implemented it.
4337 See also C<guestfs_version>.
4338
4339 =back");
4340
4341   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4342    [InitBasicFS, Always, TestOutputBuffer (
4343       [["write"; "/src"; "hello, world"];
4344        ["dd"; "/src"; "/dest"];
4345        ["read_file"; "/dest"]], "hello, world")],
4346    "copy from source to destination using dd",
4347    "\
4348 This command copies from one source device or file C<src>
4349 to another destination device or file C<dest>.  Normally you
4350 would use this to copy to or from a device or partition, for
4351 example to duplicate a filesystem.
4352
4353 If the destination is a device, it must be as large or larger
4354 than the source file or device, otherwise the copy will fail.
4355 This command cannot do partial copies (see C<guestfs_copy_size>).");
4356
4357   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4358    [InitBasicFS, Always, TestOutputInt (
4359       [["write"; "/file"; "hello, world"];
4360        ["filesize"; "/file"]], 12)],
4361    "return the size of the file in bytes",
4362    "\
4363 This command returns the size of C<file> in bytes.
4364
4365 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4366 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4367 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4368
4369   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4370    [InitBasicFSonLVM, Always, TestOutputList (
4371       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4372        ["lvs"]], ["/dev/VG/LV2"])],
4373    "rename an LVM logical volume",
4374    "\
4375 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4376
4377   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4378    [InitBasicFSonLVM, Always, TestOutputList (
4379       [["umount"; "/"];
4380        ["vg_activate"; "false"; "VG"];
4381        ["vgrename"; "VG"; "VG2"];
4382        ["vg_activate"; "true"; "VG2"];
4383        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4384        ["vgs"]], ["VG2"])],
4385    "rename an LVM volume group",
4386    "\
4387 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4388
4389   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4390    [InitISOFS, Always, TestOutputBuffer (
4391       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4392    "list the contents of a single file in an initrd",
4393    "\
4394 This command unpacks the file C<filename> from the initrd file
4395 called C<initrdpath>.  The filename must be given I<without> the
4396 initial C</> character.
4397
4398 For example, in guestfish you could use the following command
4399 to examine the boot script (usually called C</init>)
4400 contained in a Linux initrd or initramfs image:
4401
4402  initrd-cat /boot/initrd-<version>.img init
4403
4404 See also C<guestfs_initrd_list>.");
4405
4406   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4407    [],
4408    "get the UUID of a physical volume",
4409    "\
4410 This command returns the UUID of the LVM PV C<device>.");
4411
4412   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4413    [],
4414    "get the UUID of a volume group",
4415    "\
4416 This command returns the UUID of the LVM VG named C<vgname>.");
4417
4418   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4419    [],
4420    "get the UUID of a logical volume",
4421    "\
4422 This command returns the UUID of the LVM LV C<device>.");
4423
4424   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4425    [],
4426    "get the PV UUIDs containing the volume group",
4427    "\
4428 Given a VG called C<vgname>, this returns the UUIDs of all
4429 the physical volumes that this volume group resides on.
4430
4431 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4432 calls to associate physical volumes and volume groups.
4433
4434 See also C<guestfs_vglvuuids>.");
4435
4436   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4437    [],
4438    "get the LV UUIDs of all LVs in the volume group",
4439    "\
4440 Given a VG called C<vgname>, this returns the UUIDs of all
4441 the logical volumes created in this volume group.
4442
4443 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4444 calls to associate logical volumes and volume groups.
4445
4446 See also C<guestfs_vgpvuuids>.");
4447
4448   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4449    [InitBasicFS, Always, TestOutputBuffer (
4450       [["write"; "/src"; "hello, world"];
4451        ["copy_size"; "/src"; "/dest"; "5"];
4452        ["read_file"; "/dest"]], "hello")],
4453    "copy size bytes from source to destination using dd",
4454    "\
4455 This command copies exactly C<size> bytes from one source device
4456 or file C<src> to another destination device or file C<dest>.
4457
4458 Note this will fail if the source is too short or if the destination
4459 is not large enough.");
4460
4461   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4462    [InitBasicFSonLVM, Always, TestRun (
4463       [["zero_device"; "/dev/VG/LV"]])],
4464    "write zeroes to an entire device",
4465    "\
4466 This command writes zeroes over the entire C<device>.  Compare
4467 with C<guestfs_zero> which just zeroes the first few blocks of
4468 a device.");
4469
4470   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4471    [InitBasicFS, Always, TestOutput (
4472       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4473        ["cat"; "/hello"]], "hello\n")],
4474    "unpack compressed tarball to directory",
4475    "\
4476 This command uploads and unpacks local file C<tarball> (an
4477 I<xz compressed> tar file) into C<directory>.");
4478
4479   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4480    [],
4481    "pack directory into compressed tarball",
4482    "\
4483 This command packs the contents of C<directory> and downloads
4484 it to local file C<tarball> (as an xz compressed tar archive).");
4485
4486   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4487    [],
4488    "resize an NTFS filesystem",
4489    "\
4490 This command resizes an NTFS filesystem, expanding or
4491 shrinking it to the size of the underlying device.
4492 See also L<ntfsresize(8)>.");
4493
4494   ("vgscan", (RErr, []), 232, [],
4495    [InitEmpty, Always, TestRun (
4496       [["vgscan"]])],
4497    "rescan for LVM physical volumes, volume groups and logical volumes",
4498    "\
4499 This rescans all block devices and rebuilds the list of LVM
4500 physical volumes, volume groups and logical volumes.");
4501
4502   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4503    [InitEmpty, Always, TestRun (
4504       [["part_init"; "/dev/sda"; "mbr"];
4505        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4506        ["part_del"; "/dev/sda"; "1"]])],
4507    "delete a partition",
4508    "\
4509 This command deletes the partition numbered C<partnum> on C<device>.
4510
4511 Note that in the case of MBR partitioning, deleting an
4512 extended partition also deletes any logical partitions
4513 it contains.");
4514
4515   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4516    [InitEmpty, Always, TestOutputTrue (
4517       [["part_init"; "/dev/sda"; "mbr"];
4518        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4519        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4520        ["part_get_bootable"; "/dev/sda"; "1"]])],
4521    "return true if a partition is bootable",
4522    "\
4523 This command returns true if the partition C<partnum> on
4524 C<device> has the bootable flag set.
4525
4526 See also C<guestfs_part_set_bootable>.");
4527
4528   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4529    [InitEmpty, Always, TestOutputInt (
4530       [["part_init"; "/dev/sda"; "mbr"];
4531        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4532        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4533        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4534    "get the MBR type byte (ID byte) from a partition",
4535    "\
4536 Returns the MBR type byte (also known as the ID byte) from
4537 the numbered partition C<partnum>.
4538
4539 Note that only MBR (old DOS-style) partitions have type bytes.
4540 You will get undefined results for other partition table
4541 types (see C<guestfs_part_get_parttype>).");
4542
4543   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4544    [], (* tested by part_get_mbr_id *)
4545    "set the MBR type byte (ID byte) of a partition",
4546    "\
4547 Sets the MBR type byte (also known as the ID byte) of
4548 the numbered partition C<partnum> to C<idbyte>.  Note
4549 that the type bytes quoted in most documentation are
4550 in fact hexadecimal numbers, but usually documented
4551 without any leading \"0x\" which might be confusing.
4552
4553 Note that only MBR (old DOS-style) partitions have type bytes.
4554 You will get undefined results for other partition table
4555 types (see C<guestfs_part_get_parttype>).");
4556
4557   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4558    [InitISOFS, Always, TestOutput (
4559       [["checksum_device"; "md5"; "/dev/sdd"]],
4560       (Digest.to_hex (Digest.file "images/test.iso")))],
4561    "compute MD5, SHAx or CRC checksum of the contents of a device",
4562    "\
4563 This call computes the MD5, SHAx or CRC checksum of the
4564 contents of the device named C<device>.  For the types of
4565 checksums supported see the C<guestfs_checksum> command.");
4566
4567   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4568    [InitNone, Always, TestRun (
4569       [["part_disk"; "/dev/sda"; "mbr"];
4570        ["pvcreate"; "/dev/sda1"];
4571        ["vgcreate"; "VG"; "/dev/sda1"];
4572        ["lvcreate"; "LV"; "VG"; "10"];
4573        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4574    "expand an LV to fill free space",
4575    "\
4576 This expands an existing logical volume C<lv> so that it fills
4577 C<pc>% of the remaining free space in the volume group.  Commonly
4578 you would call this with pc = 100 which expands the logical volume
4579 as much as possible, using all remaining free space in the volume
4580 group.");
4581
4582   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4583    [], (* XXX Augeas code needs tests. *)
4584    "clear Augeas path",
4585    "\
4586 Set the value associated with C<path> to C<NULL>.  This
4587 is the same as the L<augtool(1)> C<clear> command.");
4588
4589   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4590    [InitEmpty, Always, TestOutputInt (
4591       [["get_umask"]], 0o22)],
4592    "get the current umask",
4593    "\
4594 Return the current umask.  By default the umask is C<022>
4595 unless it has been set by calling C<guestfs_umask>.");
4596
4597   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4598    [],
4599    "upload a file to the appliance (internal use only)",
4600    "\
4601 The C<guestfs_debug_upload> command uploads a file to
4602 the libguestfs appliance.
4603
4604 There is no comprehensive help for this command.  You have
4605 to look at the file C<daemon/debug.c> in the libguestfs source
4606 to find out what it is for.");
4607
4608   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4609    [InitBasicFS, Always, TestOutput (
4610       [["base64_in"; "../images/hello.b64"; "/hello"];
4611        ["cat"; "/hello"]], "hello\n")],
4612    "upload base64-encoded data to file",
4613    "\
4614 This command uploads base64-encoded data from C<base64file>
4615 to C<filename>.");
4616
4617   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4618    [],
4619    "download file and encode as base64",
4620    "\
4621 This command downloads the contents of C<filename>, writing
4622 it out to local file C<base64file> encoded as base64.");
4623
4624   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4625    [],
4626    "compute MD5, SHAx or CRC checksum of files in a directory",
4627    "\
4628 This command computes the checksums of all regular files in
4629 C<directory> and then emits a list of those checksums to
4630 the local output file C<sumsfile>.
4631
4632 This can be used for verifying the integrity of a virtual
4633 machine.  However to be properly secure you should pay
4634 attention to the output of the checksum command (it uses
4635 the ones from GNU coreutils).  In particular when the
4636 filename is not printable, coreutils uses a special
4637 backslash syntax.  For more information, see the GNU
4638 coreutils info file.");
4639
4640   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4641    [InitBasicFS, Always, TestOutputBuffer (
4642       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4643        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4644    "fill a file with a repeating pattern of bytes",
4645    "\
4646 This function is like C<guestfs_fill> except that it creates
4647 a new file of length C<len> containing the repeating pattern
4648 of bytes in C<pattern>.  The pattern is truncated if necessary
4649 to ensure the length of the file is exactly C<len> bytes.");
4650
4651   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4652    [InitBasicFS, Always, TestOutput (
4653       [["write"; "/new"; "new file contents"];
4654        ["cat"; "/new"]], "new file contents");
4655     InitBasicFS, Always, TestOutput (
4656       [["write"; "/new"; "\nnew file contents\n"];
4657        ["cat"; "/new"]], "\nnew file contents\n");
4658     InitBasicFS, Always, TestOutput (
4659       [["write"; "/new"; "\n\n"];
4660        ["cat"; "/new"]], "\n\n");
4661     InitBasicFS, Always, TestOutput (
4662       [["write"; "/new"; ""];
4663        ["cat"; "/new"]], "");
4664     InitBasicFS, Always, TestOutput (
4665       [["write"; "/new"; "\n\n\n"];
4666        ["cat"; "/new"]], "\n\n\n");
4667     InitBasicFS, Always, TestOutput (
4668       [["write"; "/new"; "\n"];
4669        ["cat"; "/new"]], "\n")],
4670    "create a new file",
4671    "\
4672 This call creates a file called C<path>.  The content of the
4673 file is the string C<content> (which can contain any 8 bit data).");
4674
4675   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4676    [InitBasicFS, Always, TestOutput (
4677       [["write"; "/new"; "new file contents"];
4678        ["pwrite"; "/new"; "data"; "4"];
4679        ["cat"; "/new"]], "new data contents");
4680     InitBasicFS, Always, TestOutput (
4681       [["write"; "/new"; "new file contents"];
4682        ["pwrite"; "/new"; "is extended"; "9"];
4683        ["cat"; "/new"]], "new file is extended");
4684     InitBasicFS, Always, TestOutput (
4685       [["write"; "/new"; "new file contents"];
4686        ["pwrite"; "/new"; ""; "4"];
4687        ["cat"; "/new"]], "new file contents")],
4688    "write to part of a file",
4689    "\
4690 This command writes to part of a file.  It writes the data
4691 buffer C<content> to the file C<path> starting at offset C<offset>.
4692
4693 This command implements the L<pwrite(2)> system call, and like
4694 that system call it may not write the full data requested.  The
4695 return value is the number of bytes that were actually written
4696 to the file.  This could even be 0, although short writes are
4697 unlikely for regular files in ordinary circumstances.
4698
4699 See also C<guestfs_pread>.");
4700
4701   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4702    [],
4703    "resize an ext2/ext3 filesystem (with size)",
4704    "\
4705 This command is the same as C<guestfs_resize2fs> except that it
4706 allows you to specify the new size (in bytes) explicitly.");
4707
4708   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4709    [],
4710    "resize an LVM physical volume (with size)",
4711    "\
4712 This command is the same as C<guestfs_pvresize> except that it
4713 allows you to specify the new size (in bytes) explicitly.");
4714
4715   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4716    [],
4717    "resize an NTFS filesystem (with size)",
4718    "\
4719 This command is the same as C<guestfs_ntfsresize> except that it
4720 allows you to specify the new size (in bytes) explicitly.");
4721
4722   ("available_all_groups", (RStringList "groups", []), 251, [],
4723    [InitNone, Always, TestRun [["available_all_groups"]]],
4724    "return a list of all optional groups",
4725    "\
4726 This command returns a list of all optional groups that this
4727 daemon knows about.  Note this returns both supported and unsupported
4728 groups.  To find out which ones the daemon can actually support
4729 you have to call C<guestfs_available> on each member of the
4730 returned list.
4731
4732 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4733
4734   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4735    [InitBasicFS, Always, TestOutputStruct (
4736       [["fallocate64"; "/a"; "1000000"];
4737        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4738    "preallocate a file in the guest filesystem",
4739    "\
4740 This command preallocates a file (containing zero bytes) named
4741 C<path> of size C<len> bytes.  If the file exists already, it
4742 is overwritten.
4743
4744 Note that this call allocates disk blocks for the file.
4745 To create a sparse file use C<guestfs_truncate_size> instead.
4746
4747 The deprecated call C<guestfs_fallocate> does the same,
4748 but owing to an oversight it only allowed 30 bit lengths
4749 to be specified, effectively limiting the maximum size
4750 of files created through that call to 1GB.
4751
4752 Do not confuse this with the guestfish-specific
4753 C<alloc> and C<sparse> commands which create
4754 a file in the host and attach it as a device.");
4755
4756 ]
4757
4758 let all_functions = non_daemon_functions @ daemon_functions
4759
4760 (* In some places we want the functions to be displayed sorted
4761  * alphabetically, so this is useful:
4762  *)
4763 let all_functions_sorted =
4764   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4765                compare n1 n2) all_functions
4766
4767 (* This is used to generate the src/MAX_PROC_NR file which
4768  * contains the maximum procedure number, a surrogate for the
4769  * ABI version number.  See src/Makefile.am for the details.
4770  *)
4771 let max_proc_nr =
4772   let proc_nrs = List.map (
4773     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4774   ) daemon_functions in
4775   List.fold_left max 0 proc_nrs
4776
4777 (* Field types for structures. *)
4778 type field =
4779   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4780   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4781   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4782   | FUInt32
4783   | FInt32
4784   | FUInt64
4785   | FInt64
4786   | FBytes                      (* Any int measure that counts bytes. *)
4787   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4788   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4789
4790 (* Because we generate extra parsing code for LVM command line tools,
4791  * we have to pull out the LVM columns separately here.
4792  *)
4793 let lvm_pv_cols = [
4794   "pv_name", FString;
4795   "pv_uuid", FUUID;
4796   "pv_fmt", FString;
4797   "pv_size", FBytes;
4798   "dev_size", FBytes;
4799   "pv_free", FBytes;
4800   "pv_used", FBytes;
4801   "pv_attr", FString (* XXX *);
4802   "pv_pe_count", FInt64;
4803   "pv_pe_alloc_count", FInt64;
4804   "pv_tags", FString;
4805   "pe_start", FBytes;
4806   "pv_mda_count", FInt64;
4807   "pv_mda_free", FBytes;
4808   (* Not in Fedora 10:
4809      "pv_mda_size", FBytes;
4810   *)
4811 ]
4812 let lvm_vg_cols = [
4813   "vg_name", FString;
4814   "vg_uuid", FUUID;
4815   "vg_fmt", FString;
4816   "vg_attr", FString (* XXX *);
4817   "vg_size", FBytes;
4818   "vg_free", FBytes;
4819   "vg_sysid", FString;
4820   "vg_extent_size", FBytes;
4821   "vg_extent_count", FInt64;
4822   "vg_free_count", FInt64;
4823   "max_lv", FInt64;
4824   "max_pv", FInt64;
4825   "pv_count", FInt64;
4826   "lv_count", FInt64;
4827   "snap_count", FInt64;
4828   "vg_seqno", FInt64;
4829   "vg_tags", FString;
4830   "vg_mda_count", FInt64;
4831   "vg_mda_free", FBytes;
4832   (* Not in Fedora 10:
4833      "vg_mda_size", FBytes;
4834   *)
4835 ]
4836 let lvm_lv_cols = [
4837   "lv_name", FString;
4838   "lv_uuid", FUUID;
4839   "lv_attr", FString (* XXX *);
4840   "lv_major", FInt64;
4841   "lv_minor", FInt64;
4842   "lv_kernel_major", FInt64;
4843   "lv_kernel_minor", FInt64;
4844   "lv_size", FBytes;
4845   "seg_count", FInt64;
4846   "origin", FString;
4847   "snap_percent", FOptPercent;
4848   "copy_percent", FOptPercent;
4849   "move_pv", FString;
4850   "lv_tags", FString;
4851   "mirror_log", FString;
4852   "modules", FString;
4853 ]
4854
4855 (* Names and fields in all structures (in RStruct and RStructList)
4856  * that we support.
4857  *)
4858 let structs = [
4859   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4860    * not use this struct in any new code.
4861    *)
4862   "int_bool", [
4863     "i", FInt32;                (* for historical compatibility *)
4864     "b", FInt32;                (* for historical compatibility *)
4865   ];
4866
4867   (* LVM PVs, VGs, LVs. *)
4868   "lvm_pv", lvm_pv_cols;
4869   "lvm_vg", lvm_vg_cols;
4870   "lvm_lv", lvm_lv_cols;
4871
4872   (* Column names and types from stat structures.
4873    * NB. Can't use things like 'st_atime' because glibc header files
4874    * define some of these as macros.  Ugh.
4875    *)
4876   "stat", [
4877     "dev", FInt64;
4878     "ino", FInt64;
4879     "mode", FInt64;
4880     "nlink", FInt64;
4881     "uid", FInt64;
4882     "gid", FInt64;
4883     "rdev", FInt64;
4884     "size", FInt64;
4885     "blksize", FInt64;
4886     "blocks", FInt64;
4887     "atime", FInt64;
4888     "mtime", FInt64;
4889     "ctime", FInt64;
4890   ];
4891   "statvfs", [
4892     "bsize", FInt64;
4893     "frsize", FInt64;
4894     "blocks", FInt64;
4895     "bfree", FInt64;
4896     "bavail", FInt64;
4897     "files", FInt64;
4898     "ffree", FInt64;
4899     "favail", FInt64;
4900     "fsid", FInt64;
4901     "flag", FInt64;
4902     "namemax", FInt64;
4903   ];
4904
4905   (* Column names in dirent structure. *)
4906   "dirent", [
4907     "ino", FInt64;
4908     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4909     "ftyp", FChar;
4910     "name", FString;
4911   ];
4912
4913   (* Version numbers. *)
4914   "version", [
4915     "major", FInt64;
4916     "minor", FInt64;
4917     "release", FInt64;
4918     "extra", FString;
4919   ];
4920
4921   (* Extended attribute. *)
4922   "xattr", [
4923     "attrname", FString;
4924     "attrval", FBuffer;
4925   ];
4926
4927   (* Inotify events. *)
4928   "inotify_event", [
4929     "in_wd", FInt64;
4930     "in_mask", FUInt32;
4931     "in_cookie", FUInt32;
4932     "in_name", FString;
4933   ];
4934
4935   (* Partition table entry. *)
4936   "partition", [
4937     "part_num", FInt32;
4938     "part_start", FBytes;
4939     "part_end", FBytes;
4940     "part_size", FBytes;
4941   ];
4942 ] (* end of structs *)
4943
4944 (* Ugh, Java has to be different ..
4945  * These names are also used by the Haskell bindings.
4946  *)
4947 let java_structs = [
4948   "int_bool", "IntBool";
4949   "lvm_pv", "PV";
4950   "lvm_vg", "VG";
4951   "lvm_lv", "LV";
4952   "stat", "Stat";
4953   "statvfs", "StatVFS";
4954   "dirent", "Dirent";
4955   "version", "Version";
4956   "xattr", "XAttr";
4957   "inotify_event", "INotifyEvent";
4958   "partition", "Partition";
4959 ]
4960
4961 (* What structs are actually returned. *)
4962 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4963
4964 (* Returns a list of RStruct/RStructList structs that are returned
4965  * by any function.  Each element of returned list is a pair:
4966  *
4967  * (structname, RStructOnly)
4968  *    == there exists function which returns RStruct (_, structname)
4969  * (structname, RStructListOnly)
4970  *    == there exists function which returns RStructList (_, structname)
4971  * (structname, RStructAndList)
4972  *    == there are functions returning both RStruct (_, structname)
4973  *                                      and RStructList (_, structname)
4974  *)
4975 let rstructs_used_by functions =
4976   (* ||| is a "logical OR" for rstructs_used_t *)
4977   let (|||) a b =
4978     match a, b with
4979     | RStructAndList, _
4980     | _, RStructAndList -> RStructAndList
4981     | RStructOnly, RStructListOnly
4982     | RStructListOnly, RStructOnly -> RStructAndList
4983     | RStructOnly, RStructOnly -> RStructOnly
4984     | RStructListOnly, RStructListOnly -> RStructListOnly
4985   in
4986
4987   let h = Hashtbl.create 13 in
4988
4989   (* if elem->oldv exists, update entry using ||| operator,
4990    * else just add elem->newv to the hash
4991    *)
4992   let update elem newv =
4993     try  let oldv = Hashtbl.find h elem in
4994          Hashtbl.replace h elem (newv ||| oldv)
4995     with Not_found -> Hashtbl.add h elem newv
4996   in
4997
4998   List.iter (
4999     fun (_, style, _, _, _, _, _) ->
5000       match fst style with
5001       | RStruct (_, structname) -> update structname RStructOnly
5002       | RStructList (_, structname) -> update structname RStructListOnly
5003       | _ -> ()
5004   ) functions;
5005
5006   (* return key->values as a list of (key,value) *)
5007   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5008
5009 (* Used for testing language bindings. *)
5010 type callt =
5011   | CallString of string
5012   | CallOptString of string option
5013   | CallStringList of string list
5014   | CallInt of int
5015   | CallInt64 of int64
5016   | CallBool of bool
5017   | CallBuffer of string
5018
5019 (* Used to memoize the result of pod2text. *)
5020 let pod2text_memo_filename = "src/.pod2text.data"
5021 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5022   try
5023     let chan = open_in pod2text_memo_filename in
5024     let v = input_value chan in
5025     close_in chan;
5026     v
5027   with
5028     _ -> Hashtbl.create 13
5029 let pod2text_memo_updated () =
5030   let chan = open_out pod2text_memo_filename in
5031   output_value chan pod2text_memo;
5032   close_out chan
5033
5034 (* Useful functions.
5035  * Note we don't want to use any external OCaml libraries which
5036  * makes this a bit harder than it should be.
5037  *)
5038 module StringMap = Map.Make (String)
5039
5040 let failwithf fs = ksprintf failwith fs
5041
5042 let unique = let i = ref 0 in fun () -> incr i; !i
5043
5044 let replace_char s c1 c2 =
5045   let s2 = String.copy s in
5046   let r = ref false in
5047   for i = 0 to String.length s2 - 1 do
5048     if String.unsafe_get s2 i = c1 then (
5049       String.unsafe_set s2 i c2;
5050       r := true
5051     )
5052   done;
5053   if not !r then s else s2
5054
5055 let isspace c =
5056   c = ' '
5057   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5058
5059 let triml ?(test = isspace) str =
5060   let i = ref 0 in
5061   let n = ref (String.length str) in
5062   while !n > 0 && test str.[!i]; do
5063     decr n;
5064     incr i
5065   done;
5066   if !i = 0 then str
5067   else String.sub str !i !n
5068
5069 let trimr ?(test = isspace) str =
5070   let n = ref (String.length str) in
5071   while !n > 0 && test str.[!n-1]; do
5072     decr n
5073   done;
5074   if !n = String.length str then str
5075   else String.sub str 0 !n
5076
5077 let trim ?(test = isspace) str =
5078   trimr ~test (triml ~test str)
5079
5080 let rec find s sub =
5081   let len = String.length s in
5082   let sublen = String.length sub in
5083   let rec loop i =
5084     if i <= len-sublen then (
5085       let rec loop2 j =
5086         if j < sublen then (
5087           if s.[i+j] = sub.[j] then loop2 (j+1)
5088           else -1
5089         ) else
5090           i (* found *)
5091       in
5092       let r = loop2 0 in
5093       if r = -1 then loop (i+1) else r
5094     ) else
5095       -1 (* not found *)
5096   in
5097   loop 0
5098
5099 let rec replace_str s s1 s2 =
5100   let len = String.length s in
5101   let sublen = String.length s1 in
5102   let i = find s s1 in
5103   if i = -1 then s
5104   else (
5105     let s' = String.sub s 0 i in
5106     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5107     s' ^ s2 ^ replace_str s'' s1 s2
5108   )
5109
5110 let rec string_split sep str =
5111   let len = String.length str in
5112   let seplen = String.length sep in
5113   let i = find str sep in
5114   if i = -1 then [str]
5115   else (
5116     let s' = String.sub str 0 i in
5117     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5118     s' :: string_split sep s''
5119   )
5120
5121 let files_equal n1 n2 =
5122   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5123   match Sys.command cmd with
5124   | 0 -> true
5125   | 1 -> false
5126   | i -> failwithf "%s: failed with error code %d" cmd i
5127
5128 let rec filter_map f = function
5129   | [] -> []
5130   | x :: xs ->
5131       match f x with
5132       | Some y -> y :: filter_map f xs
5133       | None -> filter_map f xs
5134
5135 let rec find_map f = function
5136   | [] -> raise Not_found
5137   | x :: xs ->
5138       match f x with
5139       | Some y -> y
5140       | None -> find_map f xs
5141
5142 let iteri f xs =
5143   let rec loop i = function
5144     | [] -> ()
5145     | x :: xs -> f i x; loop (i+1) xs
5146   in
5147   loop 0 xs
5148
5149 let mapi f xs =
5150   let rec loop i = function
5151     | [] -> []
5152     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5153   in
5154   loop 0 xs
5155
5156 let count_chars c str =
5157   let count = ref 0 in
5158   for i = 0 to String.length str - 1 do
5159     if c = String.unsafe_get str i then incr count
5160   done;
5161   !count
5162
5163 let explode str =
5164   let r = ref [] in
5165   for i = 0 to String.length str - 1 do
5166     let c = String.unsafe_get str i in
5167     r := c :: !r;
5168   done;
5169   List.rev !r
5170
5171 let map_chars f str =
5172   List.map f (explode str)
5173
5174 let name_of_argt = function
5175   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5176   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5177   | FileIn n | FileOut n | BufferIn n -> n
5178
5179 let java_name_of_struct typ =
5180   try List.assoc typ java_structs
5181   with Not_found ->
5182     failwithf
5183       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5184
5185 let cols_of_struct typ =
5186   try List.assoc typ structs
5187   with Not_found ->
5188     failwithf "cols_of_struct: unknown struct %s" typ
5189
5190 let seq_of_test = function
5191   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5192   | TestOutputListOfDevices (s, _)
5193   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5194   | TestOutputTrue s | TestOutputFalse s
5195   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5196   | TestOutputStruct (s, _)
5197   | TestLastFail s -> s
5198
5199 (* Handling for function flags. *)
5200 let protocol_limit_warning =
5201   "Because of the message protocol, there is a transfer limit
5202 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5203
5204 let danger_will_robinson =
5205   "B<This command is dangerous.  Without careful use you
5206 can easily destroy all your data>."
5207
5208 let deprecation_notice flags =
5209   try
5210     let alt =
5211       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5212     let txt =
5213       sprintf "This function is deprecated.
5214 In new code, use the C<%s> call instead.
5215
5216 Deprecated functions will not be removed from the API, but the
5217 fact that they are deprecated indicates that there are problems
5218 with correct use of these functions." alt in
5219     Some txt
5220   with
5221     Not_found -> None
5222
5223 (* Create list of optional groups. *)
5224 let optgroups =
5225   let h = Hashtbl.create 13 in
5226   List.iter (
5227     fun (name, _, _, flags, _, _, _) ->
5228       List.iter (
5229         function
5230         | Optional group ->
5231             let names = try Hashtbl.find h group with Not_found -> [] in
5232             Hashtbl.replace h group (name :: names)
5233         | _ -> ()
5234       ) flags
5235   ) daemon_functions;
5236   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5237   let groups =
5238     List.map (
5239       fun group -> group, List.sort compare (Hashtbl.find h group)
5240     ) groups in
5241   List.sort (fun x y -> compare (fst x) (fst y)) groups
5242
5243 (* Check function names etc. for consistency. *)
5244 let check_functions () =
5245   let contains_uppercase str =
5246     let len = String.length str in
5247     let rec loop i =
5248       if i >= len then false
5249       else (
5250         let c = str.[i] in
5251         if c >= 'A' && c <= 'Z' then true
5252         else loop (i+1)
5253       )
5254     in
5255     loop 0
5256   in
5257
5258   (* Check function names. *)
5259   List.iter (
5260     fun (name, _, _, _, _, _, _) ->
5261       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5262         failwithf "function name %s does not need 'guestfs' prefix" name;
5263       if name = "" then
5264         failwithf "function name is empty";
5265       if name.[0] < 'a' || name.[0] > 'z' then
5266         failwithf "function name %s must start with lowercase a-z" name;
5267       if String.contains name '-' then
5268         failwithf "function name %s should not contain '-', use '_' instead."
5269           name
5270   ) all_functions;
5271
5272   (* Check function parameter/return names. *)
5273   List.iter (
5274     fun (name, style, _, _, _, _, _) ->
5275       let check_arg_ret_name n =
5276         if contains_uppercase n then
5277           failwithf "%s param/ret %s should not contain uppercase chars"
5278             name n;
5279         if String.contains n '-' || String.contains n '_' then
5280           failwithf "%s param/ret %s should not contain '-' or '_'"
5281             name n;
5282         if n = "value" then
5283           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;
5284         if n = "int" || n = "char" || n = "short" || n = "long" then
5285           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5286         if n = "i" || n = "n" then
5287           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5288         if n = "argv" || n = "args" then
5289           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5290
5291         (* List Haskell, OCaml and C keywords here.
5292          * http://www.haskell.org/haskellwiki/Keywords
5293          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5294          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5295          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5296          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5297          * Omitting _-containing words, since they're handled above.
5298          * Omitting the OCaml reserved word, "val", is ok,
5299          * and saves us from renaming several parameters.
5300          *)
5301         let reserved = [
5302           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5303           "char"; "class"; "const"; "constraint"; "continue"; "data";
5304           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5305           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5306           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5307           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5308           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5309           "interface";
5310           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5311           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5312           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5313           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5314           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5315           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5316           "volatile"; "when"; "where"; "while";
5317           ] in
5318         if List.mem n reserved then
5319           failwithf "%s has param/ret using reserved word %s" name n;
5320       in
5321
5322       (match fst style with
5323        | RErr -> ()
5324        | RInt n | RInt64 n | RBool n
5325        | RConstString n | RConstOptString n | RString n
5326        | RStringList n | RStruct (n, _) | RStructList (n, _)
5327        | RHashtable n | RBufferOut n ->
5328            check_arg_ret_name n
5329       );
5330       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5331   ) all_functions;
5332
5333   (* Check short descriptions. *)
5334   List.iter (
5335     fun (name, _, _, _, _, shortdesc, _) ->
5336       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5337         failwithf "short description of %s should begin with lowercase." name;
5338       let c = shortdesc.[String.length shortdesc-1] in
5339       if c = '\n' || c = '.' then
5340         failwithf "short description of %s should not end with . or \\n." name
5341   ) all_functions;
5342
5343   (* Check long descriptions. *)
5344   List.iter (
5345     fun (name, _, _, _, _, _, longdesc) ->
5346       if longdesc.[String.length longdesc-1] = '\n' then
5347         failwithf "long description of %s should not end with \\n." name
5348   ) all_functions;
5349
5350   (* Check proc_nrs. *)
5351   List.iter (
5352     fun (name, _, proc_nr, _, _, _, _) ->
5353       if proc_nr <= 0 then
5354         failwithf "daemon function %s should have proc_nr > 0" name
5355   ) daemon_functions;
5356
5357   List.iter (
5358     fun (name, _, proc_nr, _, _, _, _) ->
5359       if proc_nr <> -1 then
5360         failwithf "non-daemon function %s should have proc_nr -1" name
5361   ) non_daemon_functions;
5362
5363   let proc_nrs =
5364     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5365       daemon_functions in
5366   let proc_nrs =
5367     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5368   let rec loop = function
5369     | [] -> ()
5370     | [_] -> ()
5371     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5372         loop rest
5373     | (name1,nr1) :: (name2,nr2) :: _ ->
5374         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5375           name1 name2 nr1 nr2
5376   in
5377   loop proc_nrs;
5378
5379   (* Check tests. *)
5380   List.iter (
5381     function
5382       (* Ignore functions that have no tests.  We generate a
5383        * warning when the user does 'make check' instead.
5384        *)
5385     | name, _, _, _, [], _, _ -> ()
5386     | name, _, _, _, tests, _, _ ->
5387         let funcs =
5388           List.map (
5389             fun (_, _, test) ->
5390               match seq_of_test test with
5391               | [] ->
5392                   failwithf "%s has a test containing an empty sequence" name
5393               | cmds -> List.map List.hd cmds
5394           ) tests in
5395         let funcs = List.flatten funcs in
5396
5397         let tested = List.mem name funcs in
5398
5399         if not tested then
5400           failwithf "function %s has tests but does not test itself" name
5401   ) all_functions
5402
5403 (* 'pr' prints to the current output file. *)
5404 let chan = ref Pervasives.stdout
5405 let lines = ref 0
5406 let pr fs =
5407   ksprintf
5408     (fun str ->
5409        let i = count_chars '\n' str in
5410        lines := !lines + i;
5411        output_string !chan str
5412     ) fs
5413
5414 let copyright_years =
5415   let this_year = 1900 + (localtime (time ())).tm_year in
5416   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5417
5418 (* Generate a header block in a number of standard styles. *)
5419 type comment_style =
5420     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5421 type license = GPLv2plus | LGPLv2plus
5422
5423 let generate_header ?(extra_inputs = []) comment license =
5424   let inputs = "src/generator.ml" :: extra_inputs in
5425   let c = match comment with
5426     | CStyle ->         pr "/* "; " *"
5427     | CPlusPlusStyle -> pr "// "; "//"
5428     | HashStyle ->      pr "# ";  "#"
5429     | OCamlStyle ->     pr "(* "; " *"
5430     | HaskellStyle ->   pr "{- "; "  " in
5431   pr "libguestfs generated file\n";
5432   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5433   List.iter (pr "%s   %s\n" c) inputs;
5434   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5435   pr "%s\n" c;
5436   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5437   pr "%s\n" c;
5438   (match license with
5439    | GPLv2plus ->
5440        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5441        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5442        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5443        pr "%s (at your option) any later version.\n" c;
5444        pr "%s\n" c;
5445        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5446        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5447        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5448        pr "%s GNU General Public License for more details.\n" c;
5449        pr "%s\n" c;
5450        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5451        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5452        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5453
5454    | LGPLv2plus ->
5455        pr "%s This library is free software; you can redistribute it and/or\n" c;
5456        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5457        pr "%s License as published by the Free Software Foundation; either\n" c;
5458        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5459        pr "%s\n" c;
5460        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5461        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5462        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5463        pr "%s Lesser General Public License for more details.\n" c;
5464        pr "%s\n" c;
5465        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5466        pr "%s License along with this library; if not, write to the Free Software\n" c;
5467        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5468   );
5469   (match comment with
5470    | CStyle -> pr " */\n"
5471    | CPlusPlusStyle
5472    | HashStyle -> ()
5473    | OCamlStyle -> pr " *)\n"
5474    | HaskellStyle -> pr "-}\n"
5475   );
5476   pr "\n"
5477
5478 (* Start of main code generation functions below this line. *)
5479
5480 (* Generate the pod documentation for the C API. *)
5481 let rec generate_actions_pod () =
5482   List.iter (
5483     fun (shortname, style, _, flags, _, _, longdesc) ->
5484       if not (List.mem NotInDocs flags) then (
5485         let name = "guestfs_" ^ shortname in
5486         pr "=head2 %s\n\n" name;
5487         pr " ";
5488         generate_prototype ~extern:false ~handle:"g" name style;
5489         pr "\n\n";
5490         pr "%s\n\n" longdesc;
5491         (match fst style with
5492          | RErr ->
5493              pr "This function returns 0 on success or -1 on error.\n\n"
5494          | RInt _ ->
5495              pr "On error this function returns -1.\n\n"
5496          | RInt64 _ ->
5497              pr "On error this function returns -1.\n\n"
5498          | RBool _ ->
5499              pr "This function returns a C truth value on success or -1 on error.\n\n"
5500          | RConstString _ ->
5501              pr "This function returns a string, or NULL on error.
5502 The string is owned by the guest handle and must I<not> be freed.\n\n"
5503          | RConstOptString _ ->
5504              pr "This function returns a string which may be NULL.
5505 There is way to return an error from this function.
5506 The string is owned by the guest handle and must I<not> be freed.\n\n"
5507          | RString _ ->
5508              pr "This function returns a string, or NULL on error.
5509 I<The caller must free the returned string after use>.\n\n"
5510          | RStringList _ ->
5511              pr "This function returns a NULL-terminated array of strings
5512 (like L<environ(3)>), or NULL if there was an error.
5513 I<The caller must free the strings and the array after use>.\n\n"
5514          | RStruct (_, typ) ->
5515              pr "This function returns a C<struct guestfs_%s *>,
5516 or NULL if there was an error.
5517 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5518          | RStructList (_, typ) ->
5519              pr "This function returns a C<struct guestfs_%s_list *>
5520 (see E<lt>guestfs-structs.hE<gt>),
5521 or NULL if there was an error.
5522 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5523          | RHashtable _ ->
5524              pr "This function returns a NULL-terminated array of
5525 strings, or NULL if there was an error.
5526 The array of strings will always have length C<2n+1>, where
5527 C<n> keys and values alternate, followed by the trailing NULL entry.
5528 I<The caller must free the strings and the array after use>.\n\n"
5529          | RBufferOut _ ->
5530              pr "This function returns a buffer, or NULL on error.
5531 The size of the returned buffer is written to C<*size_r>.
5532 I<The caller must free the returned buffer after use>.\n\n"
5533         );
5534         if List.mem ProtocolLimitWarning flags then
5535           pr "%s\n\n" protocol_limit_warning;
5536         if List.mem DangerWillRobinson flags then
5537           pr "%s\n\n" danger_will_robinson;
5538         match deprecation_notice flags with
5539         | None -> ()
5540         | Some txt -> pr "%s\n\n" txt
5541       )
5542   ) all_functions_sorted
5543
5544 and generate_structs_pod () =
5545   (* Structs documentation. *)
5546   List.iter (
5547     fun (typ, cols) ->
5548       pr "=head2 guestfs_%s\n" typ;
5549       pr "\n";
5550       pr " struct guestfs_%s {\n" typ;
5551       List.iter (
5552         function
5553         | name, FChar -> pr "   char %s;\n" name
5554         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5555         | name, FInt32 -> pr "   int32_t %s;\n" name
5556         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5557         | name, FInt64 -> pr "   int64_t %s;\n" name
5558         | name, FString -> pr "   char *%s;\n" name
5559         | name, FBuffer ->
5560             pr "   /* The next two fields describe a byte array. */\n";
5561             pr "   uint32_t %s_len;\n" name;
5562             pr "   char *%s;\n" name
5563         | name, FUUID ->
5564             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5565             pr "   char %s[32];\n" name
5566         | name, FOptPercent ->
5567             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5568             pr "   float %s;\n" name
5569       ) cols;
5570       pr " };\n";
5571       pr " \n";
5572       pr " struct guestfs_%s_list {\n" typ;
5573       pr "   uint32_t len; /* Number of elements in list. */\n";
5574       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5575       pr " };\n";
5576       pr " \n";
5577       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5578       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5579         typ typ;
5580       pr "\n"
5581   ) structs
5582
5583 and generate_availability_pod () =
5584   (* Availability documentation. *)
5585   pr "=over 4\n";
5586   pr "\n";
5587   List.iter (
5588     fun (group, functions) ->
5589       pr "=item B<%s>\n" group;
5590       pr "\n";
5591       pr "The following functions:\n";
5592       List.iter (pr "L</guestfs_%s>\n") functions;
5593       pr "\n"
5594   ) optgroups;
5595   pr "=back\n";
5596   pr "\n"
5597
5598 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5599  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5600  *
5601  * We have to use an underscore instead of a dash because otherwise
5602  * rpcgen generates incorrect code.
5603  *
5604  * This header is NOT exported to clients, but see also generate_structs_h.
5605  *)
5606 and generate_xdr () =
5607   generate_header CStyle LGPLv2plus;
5608
5609   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5610   pr "typedef string str<>;\n";
5611   pr "\n";
5612
5613   (* Internal structures. *)
5614   List.iter (
5615     function
5616     | typ, cols ->
5617         pr "struct guestfs_int_%s {\n" typ;
5618         List.iter (function
5619                    | name, FChar -> pr "  char %s;\n" name
5620                    | name, FString -> pr "  string %s<>;\n" name
5621                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5622                    | name, FUUID -> pr "  opaque %s[32];\n" name
5623                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5624                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5625                    | name, FOptPercent -> pr "  float %s;\n" name
5626                   ) cols;
5627         pr "};\n";
5628         pr "\n";
5629         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5630         pr "\n";
5631   ) structs;
5632
5633   List.iter (
5634     fun (shortname, style, _, _, _, _, _) ->
5635       let name = "guestfs_" ^ shortname in
5636
5637       (match snd style with
5638        | [] -> ()
5639        | args ->
5640            pr "struct %s_args {\n" name;
5641            List.iter (
5642              function
5643              | Pathname n | Device n | Dev_or_Path n | String n ->
5644                  pr "  string %s<>;\n" n
5645              | OptString n -> pr "  str *%s;\n" n
5646              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5647              | Bool n -> pr "  bool %s;\n" n
5648              | Int n -> pr "  int %s;\n" n
5649              | Int64 n -> pr "  hyper %s;\n" n
5650              | BufferIn n ->
5651                  pr "  opaque %s<>;\n" n
5652              | FileIn _ | FileOut _ -> ()
5653            ) args;
5654            pr "};\n\n"
5655       );
5656       (match fst style with
5657        | RErr -> ()
5658        | RInt n ->
5659            pr "struct %s_ret {\n" name;
5660            pr "  int %s;\n" n;
5661            pr "};\n\n"
5662        | RInt64 n ->
5663            pr "struct %s_ret {\n" name;
5664            pr "  hyper %s;\n" n;
5665            pr "};\n\n"
5666        | RBool n ->
5667            pr "struct %s_ret {\n" name;
5668            pr "  bool %s;\n" n;
5669            pr "};\n\n"
5670        | RConstString _ | RConstOptString _ ->
5671            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5672        | RString n ->
5673            pr "struct %s_ret {\n" name;
5674            pr "  string %s<>;\n" n;
5675            pr "};\n\n"
5676        | RStringList n ->
5677            pr "struct %s_ret {\n" name;
5678            pr "  str %s<>;\n" n;
5679            pr "};\n\n"
5680        | RStruct (n, typ) ->
5681            pr "struct %s_ret {\n" name;
5682            pr "  guestfs_int_%s %s;\n" typ n;
5683            pr "};\n\n"
5684        | RStructList (n, typ) ->
5685            pr "struct %s_ret {\n" name;
5686            pr "  guestfs_int_%s_list %s;\n" typ n;
5687            pr "};\n\n"
5688        | RHashtable n ->
5689            pr "struct %s_ret {\n" name;
5690            pr "  str %s<>;\n" n;
5691            pr "};\n\n"
5692        | RBufferOut n ->
5693            pr "struct %s_ret {\n" name;
5694            pr "  opaque %s<>;\n" n;
5695            pr "};\n\n"
5696       );
5697   ) daemon_functions;
5698
5699   (* Table of procedure numbers. *)
5700   pr "enum guestfs_procedure {\n";
5701   List.iter (
5702     fun (shortname, _, proc_nr, _, _, _, _) ->
5703       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5704   ) daemon_functions;
5705   pr "  GUESTFS_PROC_NR_PROCS\n";
5706   pr "};\n";
5707   pr "\n";
5708
5709   (* Having to choose a maximum message size is annoying for several
5710    * reasons (it limits what we can do in the API), but it (a) makes
5711    * the protocol a lot simpler, and (b) provides a bound on the size
5712    * of the daemon which operates in limited memory space.
5713    *)
5714   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5715   pr "\n";
5716
5717   (* Message header, etc. *)
5718   pr "\
5719 /* The communication protocol is now documented in the guestfs(3)
5720  * manpage.
5721  */
5722
5723 const GUESTFS_PROGRAM = 0x2000F5F5;
5724 const GUESTFS_PROTOCOL_VERSION = 1;
5725
5726 /* These constants must be larger than any possible message length. */
5727 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5728 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5729
5730 enum guestfs_message_direction {
5731   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5732   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5733 };
5734
5735 enum guestfs_message_status {
5736   GUESTFS_STATUS_OK = 0,
5737   GUESTFS_STATUS_ERROR = 1
5738 };
5739
5740 const GUESTFS_ERROR_LEN = 256;
5741
5742 struct guestfs_message_error {
5743   string error_message<GUESTFS_ERROR_LEN>;
5744 };
5745
5746 struct guestfs_message_header {
5747   unsigned prog;                     /* GUESTFS_PROGRAM */
5748   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5749   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5750   guestfs_message_direction direction;
5751   unsigned serial;                   /* message serial number */
5752   guestfs_message_status status;
5753 };
5754
5755 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5756
5757 struct guestfs_chunk {
5758   int cancel;                        /* if non-zero, transfer is cancelled */
5759   /* data size is 0 bytes if the transfer has finished successfully */
5760   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5761 };
5762 "
5763
5764 (* Generate the guestfs-structs.h file. *)
5765 and generate_structs_h () =
5766   generate_header CStyle LGPLv2plus;
5767
5768   (* This is a public exported header file containing various
5769    * structures.  The structures are carefully written to have
5770    * exactly the same in-memory format as the XDR structures that
5771    * we use on the wire to the daemon.  The reason for creating
5772    * copies of these structures here is just so we don't have to
5773    * export the whole of guestfs_protocol.h (which includes much
5774    * unrelated and XDR-dependent stuff that we don't want to be
5775    * public, or required by clients).
5776    *
5777    * To reiterate, we will pass these structures to and from the
5778    * client with a simple assignment or memcpy, so the format
5779    * must be identical to what rpcgen / the RFC defines.
5780    *)
5781
5782   (* Public structures. *)
5783   List.iter (
5784     fun (typ, cols) ->
5785       pr "struct guestfs_%s {\n" typ;
5786       List.iter (
5787         function
5788         | name, FChar -> pr "  char %s;\n" name
5789         | name, FString -> pr "  char *%s;\n" name
5790         | name, FBuffer ->
5791             pr "  uint32_t %s_len;\n" name;
5792             pr "  char *%s;\n" name
5793         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5794         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5795         | name, FInt32 -> pr "  int32_t %s;\n" name
5796         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5797         | name, FInt64 -> pr "  int64_t %s;\n" name
5798         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5799       ) cols;
5800       pr "};\n";
5801       pr "\n";
5802       pr "struct guestfs_%s_list {\n" typ;
5803       pr "  uint32_t len;\n";
5804       pr "  struct guestfs_%s *val;\n" typ;
5805       pr "};\n";
5806       pr "\n";
5807       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5808       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5809       pr "\n"
5810   ) structs
5811
5812 (* Generate the guestfs-actions.h file. *)
5813 and generate_actions_h () =
5814   generate_header CStyle LGPLv2plus;
5815   List.iter (
5816     fun (shortname, style, _, _, _, _, _) ->
5817       let name = "guestfs_" ^ shortname in
5818       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5819         name style
5820   ) all_functions
5821
5822 (* Generate the guestfs-internal-actions.h file. *)
5823 and generate_internal_actions_h () =
5824   generate_header CStyle LGPLv2plus;
5825   List.iter (
5826     fun (shortname, style, _, _, _, _, _) ->
5827       let name = "guestfs__" ^ shortname in
5828       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5829         name style
5830   ) non_daemon_functions
5831
5832 (* Generate the client-side dispatch stubs. *)
5833 and generate_client_actions () =
5834   generate_header CStyle LGPLv2plus;
5835
5836   pr "\
5837 #include <stdio.h>
5838 #include <stdlib.h>
5839 #include <stdint.h>
5840 #include <string.h>
5841 #include <inttypes.h>
5842
5843 #include \"guestfs.h\"
5844 #include \"guestfs-internal.h\"
5845 #include \"guestfs-internal-actions.h\"
5846 #include \"guestfs_protocol.h\"
5847
5848 #define error guestfs_error
5849 //#define perrorf guestfs_perrorf
5850 #define safe_malloc guestfs_safe_malloc
5851 #define safe_realloc guestfs_safe_realloc
5852 //#define safe_strdup guestfs_safe_strdup
5853 #define safe_memdup guestfs_safe_memdup
5854
5855 /* Check the return message from a call for validity. */
5856 static int
5857 check_reply_header (guestfs_h *g,
5858                     const struct guestfs_message_header *hdr,
5859                     unsigned int proc_nr, unsigned int serial)
5860 {
5861   if (hdr->prog != GUESTFS_PROGRAM) {
5862     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5863     return -1;
5864   }
5865   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5866     error (g, \"wrong protocol version (%%d/%%d)\",
5867            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5868     return -1;
5869   }
5870   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5871     error (g, \"unexpected message direction (%%d/%%d)\",
5872            hdr->direction, GUESTFS_DIRECTION_REPLY);
5873     return -1;
5874   }
5875   if (hdr->proc != proc_nr) {
5876     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5877     return -1;
5878   }
5879   if (hdr->serial != serial) {
5880     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5881     return -1;
5882   }
5883
5884   return 0;
5885 }
5886
5887 /* Check we are in the right state to run a high-level action. */
5888 static int
5889 check_state (guestfs_h *g, const char *caller)
5890 {
5891   if (!guestfs__is_ready (g)) {
5892     if (guestfs__is_config (g) || guestfs__is_launching (g))
5893       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5894         caller);
5895     else
5896       error (g, \"%%s called from the wrong state, %%d != READY\",
5897         caller, guestfs__get_state (g));
5898     return -1;
5899   }
5900   return 0;
5901 }
5902
5903 ";
5904
5905   let error_code_of = function
5906     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5907     | RConstString _ | RConstOptString _
5908     | RString _ | RStringList _
5909     | RStruct _ | RStructList _
5910     | RHashtable _ | RBufferOut _ -> "NULL"
5911   in
5912
5913   (* Generate code to check String-like parameters are not passed in
5914    * as NULL (returning an error if they are).
5915    *)
5916   let check_null_strings shortname style =
5917     let pr_newline = ref false in
5918     List.iter (
5919       function
5920       (* parameters which should not be NULL *)
5921       | String n
5922       | Device n
5923       | Pathname n
5924       | Dev_or_Path n
5925       | FileIn n
5926       | FileOut n
5927       | BufferIn n
5928       | StringList n
5929       | DeviceList n ->
5930           pr "  if (%s == NULL) {\n" n;
5931           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5932           pr "           \"%s\", \"%s\");\n" shortname n;
5933           pr "    return %s;\n" (error_code_of (fst style));
5934           pr "  }\n";
5935           pr_newline := true
5936
5937       (* can be NULL *)
5938       | OptString _
5939
5940       (* not applicable *)
5941       | Bool _
5942       | Int _
5943       | Int64 _ -> ()
5944     ) (snd style);
5945
5946     if !pr_newline then pr "\n";
5947   in
5948
5949   (* Generate code to generate guestfish call traces. *)
5950   let trace_call shortname style =
5951     pr "  if (guestfs__get_trace (g)) {\n";
5952
5953     let needs_i =
5954       List.exists (function
5955                    | StringList _ | DeviceList _ -> true
5956                    | _ -> false) (snd style) in
5957     if needs_i then (
5958       pr "    int i;\n";
5959       pr "\n"
5960     );
5961
5962     pr "    printf (\"%s\");\n" shortname;
5963     List.iter (
5964       function
5965       | String n                        (* strings *)
5966       | Device n
5967       | Pathname n
5968       | Dev_or_Path n
5969       | FileIn n
5970       | FileOut n
5971       | BufferIn n ->
5972           (* guestfish doesn't support string escaping, so neither do we *)
5973           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5974       | OptString n ->                  (* string option *)
5975           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5976           pr "    else printf (\" null\");\n"
5977       | StringList n
5978       | DeviceList n ->                 (* string list *)
5979           pr "    putchar (' ');\n";
5980           pr "    putchar ('\"');\n";
5981           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5982           pr "      if (i > 0) putchar (' ');\n";
5983           pr "      fputs (%s[i], stdout);\n" n;
5984           pr "    }\n";
5985           pr "    putchar ('\"');\n";
5986       | Bool n ->                       (* boolean *)
5987           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5988       | Int n ->                        (* int *)
5989           pr "    printf (\" %%d\", %s);\n" n
5990       | Int64 n ->
5991           pr "    printf (\" %%\" PRIi64, %s);\n" n
5992     ) (snd style);
5993     pr "    putchar ('\\n');\n";
5994     pr "  }\n";
5995     pr "\n";
5996   in
5997
5998   (* For non-daemon functions, generate a wrapper around each function. *)
5999   List.iter (
6000     fun (shortname, style, _, _, _, _, _) ->
6001       let name = "guestfs_" ^ shortname in
6002
6003       generate_prototype ~extern:false ~semicolon:false ~newline:true
6004         ~handle:"g" name style;
6005       pr "{\n";
6006       check_null_strings shortname style;
6007       trace_call shortname style;
6008       pr "  return guestfs__%s " shortname;
6009       generate_c_call_args ~handle:"g" style;
6010       pr ";\n";
6011       pr "}\n";
6012       pr "\n"
6013   ) non_daemon_functions;
6014
6015   (* Client-side stubs for each function. *)
6016   List.iter (
6017     fun (shortname, style, _, _, _, _, _) ->
6018       let name = "guestfs_" ^ shortname in
6019       let error_code = error_code_of (fst style) in
6020
6021       (* Generate the action stub. *)
6022       generate_prototype ~extern:false ~semicolon:false ~newline:true
6023         ~handle:"g" name style;
6024
6025       pr "{\n";
6026
6027       (match snd style with
6028        | [] -> ()
6029        | _ -> pr "  struct %s_args args;\n" name
6030       );
6031
6032       pr "  guestfs_message_header hdr;\n";
6033       pr "  guestfs_message_error err;\n";
6034       let has_ret =
6035         match fst style with
6036         | RErr -> false
6037         | RConstString _ | RConstOptString _ ->
6038             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6039         | RInt _ | RInt64 _
6040         | RBool _ | RString _ | RStringList _
6041         | RStruct _ | RStructList _
6042         | RHashtable _ | RBufferOut _ ->
6043             pr "  struct %s_ret ret;\n" name;
6044             true in
6045
6046       pr "  int serial;\n";
6047       pr "  int r;\n";
6048       pr "\n";
6049       check_null_strings shortname style;
6050       trace_call shortname style;
6051       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6052         shortname error_code;
6053       pr "  guestfs___set_busy (g);\n";
6054       pr "\n";
6055
6056       (* Send the main header and arguments. *)
6057       (match snd style with
6058        | [] ->
6059            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6060              (String.uppercase shortname)
6061        | args ->
6062            List.iter (
6063              function
6064              | Pathname n | Device n | Dev_or_Path n | String n ->
6065                  pr "  args.%s = (char *) %s;\n" n n
6066              | OptString n ->
6067                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6068              | StringList n | DeviceList n ->
6069                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6070                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6071              | Bool n ->
6072                  pr "  args.%s = %s;\n" n n
6073              | Int n ->
6074                  pr "  args.%s = %s;\n" n n
6075              | Int64 n ->
6076                  pr "  args.%s = %s;\n" n n
6077              | FileIn _ | FileOut _ -> ()
6078              | BufferIn n ->
6079                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6080                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6081                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6082                    shortname;
6083                  pr "    guestfs___end_busy (g);\n";
6084                  pr "    return %s;\n" error_code;
6085                  pr "  }\n";
6086                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6087                  pr "  args.%s.%s_len = %s_size;\n" n n n
6088            ) args;
6089            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6090              (String.uppercase shortname);
6091            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6092              name;
6093       );
6094       pr "  if (serial == -1) {\n";
6095       pr "    guestfs___end_busy (g);\n";
6096       pr "    return %s;\n" error_code;
6097       pr "  }\n";
6098       pr "\n";
6099
6100       (* Send any additional files (FileIn) requested. *)
6101       let need_read_reply_label = ref false in
6102       List.iter (
6103         function
6104         | FileIn n ->
6105             pr "  r = guestfs___send_file (g, %s);\n" n;
6106             pr "  if (r == -1) {\n";
6107             pr "    guestfs___end_busy (g);\n";
6108             pr "    return %s;\n" error_code;
6109             pr "  }\n";
6110             pr "  if (r == -2) /* daemon cancelled */\n";
6111             pr "    goto read_reply;\n";
6112             need_read_reply_label := true;
6113             pr "\n";
6114         | _ -> ()
6115       ) (snd style);
6116
6117       (* Wait for the reply from the remote end. *)
6118       if !need_read_reply_label then pr " read_reply:\n";
6119       pr "  memset (&hdr, 0, sizeof hdr);\n";
6120       pr "  memset (&err, 0, sizeof err);\n";
6121       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6122       pr "\n";
6123       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6124       if not has_ret then
6125         pr "NULL, NULL"
6126       else
6127         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6128       pr ");\n";
6129
6130       pr "  if (r == -1) {\n";
6131       pr "    guestfs___end_busy (g);\n";
6132       pr "    return %s;\n" error_code;
6133       pr "  }\n";
6134       pr "\n";
6135
6136       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6137         (String.uppercase shortname);
6138       pr "    guestfs___end_busy (g);\n";
6139       pr "    return %s;\n" error_code;
6140       pr "  }\n";
6141       pr "\n";
6142
6143       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6144       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6145       pr "    free (err.error_message);\n";
6146       pr "    guestfs___end_busy (g);\n";
6147       pr "    return %s;\n" error_code;
6148       pr "  }\n";
6149       pr "\n";
6150
6151       (* Expecting to receive further files (FileOut)? *)
6152       List.iter (
6153         function
6154         | FileOut n ->
6155             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6156             pr "    guestfs___end_busy (g);\n";
6157             pr "    return %s;\n" error_code;
6158             pr "  }\n";
6159             pr "\n";
6160         | _ -> ()
6161       ) (snd style);
6162
6163       pr "  guestfs___end_busy (g);\n";
6164
6165       (match fst style with
6166        | RErr -> pr "  return 0;\n"
6167        | RInt n | RInt64 n | RBool n ->
6168            pr "  return ret.%s;\n" n
6169        | RConstString _ | RConstOptString _ ->
6170            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6171        | RString n ->
6172            pr "  return ret.%s; /* caller will free */\n" n
6173        | RStringList n | RHashtable n ->
6174            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6175            pr "  ret.%s.%s_val =\n" n n;
6176            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6177            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6178              n n;
6179            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6180            pr "  return ret.%s.%s_val;\n" n n
6181        | RStruct (n, _) ->
6182            pr "  /* caller will free this */\n";
6183            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6184        | RStructList (n, _) ->
6185            pr "  /* caller will free this */\n";
6186            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6187        | RBufferOut n ->
6188            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6189            pr "   * _val might be NULL here.  To make the API saner for\n";
6190            pr "   * callers, we turn this case into a unique pointer (using\n";
6191            pr "   * malloc(1)).\n";
6192            pr "   */\n";
6193            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6194            pr "    *size_r = ret.%s.%s_len;\n" n n;
6195            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6196            pr "  } else {\n";
6197            pr "    free (ret.%s.%s_val);\n" n n;
6198            pr "    char *p = safe_malloc (g, 1);\n";
6199            pr "    *size_r = ret.%s.%s_len;\n" n n;
6200            pr "    return p;\n";
6201            pr "  }\n";
6202       );
6203
6204       pr "}\n\n"
6205   ) daemon_functions;
6206
6207   (* Functions to free structures. *)
6208   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6209   pr " * structure format is identical to the XDR format.  See note in\n";
6210   pr " * generator.ml.\n";
6211   pr " */\n";
6212   pr "\n";
6213
6214   List.iter (
6215     fun (typ, _) ->
6216       pr "void\n";
6217       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6218       pr "{\n";
6219       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6220       pr "  free (x);\n";
6221       pr "}\n";
6222       pr "\n";
6223
6224       pr "void\n";
6225       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6226       pr "{\n";
6227       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6228       pr "  free (x);\n";
6229       pr "}\n";
6230       pr "\n";
6231
6232   ) structs;
6233
6234 (* Generate daemon/actions.h. *)
6235 and generate_daemon_actions_h () =
6236   generate_header CStyle GPLv2plus;
6237
6238   pr "#include \"../src/guestfs_protocol.h\"\n";
6239   pr "\n";
6240
6241   List.iter (
6242     fun (name, style, _, _, _, _, _) ->
6243       generate_prototype
6244         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6245         name style;
6246   ) daemon_functions
6247
6248 (* Generate the linker script which controls the visibility of
6249  * symbols in the public ABI and ensures no other symbols get
6250  * exported accidentally.
6251  *)
6252 and generate_linker_script () =
6253   generate_header HashStyle GPLv2plus;
6254
6255   let globals = [
6256     "guestfs_create";
6257     "guestfs_close";
6258     "guestfs_get_error_handler";
6259     "guestfs_get_out_of_memory_handler";
6260     "guestfs_last_error";
6261     "guestfs_set_error_handler";
6262     "guestfs_set_launch_done_callback";
6263     "guestfs_set_log_message_callback";
6264     "guestfs_set_out_of_memory_handler";
6265     "guestfs_set_subprocess_quit_callback";
6266
6267     (* Unofficial parts of the API: the bindings code use these
6268      * functions, so it is useful to export them.
6269      *)
6270     "guestfs_safe_calloc";
6271     "guestfs_safe_malloc";
6272   ] in
6273   let functions =
6274     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6275       all_functions in
6276   let structs =
6277     List.concat (
6278       List.map (fun (typ, _) ->
6279                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6280         structs
6281     ) in
6282   let globals = List.sort compare (globals @ functions @ structs) in
6283
6284   pr "{\n";
6285   pr "    global:\n";
6286   List.iter (pr "        %s;\n") globals;
6287   pr "\n";
6288
6289   pr "    local:\n";
6290   pr "        *;\n";
6291   pr "};\n"
6292
6293 (* Generate the server-side stubs. *)
6294 and generate_daemon_actions () =
6295   generate_header CStyle GPLv2plus;
6296
6297   pr "#include <config.h>\n";
6298   pr "\n";
6299   pr "#include <stdio.h>\n";
6300   pr "#include <stdlib.h>\n";
6301   pr "#include <string.h>\n";
6302   pr "#include <inttypes.h>\n";
6303   pr "#include <rpc/types.h>\n";
6304   pr "#include <rpc/xdr.h>\n";
6305   pr "\n";
6306   pr "#include \"daemon.h\"\n";
6307   pr "#include \"c-ctype.h\"\n";
6308   pr "#include \"../src/guestfs_protocol.h\"\n";
6309   pr "#include \"actions.h\"\n";
6310   pr "\n";
6311
6312   List.iter (
6313     fun (name, style, _, _, _, _, _) ->
6314       (* Generate server-side stubs. *)
6315       pr "static void %s_stub (XDR *xdr_in)\n" name;
6316       pr "{\n";
6317       let error_code =
6318         match fst style with
6319         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6320         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6321         | RBool _ -> pr "  int r;\n"; "-1"
6322         | RConstString _ | RConstOptString _ ->
6323             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6324         | RString _ -> pr "  char *r;\n"; "NULL"
6325         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6326         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6327         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6328         | RBufferOut _ ->
6329             pr "  size_t size = 1;\n";
6330             pr "  char *r;\n";
6331             "NULL" in
6332
6333       (match snd style with
6334        | [] -> ()
6335        | args ->
6336            pr "  struct guestfs_%s_args args;\n" name;
6337            List.iter (
6338              function
6339              | Device n | Dev_or_Path n
6340              | Pathname n
6341              | String n -> ()
6342              | OptString n -> pr "  char *%s;\n" n
6343              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6344              | Bool n -> pr "  int %s;\n" n
6345              | Int n -> pr "  int %s;\n" n
6346              | Int64 n -> pr "  int64_t %s;\n" n
6347              | FileIn _ | FileOut _ -> ()
6348              | BufferIn n ->
6349                  pr "  const char *%s;\n" n;
6350                  pr "  size_t %s_size;\n" n
6351            ) args
6352       );
6353       pr "\n";
6354
6355       let is_filein =
6356         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6357
6358       (match snd style with
6359        | [] -> ()
6360        | args ->
6361            pr "  memset (&args, 0, sizeof args);\n";
6362            pr "\n";
6363            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6364            if is_filein then
6365              pr "    if (cancel_receive () != -2)\n";
6366            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6367            pr "    goto done;\n";
6368            pr "  }\n";
6369            let pr_args n =
6370              pr "  char *%s = args.%s;\n" n n
6371            in
6372            let pr_list_handling_code n =
6373              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6374              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6375              pr "  if (%s == NULL) {\n" n;
6376              if is_filein then
6377                pr "    if (cancel_receive () != -2)\n";
6378              pr "      reply_with_perror (\"realloc\");\n";
6379              pr "    goto done;\n";
6380              pr "  }\n";
6381              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6382              pr "  args.%s.%s_val = %s;\n" n n n;
6383            in
6384            List.iter (
6385              function
6386              | Pathname n ->
6387                  pr_args n;
6388                  pr "  ABS_PATH (%s, %s, goto done);\n"
6389                    n (if is_filein then "cancel_receive ()" else "0");
6390              | Device n ->
6391                  pr_args n;
6392                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6393                    n (if is_filein then "cancel_receive ()" else "0");
6394              | Dev_or_Path n ->
6395                  pr_args n;
6396                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6397                    n (if is_filein then "cancel_receive ()" else "0");
6398              | String n -> pr_args n
6399              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6400              | StringList n ->
6401                  pr_list_handling_code n;
6402              | DeviceList n ->
6403                  pr_list_handling_code n;
6404                  pr "  /* Ensure that each is a device,\n";
6405                  pr "   * and perform device name translation. */\n";
6406                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6407                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6408                    (if is_filein then "cancel_receive ()" else "0");
6409                  pr "  }\n";
6410              | Bool n -> pr "  %s = args.%s;\n" n n
6411              | Int n -> pr "  %s = args.%s;\n" n n
6412              | Int64 n -> pr "  %s = args.%s;\n" n n
6413              | FileIn _ | FileOut _ -> ()
6414              | BufferIn n ->
6415                  pr "  %s = args.%s.%s_val;\n" n n n;
6416                  pr "  %s_size = args.%s.%s_len;\n" n n n
6417            ) args;
6418            pr "\n"
6419       );
6420
6421       (* this is used at least for do_equal *)
6422       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6423         (* Emit NEED_ROOT just once, even when there are two or
6424            more Pathname args *)
6425         pr "  NEED_ROOT (%s, goto done);\n"
6426           (if is_filein then "cancel_receive ()" else "0");
6427       );
6428
6429       (* Don't want to call the impl with any FileIn or FileOut
6430        * parameters, since these go "outside" the RPC protocol.
6431        *)
6432       let args' =
6433         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6434           (snd style) in
6435       pr "  r = do_%s " name;
6436       generate_c_call_args (fst style, args');
6437       pr ";\n";
6438
6439       (match fst style with
6440        | RErr | RInt _ | RInt64 _ | RBool _
6441        | RConstString _ | RConstOptString _
6442        | RString _ | RStringList _ | RHashtable _
6443        | RStruct (_, _) | RStructList (_, _) ->
6444            pr "  if (r == %s)\n" error_code;
6445            pr "    /* do_%s has already called reply_with_error */\n" name;
6446            pr "    goto done;\n";
6447            pr "\n"
6448        | RBufferOut _ ->
6449            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6450            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6451            pr "   */\n";
6452            pr "  if (size == 1 && r == %s)\n" error_code;
6453            pr "    /* do_%s has already called reply_with_error */\n" name;
6454            pr "    goto done;\n";
6455            pr "\n"
6456       );
6457
6458       (* If there are any FileOut parameters, then the impl must
6459        * send its own reply.
6460        *)
6461       let no_reply =
6462         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6463       if no_reply then
6464         pr "  /* do_%s has already sent a reply */\n" name
6465       else (
6466         match fst style with
6467         | RErr -> pr "  reply (NULL, NULL);\n"
6468         | RInt n | RInt64 n | RBool n ->
6469             pr "  struct guestfs_%s_ret ret;\n" name;
6470             pr "  ret.%s = r;\n" n;
6471             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6472               name
6473         | RConstString _ | RConstOptString _ ->
6474             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6475         | RString n ->
6476             pr "  struct guestfs_%s_ret ret;\n" name;
6477             pr "  ret.%s = r;\n" n;
6478             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6479               name;
6480             pr "  free (r);\n"
6481         | RStringList n | RHashtable n ->
6482             pr "  struct guestfs_%s_ret ret;\n" name;
6483             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6484             pr "  ret.%s.%s_val = r;\n" n n;
6485             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6486               name;
6487             pr "  free_strings (r);\n"
6488         | RStruct (n, _) ->
6489             pr "  struct guestfs_%s_ret ret;\n" name;
6490             pr "  ret.%s = *r;\n" n;
6491             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6492               name;
6493             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6494               name
6495         | RStructList (n, _) ->
6496             pr "  struct guestfs_%s_ret ret;\n" name;
6497             pr "  ret.%s = *r;\n" n;
6498             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6499               name;
6500             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6501               name
6502         | RBufferOut n ->
6503             pr "  struct guestfs_%s_ret ret;\n" name;
6504             pr "  ret.%s.%s_val = r;\n" n n;
6505             pr "  ret.%s.%s_len = size;\n" n n;
6506             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6507               name;
6508             pr "  free (r);\n"
6509       );
6510
6511       (* Free the args. *)
6512       pr "done:\n";
6513       (match snd style with
6514        | [] -> ()
6515        | _ ->
6516            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6517              name
6518       );
6519       pr "  return;\n";
6520       pr "}\n\n";
6521   ) daemon_functions;
6522
6523   (* Dispatch function. *)
6524   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6525   pr "{\n";
6526   pr "  switch (proc_nr) {\n";
6527
6528   List.iter (
6529     fun (name, style, _, _, _, _, _) ->
6530       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6531       pr "      %s_stub (xdr_in);\n" name;
6532       pr "      break;\n"
6533   ) daemon_functions;
6534
6535   pr "    default:\n";
6536   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";
6537   pr "  }\n";
6538   pr "}\n";
6539   pr "\n";
6540
6541   (* LVM columns and tokenization functions. *)
6542   (* XXX This generates crap code.  We should rethink how we
6543    * do this parsing.
6544    *)
6545   List.iter (
6546     function
6547     | typ, cols ->
6548         pr "static const char *lvm_%s_cols = \"%s\";\n"
6549           typ (String.concat "," (List.map fst cols));
6550         pr "\n";
6551
6552         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6553         pr "{\n";
6554         pr "  char *tok, *p, *next;\n";
6555         pr "  int i, j;\n";
6556         pr "\n";
6557         (*
6558           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6559           pr "\n";
6560         *)
6561         pr "  if (!str) {\n";
6562         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6563         pr "    return -1;\n";
6564         pr "  }\n";
6565         pr "  if (!*str || c_isspace (*str)) {\n";
6566         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6567         pr "    return -1;\n";
6568         pr "  }\n";
6569         pr "  tok = str;\n";
6570         List.iter (
6571           fun (name, coltype) ->
6572             pr "  if (!tok) {\n";
6573             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6574             pr "    return -1;\n";
6575             pr "  }\n";
6576             pr "  p = strchrnul (tok, ',');\n";
6577             pr "  if (*p) next = p+1; else next = NULL;\n";
6578             pr "  *p = '\\0';\n";
6579             (match coltype with
6580              | FString ->
6581                  pr "  r->%s = strdup (tok);\n" name;
6582                  pr "  if (r->%s == NULL) {\n" name;
6583                  pr "    perror (\"strdup\");\n";
6584                  pr "    return -1;\n";
6585                  pr "  }\n"
6586              | FUUID ->
6587                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6588                  pr "    if (tok[j] == '\\0') {\n";
6589                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6590                  pr "      return -1;\n";
6591                  pr "    } else if (tok[j] != '-')\n";
6592                  pr "      r->%s[i++] = tok[j];\n" name;
6593                  pr "  }\n";
6594              | FBytes ->
6595                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6596                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6597                  pr "    return -1;\n";
6598                  pr "  }\n";
6599              | FInt64 ->
6600                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6601                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6602                  pr "    return -1;\n";
6603                  pr "  }\n";
6604              | FOptPercent ->
6605                  pr "  if (tok[0] == '\\0')\n";
6606                  pr "    r->%s = -1;\n" name;
6607                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6608                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6609                  pr "    return -1;\n";
6610                  pr "  }\n";
6611              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6612                  assert false (* can never be an LVM column *)
6613             );
6614             pr "  tok = next;\n";
6615         ) cols;
6616
6617         pr "  if (tok != NULL) {\n";
6618         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6619         pr "    return -1;\n";
6620         pr "  }\n";
6621         pr "  return 0;\n";
6622         pr "}\n";
6623         pr "\n";
6624
6625         pr "guestfs_int_lvm_%s_list *\n" typ;
6626         pr "parse_command_line_%ss (void)\n" typ;
6627         pr "{\n";
6628         pr "  char *out, *err;\n";
6629         pr "  char *p, *pend;\n";
6630         pr "  int r, i;\n";
6631         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6632         pr "  void *newp;\n";
6633         pr "\n";
6634         pr "  ret = malloc (sizeof *ret);\n";
6635         pr "  if (!ret) {\n";
6636         pr "    reply_with_perror (\"malloc\");\n";
6637         pr "    return NULL;\n";
6638         pr "  }\n";
6639         pr "\n";
6640         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6641         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6642         pr "\n";
6643         pr "  r = command (&out, &err,\n";
6644         pr "           \"lvm\", \"%ss\",\n" typ;
6645         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6646         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6647         pr "  if (r == -1) {\n";
6648         pr "    reply_with_error (\"%%s\", err);\n";
6649         pr "    free (out);\n";
6650         pr "    free (err);\n";
6651         pr "    free (ret);\n";
6652         pr "    return NULL;\n";
6653         pr "  }\n";
6654         pr "\n";
6655         pr "  free (err);\n";
6656         pr "\n";
6657         pr "  /* Tokenize each line of the output. */\n";
6658         pr "  p = out;\n";
6659         pr "  i = 0;\n";
6660         pr "  while (p) {\n";
6661         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6662         pr "    if (pend) {\n";
6663         pr "      *pend = '\\0';\n";
6664         pr "      pend++;\n";
6665         pr "    }\n";
6666         pr "\n";
6667         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6668         pr "      p++;\n";
6669         pr "\n";
6670         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6671         pr "      p = pend;\n";
6672         pr "      continue;\n";
6673         pr "    }\n";
6674         pr "\n";
6675         pr "    /* Allocate some space to store this next entry. */\n";
6676         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6677         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6678         pr "    if (newp == NULL) {\n";
6679         pr "      reply_with_perror (\"realloc\");\n";
6680         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6681         pr "      free (ret);\n";
6682         pr "      free (out);\n";
6683         pr "      return NULL;\n";
6684         pr "    }\n";
6685         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6686         pr "\n";
6687         pr "    /* Tokenize the next entry. */\n";
6688         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6689         pr "    if (r == -1) {\n";
6690         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6691         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6692         pr "      free (ret);\n";
6693         pr "      free (out);\n";
6694         pr "      return NULL;\n";
6695         pr "    }\n";
6696         pr "\n";
6697         pr "    ++i;\n";
6698         pr "    p = pend;\n";
6699         pr "  }\n";
6700         pr "\n";
6701         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6702         pr "\n";
6703         pr "  free (out);\n";
6704         pr "  return ret;\n";
6705         pr "}\n"
6706
6707   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6708
6709 (* Generate a list of function names, for debugging in the daemon.. *)
6710 and generate_daemon_names () =
6711   generate_header CStyle GPLv2plus;
6712
6713   pr "#include <config.h>\n";
6714   pr "\n";
6715   pr "#include \"daemon.h\"\n";
6716   pr "\n";
6717
6718   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6719   pr "const char *function_names[] = {\n";
6720   List.iter (
6721     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6722   ) daemon_functions;
6723   pr "};\n";
6724
6725 (* Generate the optional groups for the daemon to implement
6726  * guestfs_available.
6727  *)
6728 and generate_daemon_optgroups_c () =
6729   generate_header CStyle GPLv2plus;
6730
6731   pr "#include <config.h>\n";
6732   pr "\n";
6733   pr "#include \"daemon.h\"\n";
6734   pr "#include \"optgroups.h\"\n";
6735   pr "\n";
6736
6737   pr "struct optgroup optgroups[] = {\n";
6738   List.iter (
6739     fun (group, _) ->
6740       pr "  { \"%s\", optgroup_%s_available },\n" group group
6741   ) optgroups;
6742   pr "  { NULL, NULL }\n";
6743   pr "};\n"
6744
6745 and generate_daemon_optgroups_h () =
6746   generate_header CStyle GPLv2plus;
6747
6748   List.iter (
6749     fun (group, _) ->
6750       pr "extern int optgroup_%s_available (void);\n" group
6751   ) optgroups
6752
6753 (* Generate the tests. *)
6754 and generate_tests () =
6755   generate_header CStyle GPLv2plus;
6756
6757   pr "\
6758 #include <stdio.h>
6759 #include <stdlib.h>
6760 #include <string.h>
6761 #include <unistd.h>
6762 #include <sys/types.h>
6763 #include <fcntl.h>
6764
6765 #include \"guestfs.h\"
6766 #include \"guestfs-internal.h\"
6767
6768 static guestfs_h *g;
6769 static int suppress_error = 0;
6770
6771 static void print_error (guestfs_h *g, void *data, const char *msg)
6772 {
6773   if (!suppress_error)
6774     fprintf (stderr, \"%%s\\n\", msg);
6775 }
6776
6777 /* FIXME: nearly identical code appears in fish.c */
6778 static void print_strings (char *const *argv)
6779 {
6780   int argc;
6781
6782   for (argc = 0; argv[argc] != NULL; ++argc)
6783     printf (\"\\t%%s\\n\", argv[argc]);
6784 }
6785
6786 /*
6787 static void print_table (char const *const *argv)
6788 {
6789   int i;
6790
6791   for (i = 0; argv[i] != NULL; i += 2)
6792     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6793 }
6794 */
6795
6796 ";
6797
6798   (* Generate a list of commands which are not tested anywhere. *)
6799   pr "static void no_test_warnings (void)\n";
6800   pr "{\n";
6801
6802   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6803   List.iter (
6804     fun (_, _, _, _, tests, _, _) ->
6805       let tests = filter_map (
6806         function
6807         | (_, (Always|If _|Unless _), test) -> Some test
6808         | (_, Disabled, _) -> None
6809       ) tests in
6810       let seq = List.concat (List.map seq_of_test tests) in
6811       let cmds_tested = List.map List.hd seq in
6812       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6813   ) all_functions;
6814
6815   List.iter (
6816     fun (name, _, _, _, _, _, _) ->
6817       if not (Hashtbl.mem hash name) then
6818         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6819   ) all_functions;
6820
6821   pr "}\n";
6822   pr "\n";
6823
6824   (* Generate the actual tests.  Note that we generate the tests
6825    * in reverse order, deliberately, so that (in general) the
6826    * newest tests run first.  This makes it quicker and easier to
6827    * debug them.
6828    *)
6829   let test_names =
6830     List.map (
6831       fun (name, _, _, flags, tests, _, _) ->
6832         mapi (generate_one_test name flags) tests
6833     ) (List.rev all_functions) in
6834   let test_names = List.concat test_names in
6835   let nr_tests = List.length test_names in
6836
6837   pr "\
6838 int main (int argc, char *argv[])
6839 {
6840   char c = 0;
6841   unsigned long int n_failed = 0;
6842   const char *filename;
6843   int fd;
6844   int nr_tests, test_num = 0;
6845
6846   setbuf (stdout, NULL);
6847
6848   no_test_warnings ();
6849
6850   g = guestfs_create ();
6851   if (g == NULL) {
6852     printf (\"guestfs_create FAILED\\n\");
6853     exit (EXIT_FAILURE);
6854   }
6855
6856   guestfs_set_error_handler (g, print_error, NULL);
6857
6858   guestfs_set_path (g, \"../appliance\");
6859
6860   filename = \"test1.img\";
6861   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6862   if (fd == -1) {
6863     perror (filename);
6864     exit (EXIT_FAILURE);
6865   }
6866   if (lseek (fd, %d, SEEK_SET) == -1) {
6867     perror (\"lseek\");
6868     close (fd);
6869     unlink (filename);
6870     exit (EXIT_FAILURE);
6871   }
6872   if (write (fd, &c, 1) == -1) {
6873     perror (\"write\");
6874     close (fd);
6875     unlink (filename);
6876     exit (EXIT_FAILURE);
6877   }
6878   if (close (fd) == -1) {
6879     perror (filename);
6880     unlink (filename);
6881     exit (EXIT_FAILURE);
6882   }
6883   if (guestfs_add_drive (g, filename) == -1) {
6884     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6885     exit (EXIT_FAILURE);
6886   }
6887
6888   filename = \"test2.img\";
6889   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6890   if (fd == -1) {
6891     perror (filename);
6892     exit (EXIT_FAILURE);
6893   }
6894   if (lseek (fd, %d, SEEK_SET) == -1) {
6895     perror (\"lseek\");
6896     close (fd);
6897     unlink (filename);
6898     exit (EXIT_FAILURE);
6899   }
6900   if (write (fd, &c, 1) == -1) {
6901     perror (\"write\");
6902     close (fd);
6903     unlink (filename);
6904     exit (EXIT_FAILURE);
6905   }
6906   if (close (fd) == -1) {
6907     perror (filename);
6908     unlink (filename);
6909     exit (EXIT_FAILURE);
6910   }
6911   if (guestfs_add_drive (g, filename) == -1) {
6912     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6913     exit (EXIT_FAILURE);
6914   }
6915
6916   filename = \"test3.img\";
6917   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6918   if (fd == -1) {
6919     perror (filename);
6920     exit (EXIT_FAILURE);
6921   }
6922   if (lseek (fd, %d, SEEK_SET) == -1) {
6923     perror (\"lseek\");
6924     close (fd);
6925     unlink (filename);
6926     exit (EXIT_FAILURE);
6927   }
6928   if (write (fd, &c, 1) == -1) {
6929     perror (\"write\");
6930     close (fd);
6931     unlink (filename);
6932     exit (EXIT_FAILURE);
6933   }
6934   if (close (fd) == -1) {
6935     perror (filename);
6936     unlink (filename);
6937     exit (EXIT_FAILURE);
6938   }
6939   if (guestfs_add_drive (g, filename) == -1) {
6940     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6941     exit (EXIT_FAILURE);
6942   }
6943
6944   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6945     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6946     exit (EXIT_FAILURE);
6947   }
6948
6949   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6950   alarm (600);
6951
6952   if (guestfs_launch (g) == -1) {
6953     printf (\"guestfs_launch FAILED\\n\");
6954     exit (EXIT_FAILURE);
6955   }
6956
6957   /* Cancel previous alarm. */
6958   alarm (0);
6959
6960   nr_tests = %d;
6961
6962 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6963
6964   iteri (
6965     fun i test_name ->
6966       pr "  test_num++;\n";
6967       pr "  if (guestfs_get_verbose (g))\n";
6968       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6969       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6970       pr "  if (%s () == -1) {\n" test_name;
6971       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6972       pr "    n_failed++;\n";
6973       pr "  }\n";
6974   ) test_names;
6975   pr "\n";
6976
6977   pr "  guestfs_close (g);\n";
6978   pr "  unlink (\"test1.img\");\n";
6979   pr "  unlink (\"test2.img\");\n";
6980   pr "  unlink (\"test3.img\");\n";
6981   pr "\n";
6982
6983   pr "  if (n_failed > 0) {\n";
6984   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6985   pr "    exit (EXIT_FAILURE);\n";
6986   pr "  }\n";
6987   pr "\n";
6988
6989   pr "  exit (EXIT_SUCCESS);\n";
6990   pr "}\n"
6991
6992 and generate_one_test name flags i (init, prereq, test) =
6993   let test_name = sprintf "test_%s_%d" name i in
6994
6995   pr "\
6996 static int %s_skip (void)
6997 {
6998   const char *str;
6999
7000   str = getenv (\"TEST_ONLY\");
7001   if (str)
7002     return strstr (str, \"%s\") == NULL;
7003   str = getenv (\"SKIP_%s\");
7004   if (str && STREQ (str, \"1\")) return 1;
7005   str = getenv (\"SKIP_TEST_%s\");
7006   if (str && STREQ (str, \"1\")) return 1;
7007   return 0;
7008 }
7009
7010 " test_name name (String.uppercase test_name) (String.uppercase name);
7011
7012   (match prereq with
7013    | Disabled | Always -> ()
7014    | If code | Unless code ->
7015        pr "static int %s_prereq (void)\n" test_name;
7016        pr "{\n";
7017        pr "  %s\n" code;
7018        pr "}\n";
7019        pr "\n";
7020   );
7021
7022   pr "\
7023 static int %s (void)
7024 {
7025   if (%s_skip ()) {
7026     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7027     return 0;
7028   }
7029
7030 " test_name test_name test_name;
7031
7032   (* Optional functions should only be tested if the relevant
7033    * support is available in the daemon.
7034    *)
7035   List.iter (
7036     function
7037     | Optional group ->
7038         pr "  {\n";
7039         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7040         pr "    int r;\n";
7041         pr "    suppress_error = 1;\n";
7042         pr "    r = guestfs_available (g, (char **) groups);\n";
7043         pr "    suppress_error = 0;\n";
7044         pr "    if (r == -1) {\n";
7045         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7046         pr "      return 0;\n";
7047         pr "    }\n";
7048         pr "  }\n";
7049     | _ -> ()
7050   ) flags;
7051
7052   (match prereq with
7053    | Disabled ->
7054        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7055    | If _ ->
7056        pr "  if (! %s_prereq ()) {\n" test_name;
7057        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7058        pr "    return 0;\n";
7059        pr "  }\n";
7060        pr "\n";
7061        generate_one_test_body name i test_name init test;
7062    | Unless _ ->
7063        pr "  if (%s_prereq ()) {\n" test_name;
7064        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7065        pr "    return 0;\n";
7066        pr "  }\n";
7067        pr "\n";
7068        generate_one_test_body name i test_name init test;
7069    | Always ->
7070        generate_one_test_body name i test_name init test
7071   );
7072
7073   pr "  return 0;\n";
7074   pr "}\n";
7075   pr "\n";
7076   test_name
7077
7078 and generate_one_test_body name i test_name init test =
7079   (match init with
7080    | InitNone (* XXX at some point, InitNone and InitEmpty became
7081                * folded together as the same thing.  Really we should
7082                * make InitNone do nothing at all, but the tests may
7083                * need to be checked to make sure this is OK.
7084                *)
7085    | InitEmpty ->
7086        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7087        List.iter (generate_test_command_call test_name)
7088          [["blockdev_setrw"; "/dev/sda"];
7089           ["umount_all"];
7090           ["lvm_remove_all"]]
7091    | InitPartition ->
7092        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7093        List.iter (generate_test_command_call test_name)
7094          [["blockdev_setrw"; "/dev/sda"];
7095           ["umount_all"];
7096           ["lvm_remove_all"];
7097           ["part_disk"; "/dev/sda"; "mbr"]]
7098    | InitBasicFS ->
7099        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7100        List.iter (generate_test_command_call test_name)
7101          [["blockdev_setrw"; "/dev/sda"];
7102           ["umount_all"];
7103           ["lvm_remove_all"];
7104           ["part_disk"; "/dev/sda"; "mbr"];
7105           ["mkfs"; "ext2"; "/dev/sda1"];
7106           ["mount_options"; ""; "/dev/sda1"; "/"]]
7107    | InitBasicFSonLVM ->
7108        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7109          test_name;
7110        List.iter (generate_test_command_call test_name)
7111          [["blockdev_setrw"; "/dev/sda"];
7112           ["umount_all"];
7113           ["lvm_remove_all"];
7114           ["part_disk"; "/dev/sda"; "mbr"];
7115           ["pvcreate"; "/dev/sda1"];
7116           ["vgcreate"; "VG"; "/dev/sda1"];
7117           ["lvcreate"; "LV"; "VG"; "8"];
7118           ["mkfs"; "ext2"; "/dev/VG/LV"];
7119           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7120    | InitISOFS ->
7121        pr "  /* InitISOFS for %s */\n" test_name;
7122        List.iter (generate_test_command_call test_name)
7123          [["blockdev_setrw"; "/dev/sda"];
7124           ["umount_all"];
7125           ["lvm_remove_all"];
7126           ["mount_ro"; "/dev/sdd"; "/"]]
7127   );
7128
7129   let get_seq_last = function
7130     | [] ->
7131         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7132           test_name
7133     | seq ->
7134         let seq = List.rev seq in
7135         List.rev (List.tl seq), List.hd seq
7136   in
7137
7138   match test with
7139   | TestRun seq ->
7140       pr "  /* TestRun for %s (%d) */\n" name i;
7141       List.iter (generate_test_command_call test_name) seq
7142   | TestOutput (seq, expected) ->
7143       pr "  /* TestOutput for %s (%d) */\n" name i;
7144       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7145       let seq, last = get_seq_last seq in
7146       let test () =
7147         pr "    if (STRNEQ (r, expected)) {\n";
7148         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7149         pr "      return -1;\n";
7150         pr "    }\n"
7151       in
7152       List.iter (generate_test_command_call test_name) seq;
7153       generate_test_command_call ~test test_name last
7154   | TestOutputList (seq, expected) ->
7155       pr "  /* TestOutputList for %s (%d) */\n" name i;
7156       let seq, last = get_seq_last seq in
7157       let test () =
7158         iteri (
7159           fun i str ->
7160             pr "    if (!r[%d]) {\n" i;
7161             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7162             pr "      print_strings (r);\n";
7163             pr "      return -1;\n";
7164             pr "    }\n";
7165             pr "    {\n";
7166             pr "      const char *expected = \"%s\";\n" (c_quote str);
7167             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7168             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7169             pr "        return -1;\n";
7170             pr "      }\n";
7171             pr "    }\n"
7172         ) expected;
7173         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7174         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7175           test_name;
7176         pr "      print_strings (r);\n";
7177         pr "      return -1;\n";
7178         pr "    }\n"
7179       in
7180       List.iter (generate_test_command_call test_name) seq;
7181       generate_test_command_call ~test test_name last
7182   | TestOutputListOfDevices (seq, expected) ->
7183       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7184       let seq, last = get_seq_last seq in
7185       let test () =
7186         iteri (
7187           fun i str ->
7188             pr "    if (!r[%d]) {\n" i;
7189             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7190             pr "      print_strings (r);\n";
7191             pr "      return -1;\n";
7192             pr "    }\n";
7193             pr "    {\n";
7194             pr "      const char *expected = \"%s\";\n" (c_quote str);
7195             pr "      r[%d][5] = 's';\n" i;
7196             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7197             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7198             pr "        return -1;\n";
7199             pr "      }\n";
7200             pr "    }\n"
7201         ) expected;
7202         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7203         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7204           test_name;
7205         pr "      print_strings (r);\n";
7206         pr "      return -1;\n";
7207         pr "    }\n"
7208       in
7209       List.iter (generate_test_command_call test_name) seq;
7210       generate_test_command_call ~test test_name last
7211   | TestOutputInt (seq, expected) ->
7212       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7213       let seq, last = get_seq_last seq in
7214       let test () =
7215         pr "    if (r != %d) {\n" expected;
7216         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7217           test_name expected;
7218         pr "               (int) r);\n";
7219         pr "      return -1;\n";
7220         pr "    }\n"
7221       in
7222       List.iter (generate_test_command_call test_name) seq;
7223       generate_test_command_call ~test test_name last
7224   | TestOutputIntOp (seq, op, expected) ->
7225       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7226       let seq, last = get_seq_last seq in
7227       let test () =
7228         pr "    if (! (r %s %d)) {\n" op expected;
7229         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7230           test_name op expected;
7231         pr "               (int) r);\n";
7232         pr "      return -1;\n";
7233         pr "    }\n"
7234       in
7235       List.iter (generate_test_command_call test_name) seq;
7236       generate_test_command_call ~test test_name last
7237   | TestOutputTrue seq ->
7238       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7239       let seq, last = get_seq_last seq in
7240       let test () =
7241         pr "    if (!r) {\n";
7242         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7243           test_name;
7244         pr "      return -1;\n";
7245         pr "    }\n"
7246       in
7247       List.iter (generate_test_command_call test_name) seq;
7248       generate_test_command_call ~test test_name last
7249   | TestOutputFalse seq ->
7250       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7251       let seq, last = get_seq_last seq in
7252       let test () =
7253         pr "    if (r) {\n";
7254         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7255           test_name;
7256         pr "      return -1;\n";
7257         pr "    }\n"
7258       in
7259       List.iter (generate_test_command_call test_name) seq;
7260       generate_test_command_call ~test test_name last
7261   | TestOutputLength (seq, expected) ->
7262       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7263       let seq, last = get_seq_last seq in
7264       let test () =
7265         pr "    int j;\n";
7266         pr "    for (j = 0; j < %d; ++j)\n" expected;
7267         pr "      if (r[j] == NULL) {\n";
7268         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7269           test_name;
7270         pr "        print_strings (r);\n";
7271         pr "        return -1;\n";
7272         pr "      }\n";
7273         pr "    if (r[j] != NULL) {\n";
7274         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7275           test_name;
7276         pr "      print_strings (r);\n";
7277         pr "      return -1;\n";
7278         pr "    }\n"
7279       in
7280       List.iter (generate_test_command_call test_name) seq;
7281       generate_test_command_call ~test test_name last
7282   | TestOutputBuffer (seq, expected) ->
7283       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7284       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7285       let seq, last = get_seq_last seq in
7286       let len = String.length expected in
7287       let test () =
7288         pr "    if (size != %d) {\n" len;
7289         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7290         pr "      return -1;\n";
7291         pr "    }\n";
7292         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7293         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7294         pr "      return -1;\n";
7295         pr "    }\n"
7296       in
7297       List.iter (generate_test_command_call test_name) seq;
7298       generate_test_command_call ~test test_name last
7299   | TestOutputStruct (seq, checks) ->
7300       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7301       let seq, last = get_seq_last seq in
7302       let test () =
7303         List.iter (
7304           function
7305           | CompareWithInt (field, expected) ->
7306               pr "    if (r->%s != %d) {\n" field expected;
7307               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7308                 test_name field expected;
7309               pr "               (int) r->%s);\n" field;
7310               pr "      return -1;\n";
7311               pr "    }\n"
7312           | CompareWithIntOp (field, op, expected) ->
7313               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7314               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7315                 test_name field op expected;
7316               pr "               (int) r->%s);\n" field;
7317               pr "      return -1;\n";
7318               pr "    }\n"
7319           | CompareWithString (field, expected) ->
7320               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7321               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7322                 test_name field expected;
7323               pr "               r->%s);\n" field;
7324               pr "      return -1;\n";
7325               pr "    }\n"
7326           | CompareFieldsIntEq (field1, field2) ->
7327               pr "    if (r->%s != r->%s) {\n" field1 field2;
7328               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7329                 test_name field1 field2;
7330               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7331               pr "      return -1;\n";
7332               pr "    }\n"
7333           | CompareFieldsStrEq (field1, field2) ->
7334               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7335               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7336                 test_name field1 field2;
7337               pr "               r->%s, r->%s);\n" field1 field2;
7338               pr "      return -1;\n";
7339               pr "    }\n"
7340         ) checks
7341       in
7342       List.iter (generate_test_command_call test_name) seq;
7343       generate_test_command_call ~test test_name last
7344   | TestLastFail seq ->
7345       pr "  /* TestLastFail for %s (%d) */\n" name i;
7346       let seq, last = get_seq_last seq in
7347       List.iter (generate_test_command_call test_name) seq;
7348       generate_test_command_call test_name ~expect_error:true last
7349
7350 (* Generate the code to run a command, leaving the result in 'r'.
7351  * If you expect to get an error then you should set expect_error:true.
7352  *)
7353 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7354   match cmd with
7355   | [] -> assert false
7356   | name :: args ->
7357       (* Look up the command to find out what args/ret it has. *)
7358       let style =
7359         try
7360           let _, style, _, _, _, _, _ =
7361             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7362           style
7363         with Not_found ->
7364           failwithf "%s: in test, command %s was not found" test_name name in
7365
7366       if List.length (snd style) <> List.length args then
7367         failwithf "%s: in test, wrong number of args given to %s"
7368           test_name name;
7369
7370       pr "  {\n";
7371
7372       List.iter (
7373         function
7374         | OptString n, "NULL" -> ()
7375         | Pathname n, arg
7376         | Device n, arg
7377         | Dev_or_Path n, arg
7378         | String n, arg
7379         | OptString n, arg ->
7380             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7381         | BufferIn n, arg ->
7382             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7383             pr "    size_t %s_size = %d;\n" n (String.length arg)
7384         | Int _, _
7385         | Int64 _, _
7386         | Bool _, _
7387         | FileIn _, _ | FileOut _, _ -> ()
7388         | StringList n, "" | DeviceList n, "" ->
7389             pr "    const char *const %s[1] = { NULL };\n" n
7390         | StringList n, arg | DeviceList n, arg ->
7391             let strs = string_split " " arg in
7392             iteri (
7393               fun i str ->
7394                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7395             ) strs;
7396             pr "    const char *const %s[] = {\n" n;
7397             iteri (
7398               fun i _ -> pr "      %s_%d,\n" n i
7399             ) strs;
7400             pr "      NULL\n";
7401             pr "    };\n";
7402       ) (List.combine (snd style) args);
7403
7404       let error_code =
7405         match fst style with
7406         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7407         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7408         | RConstString _ | RConstOptString _ ->
7409             pr "    const char *r;\n"; "NULL"
7410         | RString _ -> pr "    char *r;\n"; "NULL"
7411         | RStringList _ | RHashtable _ ->
7412             pr "    char **r;\n";
7413             pr "    int i;\n";
7414             "NULL"
7415         | RStruct (_, typ) ->
7416             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7417         | RStructList (_, typ) ->
7418             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7419         | RBufferOut _ ->
7420             pr "    char *r;\n";
7421             pr "    size_t size;\n";
7422             "NULL" in
7423
7424       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7425       pr "    r = guestfs_%s (g" name;
7426
7427       (* Generate the parameters. *)
7428       List.iter (
7429         function
7430         | OptString _, "NULL" -> pr ", NULL"
7431         | Pathname n, _
7432         | Device n, _ | Dev_or_Path n, _
7433         | String n, _
7434         | OptString n, _ ->
7435             pr ", %s" n
7436         | BufferIn n, _ ->
7437             pr ", %s, %s_size" n n
7438         | FileIn _, arg | FileOut _, arg ->
7439             pr ", \"%s\"" (c_quote arg)
7440         | StringList n, _ | DeviceList n, _ ->
7441             pr ", (char **) %s" n
7442         | Int _, arg ->
7443             let i =
7444               try int_of_string arg
7445               with Failure "int_of_string" ->
7446                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7447             pr ", %d" i
7448         | Int64 _, arg ->
7449             let i =
7450               try Int64.of_string arg
7451               with Failure "int_of_string" ->
7452                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7453             pr ", %Ld" i
7454         | Bool _, arg ->
7455             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7456       ) (List.combine (snd style) args);
7457
7458       (match fst style with
7459        | RBufferOut _ -> pr ", &size"
7460        | _ -> ()
7461       );
7462
7463       pr ");\n";
7464
7465       if not expect_error then
7466         pr "    if (r == %s)\n" error_code
7467       else
7468         pr "    if (r != %s)\n" error_code;
7469       pr "      return -1;\n";
7470
7471       (* Insert the test code. *)
7472       (match test with
7473        | None -> ()
7474        | Some f -> f ()
7475       );
7476
7477       (match fst style with
7478        | RErr | RInt _ | RInt64 _ | RBool _
7479        | RConstString _ | RConstOptString _ -> ()
7480        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7481        | RStringList _ | RHashtable _ ->
7482            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7483            pr "      free (r[i]);\n";
7484            pr "    free (r);\n"
7485        | RStruct (_, typ) ->
7486            pr "    guestfs_free_%s (r);\n" typ
7487        | RStructList (_, typ) ->
7488            pr "    guestfs_free_%s_list (r);\n" typ
7489       );
7490
7491       pr "  }\n"
7492
7493 and c_quote str =
7494   let str = replace_str str "\r" "\\r" in
7495   let str = replace_str str "\n" "\\n" in
7496   let str = replace_str str "\t" "\\t" in
7497   let str = replace_str str "\000" "\\0" in
7498   str
7499
7500 (* Generate a lot of different functions for guestfish. *)
7501 and generate_fish_cmds () =
7502   generate_header CStyle GPLv2plus;
7503
7504   let all_functions =
7505     List.filter (
7506       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7507     ) all_functions in
7508   let all_functions_sorted =
7509     List.filter (
7510       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7511     ) all_functions_sorted in
7512
7513   pr "#include <config.h>\n";
7514   pr "\n";
7515   pr "#include <stdio.h>\n";
7516   pr "#include <stdlib.h>\n";
7517   pr "#include <string.h>\n";
7518   pr "#include <inttypes.h>\n";
7519   pr "\n";
7520   pr "#include <guestfs.h>\n";
7521   pr "#include \"c-ctype.h\"\n";
7522   pr "#include \"full-write.h\"\n";
7523   pr "#include \"xstrtol.h\"\n";
7524   pr "#include \"fish.h\"\n";
7525   pr "\n";
7526   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7527   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7528   pr "\n";
7529
7530   (* list_commands function, which implements guestfish -h *)
7531   pr "void list_commands (void)\n";
7532   pr "{\n";
7533   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7534   pr "  list_builtin_commands ();\n";
7535   List.iter (
7536     fun (name, _, _, flags, _, shortdesc, _) ->
7537       let name = replace_char name '_' '-' in
7538       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7539         name shortdesc
7540   ) all_functions_sorted;
7541   pr "  printf (\"    %%s\\n\",";
7542   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7543   pr "}\n";
7544   pr "\n";
7545
7546   (* display_command function, which implements guestfish -h cmd *)
7547   pr "void display_command (const char *cmd)\n";
7548   pr "{\n";
7549   List.iter (
7550     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7551       let name2 = replace_char name '_' '-' in
7552       let alias =
7553         try find_map (function FishAlias n -> Some n | _ -> None) flags
7554         with Not_found -> name in
7555       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7556       let synopsis =
7557         match snd style with
7558         | [] -> name2
7559         | args ->
7560             sprintf "%s %s"
7561               name2 (String.concat " " (List.map name_of_argt args)) in
7562
7563       let warnings =
7564         if List.mem ProtocolLimitWarning flags then
7565           ("\n\n" ^ protocol_limit_warning)
7566         else "" in
7567
7568       (* For DangerWillRobinson commands, we should probably have
7569        * guestfish prompt before allowing you to use them (especially
7570        * in interactive mode). XXX
7571        *)
7572       let warnings =
7573         warnings ^
7574           if List.mem DangerWillRobinson flags then
7575             ("\n\n" ^ danger_will_robinson)
7576           else "" in
7577
7578       let warnings =
7579         warnings ^
7580           match deprecation_notice flags with
7581           | None -> ""
7582           | Some txt -> "\n\n" ^ txt in
7583
7584       let describe_alias =
7585         if name <> alias then
7586           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7587         else "" in
7588
7589       pr "  if (";
7590       pr "STRCASEEQ (cmd, \"%s\")" name;
7591       if name <> name2 then
7592         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7593       if name <> alias then
7594         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7595       pr ")\n";
7596       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7597         name2 shortdesc
7598         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7599          "=head1 DESCRIPTION\n\n" ^
7600          longdesc ^ warnings ^ describe_alias);
7601       pr "  else\n"
7602   ) all_functions;
7603   pr "    display_builtin_command (cmd);\n";
7604   pr "}\n";
7605   pr "\n";
7606
7607   let emit_print_list_function typ =
7608     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7609       typ typ typ;
7610     pr "{\n";
7611     pr "  unsigned int i;\n";
7612     pr "\n";
7613     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7614     pr "    printf (\"[%%d] = {\\n\", i);\n";
7615     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7616     pr "    printf (\"}\\n\");\n";
7617     pr "  }\n";
7618     pr "}\n";
7619     pr "\n";
7620   in
7621
7622   (* print_* functions *)
7623   List.iter (
7624     fun (typ, cols) ->
7625       let needs_i =
7626         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7627
7628       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7629       pr "{\n";
7630       if needs_i then (
7631         pr "  unsigned int i;\n";
7632         pr "\n"
7633       );
7634       List.iter (
7635         function
7636         | name, FString ->
7637             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7638         | name, FUUID ->
7639             pr "  printf (\"%%s%s: \", indent);\n" name;
7640             pr "  for (i = 0; i < 32; ++i)\n";
7641             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7642             pr "  printf (\"\\n\");\n"
7643         | name, FBuffer ->
7644             pr "  printf (\"%%s%s: \", indent);\n" name;
7645             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7646             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7647             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7648             pr "    else\n";
7649             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7650             pr "  printf (\"\\n\");\n"
7651         | name, (FUInt64|FBytes) ->
7652             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7653               name typ name
7654         | name, FInt64 ->
7655             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7656               name typ name
7657         | name, FUInt32 ->
7658             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7659               name typ name
7660         | name, FInt32 ->
7661             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7662               name typ name
7663         | name, FChar ->
7664             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7665               name typ name
7666         | name, FOptPercent ->
7667             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7668               typ name name typ name;
7669             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7670       ) cols;
7671       pr "}\n";
7672       pr "\n";
7673   ) structs;
7674
7675   (* Emit a print_TYPE_list function definition only if that function is used. *)
7676   List.iter (
7677     function
7678     | typ, (RStructListOnly | RStructAndList) ->
7679         (* generate the function for typ *)
7680         emit_print_list_function typ
7681     | typ, _ -> () (* empty *)
7682   ) (rstructs_used_by all_functions);
7683
7684   (* Emit a print_TYPE function definition only if that function is used. *)
7685   List.iter (
7686     function
7687     | typ, (RStructOnly | RStructAndList) ->
7688         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7689         pr "{\n";
7690         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7691         pr "}\n";
7692         pr "\n";
7693     | typ, _ -> () (* empty *)
7694   ) (rstructs_used_by all_functions);
7695
7696   (* run_<action> actions *)
7697   List.iter (
7698     fun (name, style, _, flags, _, _, _) ->
7699       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7700       pr "{\n";
7701       (match fst style with
7702        | RErr
7703        | RInt _
7704        | RBool _ -> pr "  int r;\n"
7705        | RInt64 _ -> pr "  int64_t r;\n"
7706        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7707        | RString _ -> pr "  char *r;\n"
7708        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7709        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7710        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7711        | RBufferOut _ ->
7712            pr "  char *r;\n";
7713            pr "  size_t size;\n";
7714       );
7715       List.iter (
7716         function
7717         | Device n
7718         | String n
7719         | OptString n -> pr "  const char *%s;\n" n
7720         | Pathname n
7721         | Dev_or_Path n
7722         | FileIn n
7723         | FileOut n -> pr "  char *%s;\n" n
7724         | BufferIn n ->
7725             pr "  const char *%s;\n" n;
7726             pr "  size_t %s_size;\n" n
7727         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7728         | Bool n -> pr "  int %s;\n" n
7729         | Int n -> pr "  int %s;\n" n
7730         | Int64 n -> pr "  int64_t %s;\n" n
7731       ) (snd style);
7732
7733       (* Check and convert parameters. *)
7734       let argc_expected = List.length (snd style) in
7735       pr "  if (argc != %d) {\n" argc_expected;
7736       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7737         argc_expected;
7738       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7739       pr "    return -1;\n";
7740       pr "  }\n";
7741
7742       let parse_integer fn fntyp rtyp range name i =
7743         pr "  {\n";
7744         pr "    strtol_error xerr;\n";
7745         pr "    %s r;\n" fntyp;
7746         pr "\n";
7747         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7748         pr "    if (xerr != LONGINT_OK) {\n";
7749         pr "      fprintf (stderr,\n";
7750         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7751         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7752         pr "      return -1;\n";
7753         pr "    }\n";
7754         (match range with
7755          | None -> ()
7756          | Some (min, max, comment) ->
7757              pr "    /* %s */\n" comment;
7758              pr "    if (r < %s || r > %s) {\n" min max;
7759              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7760                name;
7761              pr "      return -1;\n";
7762              pr "    }\n";
7763              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7764         );
7765         pr "    %s = r;\n" name;
7766         pr "  }\n";
7767       in
7768
7769       iteri (
7770         fun i ->
7771           function
7772           | Device name
7773           | String name ->
7774               pr "  %s = argv[%d];\n" name i
7775           | Pathname name
7776           | Dev_or_Path name ->
7777               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7778               pr "  if (%s == NULL) return -1;\n" name
7779           | OptString name ->
7780               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7781                 name i i
7782           | BufferIn name ->
7783               pr "  %s = argv[%d];\n" name i;
7784               pr "  %s_size = strlen (argv[%d]);\n" name i
7785           | FileIn name ->
7786               pr "  %s = file_in (argv[%d]);\n" name i;
7787               pr "  if (%s == NULL) return -1;\n" name
7788           | FileOut name ->
7789               pr "  %s = file_out (argv[%d]);\n" name i;
7790               pr "  if (%s == NULL) return -1;\n" name
7791           | StringList name | DeviceList name ->
7792               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7793               pr "  if (%s == NULL) return -1;\n" name;
7794           | Bool name ->
7795               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7796           | Int name ->
7797               let range =
7798                 let min = "(-(2LL<<30))"
7799                 and max = "((2LL<<30)-1)"
7800                 and comment =
7801                   "The Int type in the generator is a signed 31 bit int." in
7802                 Some (min, max, comment) in
7803               parse_integer "xstrtoll" "long long" "int" range name i
7804           | Int64 name ->
7805               parse_integer "xstrtoll" "long long" "int64_t" None name i
7806       ) (snd style);
7807
7808       (* Call C API function. *)
7809       pr "  r = guestfs_%s " name;
7810       generate_c_call_args ~handle:"g" style;
7811       pr ";\n";
7812
7813       List.iter (
7814         function
7815         | Device name | String name
7816         | OptString name | Bool name
7817         | Int name | Int64 name
7818         | BufferIn name -> ()
7819         | Pathname name | Dev_or_Path name | FileOut name ->
7820             pr "  free (%s);\n" name
7821         | FileIn name ->
7822             pr "  free_file_in (%s);\n" name
7823         | StringList name | DeviceList name ->
7824             pr "  free_strings (%s);\n" name
7825       ) (snd style);
7826
7827       (* Any output flags? *)
7828       let fish_output =
7829         let flags = filter_map (
7830           function FishOutput flag -> Some flag | _ -> None
7831         ) flags in
7832         match flags with
7833         | [] -> None
7834         | [f] -> Some f
7835         | _ ->
7836             failwithf "%s: more than one FishOutput flag is not allowed" name in
7837
7838       (* Check return value for errors and display command results. *)
7839       (match fst style with
7840        | RErr -> pr "  return r;\n"
7841        | RInt _ ->
7842            pr "  if (r == -1) return -1;\n";
7843            (match fish_output with
7844             | None ->
7845                 pr "  printf (\"%%d\\n\", r);\n";
7846             | Some FishOutputOctal ->
7847                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7848             | Some FishOutputHexadecimal ->
7849                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7850            pr "  return 0;\n"
7851        | RInt64 _ ->
7852            pr "  if (r == -1) return -1;\n";
7853            (match fish_output with
7854             | None ->
7855                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7856             | Some FishOutputOctal ->
7857                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7858             | Some FishOutputHexadecimal ->
7859                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7860            pr "  return 0;\n"
7861        | RBool _ ->
7862            pr "  if (r == -1) return -1;\n";
7863            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7864            pr "  return 0;\n"
7865        | RConstString _ ->
7866            pr "  if (r == NULL) return -1;\n";
7867            pr "  printf (\"%%s\\n\", r);\n";
7868            pr "  return 0;\n"
7869        | RConstOptString _ ->
7870            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7871            pr "  return 0;\n"
7872        | RString _ ->
7873            pr "  if (r == NULL) return -1;\n";
7874            pr "  printf (\"%%s\\n\", r);\n";
7875            pr "  free (r);\n";
7876            pr "  return 0;\n"
7877        | RStringList _ ->
7878            pr "  if (r == NULL) return -1;\n";
7879            pr "  print_strings (r);\n";
7880            pr "  free_strings (r);\n";
7881            pr "  return 0;\n"
7882        | RStruct (_, typ) ->
7883            pr "  if (r == NULL) return -1;\n";
7884            pr "  print_%s (r);\n" typ;
7885            pr "  guestfs_free_%s (r);\n" typ;
7886            pr "  return 0;\n"
7887        | RStructList (_, typ) ->
7888            pr "  if (r == NULL) return -1;\n";
7889            pr "  print_%s_list (r);\n" typ;
7890            pr "  guestfs_free_%s_list (r);\n" typ;
7891            pr "  return 0;\n"
7892        | RHashtable _ ->
7893            pr "  if (r == NULL) return -1;\n";
7894            pr "  print_table (r);\n";
7895            pr "  free_strings (r);\n";
7896            pr "  return 0;\n"
7897        | RBufferOut _ ->
7898            pr "  if (r == NULL) return -1;\n";
7899            pr "  if (full_write (1, r, size) != size) {\n";
7900            pr "    perror (\"write\");\n";
7901            pr "    free (r);\n";
7902            pr "    return -1;\n";
7903            pr "  }\n";
7904            pr "  free (r);\n";
7905            pr "  return 0;\n"
7906       );
7907       pr "}\n";
7908       pr "\n"
7909   ) all_functions;
7910
7911   (* run_action function *)
7912   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7913   pr "{\n";
7914   List.iter (
7915     fun (name, _, _, flags, _, _, _) ->
7916       let name2 = replace_char name '_' '-' in
7917       let alias =
7918         try find_map (function FishAlias n -> Some n | _ -> None) flags
7919         with Not_found -> name in
7920       pr "  if (";
7921       pr "STRCASEEQ (cmd, \"%s\")" name;
7922       if name <> name2 then
7923         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7924       if name <> alias then
7925         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7926       pr ")\n";
7927       pr "    return run_%s (cmd, argc, argv);\n" name;
7928       pr "  else\n";
7929   ) all_functions;
7930   pr "    {\n";
7931   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7932   pr "      if (command_num == 1)\n";
7933   pr "        extended_help_message ();\n";
7934   pr "      return -1;\n";
7935   pr "    }\n";
7936   pr "  return 0;\n";
7937   pr "}\n";
7938   pr "\n"
7939
7940 (* Readline completion for guestfish. *)
7941 and generate_fish_completion () =
7942   generate_header CStyle GPLv2plus;
7943
7944   let all_functions =
7945     List.filter (
7946       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7947     ) all_functions in
7948
7949   pr "\
7950 #include <config.h>
7951
7952 #include <stdio.h>
7953 #include <stdlib.h>
7954 #include <string.h>
7955
7956 #ifdef HAVE_LIBREADLINE
7957 #include <readline/readline.h>
7958 #endif
7959
7960 #include \"fish.h\"
7961
7962 #ifdef HAVE_LIBREADLINE
7963
7964 static const char *const commands[] = {
7965   BUILTIN_COMMANDS_FOR_COMPLETION,
7966 ";
7967
7968   (* Get the commands, including the aliases.  They don't need to be
7969    * sorted - the generator() function just does a dumb linear search.
7970    *)
7971   let commands =
7972     List.map (
7973       fun (name, _, _, flags, _, _, _) ->
7974         let name2 = replace_char name '_' '-' in
7975         let alias =
7976           try find_map (function FishAlias n -> Some n | _ -> None) flags
7977           with Not_found -> name in
7978
7979         if name <> alias then [name2; alias] else [name2]
7980     ) all_functions in
7981   let commands = List.flatten commands in
7982
7983   List.iter (pr "  \"%s\",\n") commands;
7984
7985   pr "  NULL
7986 };
7987
7988 static char *
7989 generator (const char *text, int state)
7990 {
7991   static int index, len;
7992   const char *name;
7993
7994   if (!state) {
7995     index = 0;
7996     len = strlen (text);
7997   }
7998
7999   rl_attempted_completion_over = 1;
8000
8001   while ((name = commands[index]) != NULL) {
8002     index++;
8003     if (STRCASEEQLEN (name, text, len))
8004       return strdup (name);
8005   }
8006
8007   return NULL;
8008 }
8009
8010 #endif /* HAVE_LIBREADLINE */
8011
8012 #ifdef HAVE_RL_COMPLETION_MATCHES
8013 #define RL_COMPLETION_MATCHES rl_completion_matches
8014 #else
8015 #ifdef HAVE_COMPLETION_MATCHES
8016 #define RL_COMPLETION_MATCHES completion_matches
8017 #endif
8018 #endif /* else just fail if we don't have either symbol */
8019
8020 char **
8021 do_completion (const char *text, int start, int end)
8022 {
8023   char **matches = NULL;
8024
8025 #ifdef HAVE_LIBREADLINE
8026   rl_completion_append_character = ' ';
8027
8028   if (start == 0)
8029     matches = RL_COMPLETION_MATCHES (text, generator);
8030   else if (complete_dest_paths)
8031     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8032 #endif
8033
8034   return matches;
8035 }
8036 ";
8037
8038 (* Generate the POD documentation for guestfish. *)
8039 and generate_fish_actions_pod () =
8040   let all_functions_sorted =
8041     List.filter (
8042       fun (_, _, _, flags, _, _, _) ->
8043         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8044     ) all_functions_sorted in
8045
8046   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8047
8048   List.iter (
8049     fun (name, style, _, flags, _, _, longdesc) ->
8050       let longdesc =
8051         Str.global_substitute rex (
8052           fun s ->
8053             let sub =
8054               try Str.matched_group 1 s
8055               with Not_found ->
8056                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8057             "C<" ^ replace_char sub '_' '-' ^ ">"
8058         ) longdesc in
8059       let name = replace_char name '_' '-' in
8060       let alias =
8061         try find_map (function FishAlias n -> Some n | _ -> None) flags
8062         with Not_found -> name in
8063
8064       pr "=head2 %s" name;
8065       if name <> alias then
8066         pr " | %s" alias;
8067       pr "\n";
8068       pr "\n";
8069       pr " %s" name;
8070       List.iter (
8071         function
8072         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8073         | OptString n -> pr " %s" n
8074         | StringList n | DeviceList n -> pr " '%s ...'" n
8075         | Bool _ -> pr " true|false"
8076         | Int n -> pr " %s" n
8077         | Int64 n -> pr " %s" n
8078         | FileIn n | FileOut n -> pr " (%s|-)" n
8079         | BufferIn n -> pr " %s" n
8080       ) (snd style);
8081       pr "\n";
8082       pr "\n";
8083       pr "%s\n\n" longdesc;
8084
8085       if List.exists (function FileIn _ | FileOut _ -> true
8086                       | _ -> false) (snd style) then
8087         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8088
8089       if List.mem ProtocolLimitWarning flags then
8090         pr "%s\n\n" protocol_limit_warning;
8091
8092       if List.mem DangerWillRobinson flags then
8093         pr "%s\n\n" danger_will_robinson;
8094
8095       match deprecation_notice flags with
8096       | None -> ()
8097       | Some txt -> pr "%s\n\n" txt
8098   ) all_functions_sorted
8099
8100 (* Generate a C function prototype. *)
8101 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8102     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8103     ?(prefix = "")
8104     ?handle name style =
8105   if extern then pr "extern ";
8106   if static then pr "static ";
8107   (match fst style with
8108    | RErr -> pr "int "
8109    | RInt _ -> pr "int "
8110    | RInt64 _ -> pr "int64_t "
8111    | RBool _ -> pr "int "
8112    | RConstString _ | RConstOptString _ -> pr "const char *"
8113    | RString _ | RBufferOut _ -> pr "char *"
8114    | RStringList _ | RHashtable _ -> pr "char **"
8115    | RStruct (_, typ) ->
8116        if not in_daemon then pr "struct guestfs_%s *" typ
8117        else pr "guestfs_int_%s *" typ
8118    | RStructList (_, typ) ->
8119        if not in_daemon then pr "struct guestfs_%s_list *" typ
8120        else pr "guestfs_int_%s_list *" typ
8121   );
8122   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8123   pr "%s%s (" prefix name;
8124   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8125     pr "void"
8126   else (
8127     let comma = ref false in
8128     (match handle with
8129      | None -> ()
8130      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8131     );
8132     let next () =
8133       if !comma then (
8134         if single_line then pr ", " else pr ",\n\t\t"
8135       );
8136       comma := true
8137     in
8138     List.iter (
8139       function
8140       | Pathname n
8141       | Device n | Dev_or_Path n
8142       | String n
8143       | OptString n ->
8144           next ();
8145           pr "const char *%s" n
8146       | StringList n | DeviceList n ->
8147           next ();
8148           pr "char *const *%s" n
8149       | Bool n -> next (); pr "int %s" n
8150       | Int n -> next (); pr "int %s" n
8151       | Int64 n -> next (); pr "int64_t %s" n
8152       | FileIn n
8153       | FileOut n ->
8154           if not in_daemon then (next (); pr "const char *%s" n)
8155       | BufferIn n ->
8156           next ();
8157           pr "const char *%s" n;
8158           next ();
8159           pr "size_t %s_size" n
8160     ) (snd style);
8161     if is_RBufferOut then (next (); pr "size_t *size_r");
8162   );
8163   pr ")";
8164   if semicolon then pr ";";
8165   if newline then pr "\n"
8166
8167 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8168 and generate_c_call_args ?handle ?(decl = false) style =
8169   pr "(";
8170   let comma = ref false in
8171   let next () =
8172     if !comma then pr ", ";
8173     comma := true
8174   in
8175   (match handle with
8176    | None -> ()
8177    | Some handle -> pr "%s" handle; comma := true
8178   );
8179   List.iter (
8180     function
8181     | BufferIn n ->
8182         next ();
8183         pr "%s, %s_size" n n
8184     | arg ->
8185         next ();
8186         pr "%s" (name_of_argt arg)
8187   ) (snd style);
8188   (* For RBufferOut calls, add implicit &size parameter. *)
8189   if not decl then (
8190     match fst style with
8191     | RBufferOut _ ->
8192         next ();
8193         pr "&size"
8194     | _ -> ()
8195   );
8196   pr ")"
8197
8198 (* Generate the OCaml bindings interface. *)
8199 and generate_ocaml_mli () =
8200   generate_header OCamlStyle LGPLv2plus;
8201
8202   pr "\
8203 (** For API documentation you should refer to the C API
8204     in the guestfs(3) manual page.  The OCaml API uses almost
8205     exactly the same calls. *)
8206
8207 type t
8208 (** A [guestfs_h] handle. *)
8209
8210 exception Error of string
8211 (** This exception is raised when there is an error. *)
8212
8213 exception Handle_closed of string
8214 (** This exception is raised if you use a {!Guestfs.t} handle
8215     after calling {!close} on it.  The string is the name of
8216     the function. *)
8217
8218 val create : unit -> t
8219 (** Create a {!Guestfs.t} handle. *)
8220
8221 val close : t -> unit
8222 (** Close the {!Guestfs.t} handle and free up all resources used
8223     by it immediately.
8224
8225     Handles are closed by the garbage collector when they become
8226     unreferenced, but callers can call this in order to provide
8227     predictable cleanup. *)
8228
8229 ";
8230   generate_ocaml_structure_decls ();
8231
8232   (* The actions. *)
8233   List.iter (
8234     fun (name, style, _, _, _, shortdesc, _) ->
8235       generate_ocaml_prototype name style;
8236       pr "(** %s *)\n" shortdesc;
8237       pr "\n"
8238   ) all_functions_sorted
8239
8240 (* Generate the OCaml bindings implementation. *)
8241 and generate_ocaml_ml () =
8242   generate_header OCamlStyle LGPLv2plus;
8243
8244   pr "\
8245 type t
8246
8247 exception Error of string
8248 exception Handle_closed of string
8249
8250 external create : unit -> t = \"ocaml_guestfs_create\"
8251 external close : t -> unit = \"ocaml_guestfs_close\"
8252
8253 (* Give the exceptions names, so they can be raised from the C code. *)
8254 let () =
8255   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8256   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8257
8258 ";
8259
8260   generate_ocaml_structure_decls ();
8261
8262   (* The actions. *)
8263   List.iter (
8264     fun (name, style, _, _, _, shortdesc, _) ->
8265       generate_ocaml_prototype ~is_external:true name style;
8266   ) all_functions_sorted
8267
8268 (* Generate the OCaml bindings C implementation. *)
8269 and generate_ocaml_c () =
8270   generate_header CStyle LGPLv2plus;
8271
8272   pr "\
8273 #include <stdio.h>
8274 #include <stdlib.h>
8275 #include <string.h>
8276
8277 #include <caml/config.h>
8278 #include <caml/alloc.h>
8279 #include <caml/callback.h>
8280 #include <caml/fail.h>
8281 #include <caml/memory.h>
8282 #include <caml/mlvalues.h>
8283 #include <caml/signals.h>
8284
8285 #include <guestfs.h>
8286
8287 #include \"guestfs_c.h\"
8288
8289 /* Copy a hashtable of string pairs into an assoc-list.  We return
8290  * the list in reverse order, but hashtables aren't supposed to be
8291  * ordered anyway.
8292  */
8293 static CAMLprim value
8294 copy_table (char * const * argv)
8295 {
8296   CAMLparam0 ();
8297   CAMLlocal5 (rv, pairv, kv, vv, cons);
8298   int i;
8299
8300   rv = Val_int (0);
8301   for (i = 0; argv[i] != NULL; i += 2) {
8302     kv = caml_copy_string (argv[i]);
8303     vv = caml_copy_string (argv[i+1]);
8304     pairv = caml_alloc (2, 0);
8305     Store_field (pairv, 0, kv);
8306     Store_field (pairv, 1, vv);
8307     cons = caml_alloc (2, 0);
8308     Store_field (cons, 1, rv);
8309     rv = cons;
8310     Store_field (cons, 0, pairv);
8311   }
8312
8313   CAMLreturn (rv);
8314 }
8315
8316 ";
8317
8318   (* Struct copy functions. *)
8319
8320   let emit_ocaml_copy_list_function typ =
8321     pr "static CAMLprim value\n";
8322     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8323     pr "{\n";
8324     pr "  CAMLparam0 ();\n";
8325     pr "  CAMLlocal2 (rv, v);\n";
8326     pr "  unsigned int i;\n";
8327     pr "\n";
8328     pr "  if (%ss->len == 0)\n" typ;
8329     pr "    CAMLreturn (Atom (0));\n";
8330     pr "  else {\n";
8331     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8332     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8333     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8334     pr "      caml_modify (&Field (rv, i), v);\n";
8335     pr "    }\n";
8336     pr "    CAMLreturn (rv);\n";
8337     pr "  }\n";
8338     pr "}\n";
8339     pr "\n";
8340   in
8341
8342   List.iter (
8343     fun (typ, cols) ->
8344       let has_optpercent_col =
8345         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8346
8347       pr "static CAMLprim value\n";
8348       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8349       pr "{\n";
8350       pr "  CAMLparam0 ();\n";
8351       if has_optpercent_col then
8352         pr "  CAMLlocal3 (rv, v, v2);\n"
8353       else
8354         pr "  CAMLlocal2 (rv, v);\n";
8355       pr "\n";
8356       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8357       iteri (
8358         fun i col ->
8359           (match col with
8360            | name, FString ->
8361                pr "  v = caml_copy_string (%s->%s);\n" typ name
8362            | name, FBuffer ->
8363                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8364                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8365                  typ name typ name
8366            | name, FUUID ->
8367                pr "  v = caml_alloc_string (32);\n";
8368                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8369            | name, (FBytes|FInt64|FUInt64) ->
8370                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8371            | name, (FInt32|FUInt32) ->
8372                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8373            | name, FOptPercent ->
8374                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8375                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8376                pr "    v = caml_alloc (1, 0);\n";
8377                pr "    Store_field (v, 0, v2);\n";
8378                pr "  } else /* None */\n";
8379                pr "    v = Val_int (0);\n";
8380            | name, FChar ->
8381                pr "  v = Val_int (%s->%s);\n" typ name
8382           );
8383           pr "  Store_field (rv, %d, v);\n" i
8384       ) cols;
8385       pr "  CAMLreturn (rv);\n";
8386       pr "}\n";
8387       pr "\n";
8388   ) structs;
8389
8390   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8391   List.iter (
8392     function
8393     | typ, (RStructListOnly | RStructAndList) ->
8394         (* generate the function for typ *)
8395         emit_ocaml_copy_list_function typ
8396     | typ, _ -> () (* empty *)
8397   ) (rstructs_used_by all_functions);
8398
8399   (* The wrappers. *)
8400   List.iter (
8401     fun (name, style, _, _, _, _, _) ->
8402       pr "/* Automatically generated wrapper for function\n";
8403       pr " * ";
8404       generate_ocaml_prototype name style;
8405       pr " */\n";
8406       pr "\n";
8407
8408       let params =
8409         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8410
8411       let needs_extra_vs =
8412         match fst style with RConstOptString _ -> true | _ -> false in
8413
8414       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8415       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8416       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8417       pr "\n";
8418
8419       pr "CAMLprim value\n";
8420       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8421       List.iter (pr ", value %s") (List.tl params);
8422       pr ")\n";
8423       pr "{\n";
8424
8425       (match params with
8426        | [p1; p2; p3; p4; p5] ->
8427            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8428        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8429            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8430            pr "  CAMLxparam%d (%s);\n"
8431              (List.length rest) (String.concat ", " rest)
8432        | ps ->
8433            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8434       );
8435       if not needs_extra_vs then
8436         pr "  CAMLlocal1 (rv);\n"
8437       else
8438         pr "  CAMLlocal3 (rv, v, v2);\n";
8439       pr "\n";
8440
8441       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8442       pr "  if (g == NULL)\n";
8443       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8444       pr "\n";
8445
8446       List.iter (
8447         function
8448         | Pathname n
8449         | Device n | Dev_or_Path n
8450         | String n
8451         | FileIn n
8452         | FileOut n ->
8453             pr "  const char *%s = String_val (%sv);\n" n n
8454         | OptString n ->
8455             pr "  const char *%s =\n" n;
8456             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8457               n n
8458         | BufferIn n ->
8459             pr "  const char *%s = String_val (%sv);\n" n n;
8460             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8461         | StringList n | DeviceList n ->
8462             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8463         | Bool n ->
8464             pr "  int %s = Bool_val (%sv);\n" n n
8465         | Int n ->
8466             pr "  int %s = Int_val (%sv);\n" n n
8467         | Int64 n ->
8468             pr "  int64_t %s = Int64_val (%sv);\n" n n
8469       ) (snd style);
8470       let error_code =
8471         match fst style with
8472         | RErr -> pr "  int r;\n"; "-1"
8473         | RInt _ -> pr "  int r;\n"; "-1"
8474         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8475         | RBool _ -> pr "  int r;\n"; "-1"
8476         | RConstString _ | RConstOptString _ ->
8477             pr "  const char *r;\n"; "NULL"
8478         | RString _ -> pr "  char *r;\n"; "NULL"
8479         | RStringList _ ->
8480             pr "  int i;\n";
8481             pr "  char **r;\n";
8482             "NULL"
8483         | RStruct (_, typ) ->
8484             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8485         | RStructList (_, typ) ->
8486             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8487         | RHashtable _ ->
8488             pr "  int i;\n";
8489             pr "  char **r;\n";
8490             "NULL"
8491         | RBufferOut _ ->
8492             pr "  char *r;\n";
8493             pr "  size_t size;\n";
8494             "NULL" in
8495       pr "\n";
8496
8497       pr "  caml_enter_blocking_section ();\n";
8498       pr "  r = guestfs_%s " name;
8499       generate_c_call_args ~handle:"g" style;
8500       pr ";\n";
8501       pr "  caml_leave_blocking_section ();\n";
8502
8503       List.iter (
8504         function
8505         | StringList n | DeviceList n ->
8506             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8507         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8508         | Bool _ | Int _ | Int64 _
8509         | FileIn _ | FileOut _ | BufferIn _ -> ()
8510       ) (snd style);
8511
8512       pr "  if (r == %s)\n" error_code;
8513       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8514       pr "\n";
8515
8516       (match fst style with
8517        | RErr -> pr "  rv = Val_unit;\n"
8518        | RInt _ -> pr "  rv = Val_int (r);\n"
8519        | RInt64 _ ->
8520            pr "  rv = caml_copy_int64 (r);\n"
8521        | RBool _ -> pr "  rv = Val_bool (r);\n"
8522        | RConstString _ ->
8523            pr "  rv = caml_copy_string (r);\n"
8524        | RConstOptString _ ->
8525            pr "  if (r) { /* Some string */\n";
8526            pr "    v = caml_alloc (1, 0);\n";
8527            pr "    v2 = caml_copy_string (r);\n";
8528            pr "    Store_field (v, 0, v2);\n";
8529            pr "  } else /* None */\n";
8530            pr "    v = Val_int (0);\n";
8531        | RString _ ->
8532            pr "  rv = caml_copy_string (r);\n";
8533            pr "  free (r);\n"
8534        | RStringList _ ->
8535            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8536            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8537            pr "  free (r);\n"
8538        | RStruct (_, typ) ->
8539            pr "  rv = copy_%s (r);\n" typ;
8540            pr "  guestfs_free_%s (r);\n" typ;
8541        | RStructList (_, typ) ->
8542            pr "  rv = copy_%s_list (r);\n" typ;
8543            pr "  guestfs_free_%s_list (r);\n" typ;
8544        | RHashtable _ ->
8545            pr "  rv = copy_table (r);\n";
8546            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8547            pr "  free (r);\n";
8548        | RBufferOut _ ->
8549            pr "  rv = caml_alloc_string (size);\n";
8550            pr "  memcpy (String_val (rv), r, size);\n";
8551       );
8552
8553       pr "  CAMLreturn (rv);\n";
8554       pr "}\n";
8555       pr "\n";
8556
8557       if List.length params > 5 then (
8558         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8559         pr "CAMLprim value ";
8560         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8561         pr "CAMLprim value\n";
8562         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8563         pr "{\n";
8564         pr "  return ocaml_guestfs_%s (argv[0]" name;
8565         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8566         pr ");\n";
8567         pr "}\n";
8568         pr "\n"
8569       )
8570   ) all_functions_sorted
8571
8572 and generate_ocaml_structure_decls () =
8573   List.iter (
8574     fun (typ, cols) ->
8575       pr "type %s = {\n" typ;
8576       List.iter (
8577         function
8578         | name, FString -> pr "  %s : string;\n" name
8579         | name, FBuffer -> pr "  %s : string;\n" name
8580         | name, FUUID -> pr "  %s : string;\n" name
8581         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8582         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8583         | name, FChar -> pr "  %s : char;\n" name
8584         | name, FOptPercent -> pr "  %s : float option;\n" name
8585       ) cols;
8586       pr "}\n";
8587       pr "\n"
8588   ) structs
8589
8590 and generate_ocaml_prototype ?(is_external = false) name style =
8591   if is_external then pr "external " else pr "val ";
8592   pr "%s : t -> " name;
8593   List.iter (
8594     function
8595     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8596     | BufferIn _ -> pr "string -> "
8597     | OptString _ -> pr "string option -> "
8598     | StringList _ | DeviceList _ -> pr "string array -> "
8599     | Bool _ -> pr "bool -> "
8600     | Int _ -> pr "int -> "
8601     | Int64 _ -> pr "int64 -> "
8602   ) (snd style);
8603   (match fst style with
8604    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8605    | RInt _ -> pr "int"
8606    | RInt64 _ -> pr "int64"
8607    | RBool _ -> pr "bool"
8608    | RConstString _ -> pr "string"
8609    | RConstOptString _ -> pr "string option"
8610    | RString _ | RBufferOut _ -> pr "string"
8611    | RStringList _ -> pr "string array"
8612    | RStruct (_, typ) -> pr "%s" typ
8613    | RStructList (_, typ) -> pr "%s array" typ
8614    | RHashtable _ -> pr "(string * string) list"
8615   );
8616   if is_external then (
8617     pr " = ";
8618     if List.length (snd style) + 1 > 5 then
8619       pr "\"ocaml_guestfs_%s_byte\" " name;
8620     pr "\"ocaml_guestfs_%s\"" name
8621   );
8622   pr "\n"
8623
8624 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8625 and generate_perl_xs () =
8626   generate_header CStyle LGPLv2plus;
8627
8628   pr "\
8629 #include \"EXTERN.h\"
8630 #include \"perl.h\"
8631 #include \"XSUB.h\"
8632
8633 #include <guestfs.h>
8634
8635 #ifndef PRId64
8636 #define PRId64 \"lld\"
8637 #endif
8638
8639 static SV *
8640 my_newSVll(long long val) {
8641 #ifdef USE_64_BIT_ALL
8642   return newSViv(val);
8643 #else
8644   char buf[100];
8645   int len;
8646   len = snprintf(buf, 100, \"%%\" PRId64, val);
8647   return newSVpv(buf, len);
8648 #endif
8649 }
8650
8651 #ifndef PRIu64
8652 #define PRIu64 \"llu\"
8653 #endif
8654
8655 static SV *
8656 my_newSVull(unsigned long long val) {
8657 #ifdef USE_64_BIT_ALL
8658   return newSVuv(val);
8659 #else
8660   char buf[100];
8661   int len;
8662   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8663   return newSVpv(buf, len);
8664 #endif
8665 }
8666
8667 /* http://www.perlmonks.org/?node_id=680842 */
8668 static char **
8669 XS_unpack_charPtrPtr (SV *arg) {
8670   char **ret;
8671   AV *av;
8672   I32 i;
8673
8674   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8675     croak (\"array reference expected\");
8676
8677   av = (AV *)SvRV (arg);
8678   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8679   if (!ret)
8680     croak (\"malloc failed\");
8681
8682   for (i = 0; i <= av_len (av); i++) {
8683     SV **elem = av_fetch (av, i, 0);
8684
8685     if (!elem || !*elem)
8686       croak (\"missing element in list\");
8687
8688     ret[i] = SvPV_nolen (*elem);
8689   }
8690
8691   ret[i] = NULL;
8692
8693   return ret;
8694 }
8695
8696 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8697
8698 PROTOTYPES: ENABLE
8699
8700 guestfs_h *
8701 _create ()
8702    CODE:
8703       RETVAL = guestfs_create ();
8704       if (!RETVAL)
8705         croak (\"could not create guestfs handle\");
8706       guestfs_set_error_handler (RETVAL, NULL, NULL);
8707  OUTPUT:
8708       RETVAL
8709
8710 void
8711 DESTROY (g)
8712       guestfs_h *g;
8713  PPCODE:
8714       guestfs_close (g);
8715
8716 ";
8717
8718   List.iter (
8719     fun (name, style, _, _, _, _, _) ->
8720       (match fst style with
8721        | RErr -> pr "void\n"
8722        | RInt _ -> pr "SV *\n"
8723        | RInt64 _ -> pr "SV *\n"
8724        | RBool _ -> pr "SV *\n"
8725        | RConstString _ -> pr "SV *\n"
8726        | RConstOptString _ -> pr "SV *\n"
8727        | RString _ -> pr "SV *\n"
8728        | RBufferOut _ -> pr "SV *\n"
8729        | RStringList _
8730        | RStruct _ | RStructList _
8731        | RHashtable _ ->
8732            pr "void\n" (* all lists returned implictly on the stack *)
8733       );
8734       (* Call and arguments. *)
8735       pr "%s (g" name;
8736       List.iter (
8737         fun arg -> pr ", %s" (name_of_argt arg)
8738       ) (snd style);
8739       pr ")\n";
8740       pr "      guestfs_h *g;\n";
8741       iteri (
8742         fun i ->
8743           function
8744           | Pathname n | Device n | Dev_or_Path n | String n
8745           | FileIn n | FileOut n ->
8746               pr "      char *%s;\n" n
8747           | BufferIn n ->
8748               pr "      char *%s;\n" n;
8749               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8750           | OptString n ->
8751               (* http://www.perlmonks.org/?node_id=554277
8752                * Note that the implicit handle argument means we have
8753                * to add 1 to the ST(x) operator.
8754                *)
8755               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8756           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8757           | Bool n -> pr "      int %s;\n" n
8758           | Int n -> pr "      int %s;\n" n
8759           | Int64 n -> pr "      int64_t %s;\n" n
8760       ) (snd style);
8761
8762       let do_cleanups () =
8763         List.iter (
8764           function
8765           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8766           | Bool _ | Int _ | Int64 _
8767           | FileIn _ | FileOut _
8768           | BufferIn _ -> ()
8769           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8770         ) (snd style)
8771       in
8772
8773       (* Code. *)
8774       (match fst style with
8775        | RErr ->
8776            pr "PREINIT:\n";
8777            pr "      int r;\n";
8778            pr " PPCODE:\n";
8779            pr "      r = guestfs_%s " name;
8780            generate_c_call_args ~handle:"g" style;
8781            pr ";\n";
8782            do_cleanups ();
8783            pr "      if (r == -1)\n";
8784            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8785        | RInt n
8786        | RBool n ->
8787            pr "PREINIT:\n";
8788            pr "      int %s;\n" n;
8789            pr "   CODE:\n";
8790            pr "      %s = guestfs_%s " n name;
8791            generate_c_call_args ~handle:"g" style;
8792            pr ";\n";
8793            do_cleanups ();
8794            pr "      if (%s == -1)\n" n;
8795            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8796            pr "      RETVAL = newSViv (%s);\n" n;
8797            pr " OUTPUT:\n";
8798            pr "      RETVAL\n"
8799        | RInt64 n ->
8800            pr "PREINIT:\n";
8801            pr "      int64_t %s;\n" n;
8802            pr "   CODE:\n";
8803            pr "      %s = guestfs_%s " n name;
8804            generate_c_call_args ~handle:"g" style;
8805            pr ";\n";
8806            do_cleanups ();
8807            pr "      if (%s == -1)\n" n;
8808            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8809            pr "      RETVAL = my_newSVll (%s);\n" n;
8810            pr " OUTPUT:\n";
8811            pr "      RETVAL\n"
8812        | RConstString n ->
8813            pr "PREINIT:\n";
8814            pr "      const char *%s;\n" n;
8815            pr "   CODE:\n";
8816            pr "      %s = guestfs_%s " n name;
8817            generate_c_call_args ~handle:"g" style;
8818            pr ";\n";
8819            do_cleanups ();
8820            pr "      if (%s == NULL)\n" n;
8821            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8822            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8823            pr " OUTPUT:\n";
8824            pr "      RETVAL\n"
8825        | RConstOptString n ->
8826            pr "PREINIT:\n";
8827            pr "      const char *%s;\n" n;
8828            pr "   CODE:\n";
8829            pr "      %s = guestfs_%s " n name;
8830            generate_c_call_args ~handle:"g" style;
8831            pr ";\n";
8832            do_cleanups ();
8833            pr "      if (%s == NULL)\n" n;
8834            pr "        RETVAL = &PL_sv_undef;\n";
8835            pr "      else\n";
8836            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8837            pr " OUTPUT:\n";
8838            pr "      RETVAL\n"
8839        | RString n ->
8840            pr "PREINIT:\n";
8841            pr "      char *%s;\n" n;
8842            pr "   CODE:\n";
8843            pr "      %s = guestfs_%s " n name;
8844            generate_c_call_args ~handle:"g" style;
8845            pr ";\n";
8846            do_cleanups ();
8847            pr "      if (%s == NULL)\n" n;
8848            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8849            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8850            pr "      free (%s);\n" n;
8851            pr " OUTPUT:\n";
8852            pr "      RETVAL\n"
8853        | RStringList n | RHashtable n ->
8854            pr "PREINIT:\n";
8855            pr "      char **%s;\n" n;
8856            pr "      int i, n;\n";
8857            pr " PPCODE:\n";
8858            pr "      %s = guestfs_%s " n name;
8859            generate_c_call_args ~handle:"g" style;
8860            pr ";\n";
8861            do_cleanups ();
8862            pr "      if (%s == NULL)\n" n;
8863            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8864            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8865            pr "      EXTEND (SP, n);\n";
8866            pr "      for (i = 0; i < n; ++i) {\n";
8867            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8868            pr "        free (%s[i]);\n" n;
8869            pr "      }\n";
8870            pr "      free (%s);\n" n;
8871        | RStruct (n, typ) ->
8872            let cols = cols_of_struct typ in
8873            generate_perl_struct_code typ cols name style n do_cleanups
8874        | RStructList (n, typ) ->
8875            let cols = cols_of_struct typ in
8876            generate_perl_struct_list_code typ cols name style n do_cleanups
8877        | RBufferOut n ->
8878            pr "PREINIT:\n";
8879            pr "      char *%s;\n" n;
8880            pr "      size_t size;\n";
8881            pr "   CODE:\n";
8882            pr "      %s = guestfs_%s " n name;
8883            generate_c_call_args ~handle:"g" style;
8884            pr ";\n";
8885            do_cleanups ();
8886            pr "      if (%s == NULL)\n" n;
8887            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8888            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8889            pr "      free (%s);\n" n;
8890            pr " OUTPUT:\n";
8891            pr "      RETVAL\n"
8892       );
8893
8894       pr "\n"
8895   ) all_functions
8896
8897 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8898   pr "PREINIT:\n";
8899   pr "      struct guestfs_%s_list *%s;\n" typ n;
8900   pr "      int i;\n";
8901   pr "      HV *hv;\n";
8902   pr " PPCODE:\n";
8903   pr "      %s = guestfs_%s " n name;
8904   generate_c_call_args ~handle:"g" style;
8905   pr ";\n";
8906   do_cleanups ();
8907   pr "      if (%s == NULL)\n" n;
8908   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8909   pr "      EXTEND (SP, %s->len);\n" n;
8910   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8911   pr "        hv = newHV ();\n";
8912   List.iter (
8913     function
8914     | name, FString ->
8915         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8916           name (String.length name) n name
8917     | name, FUUID ->
8918         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8919           name (String.length name) n name
8920     | name, FBuffer ->
8921         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8922           name (String.length name) n name n name
8923     | name, (FBytes|FUInt64) ->
8924         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8925           name (String.length name) n name
8926     | name, FInt64 ->
8927         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8928           name (String.length name) n name
8929     | name, (FInt32|FUInt32) ->
8930         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8931           name (String.length name) n name
8932     | name, FChar ->
8933         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8934           name (String.length name) n name
8935     | name, FOptPercent ->
8936         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8937           name (String.length name) n name
8938   ) cols;
8939   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8940   pr "      }\n";
8941   pr "      guestfs_free_%s_list (%s);\n" typ n
8942
8943 and generate_perl_struct_code typ cols name style n do_cleanups =
8944   pr "PREINIT:\n";
8945   pr "      struct guestfs_%s *%s;\n" typ n;
8946   pr " PPCODE:\n";
8947   pr "      %s = guestfs_%s " n name;
8948   generate_c_call_args ~handle:"g" style;
8949   pr ";\n";
8950   do_cleanups ();
8951   pr "      if (%s == NULL)\n" n;
8952   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8953   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8954   List.iter (
8955     fun ((name, _) as col) ->
8956       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8957
8958       match col with
8959       | name, FString ->
8960           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8961             n name
8962       | name, FBuffer ->
8963           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8964             n name n name
8965       | name, FUUID ->
8966           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8967             n name
8968       | name, (FBytes|FUInt64) ->
8969           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8970             n name
8971       | name, FInt64 ->
8972           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8973             n name
8974       | name, (FInt32|FUInt32) ->
8975           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8976             n name
8977       | name, FChar ->
8978           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8979             n name
8980       | name, FOptPercent ->
8981           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8982             n name
8983   ) cols;
8984   pr "      free (%s);\n" n
8985
8986 (* Generate Sys/Guestfs.pm. *)
8987 and generate_perl_pm () =
8988   generate_header HashStyle LGPLv2plus;
8989
8990   pr "\
8991 =pod
8992
8993 =head1 NAME
8994
8995 Sys::Guestfs - Perl bindings for libguestfs
8996
8997 =head1 SYNOPSIS
8998
8999  use Sys::Guestfs;
9000
9001  my $h = Sys::Guestfs->new ();
9002  $h->add_drive ('guest.img');
9003  $h->launch ();
9004  $h->mount ('/dev/sda1', '/');
9005  $h->touch ('/hello');
9006  $h->sync ();
9007
9008 =head1 DESCRIPTION
9009
9010 The C<Sys::Guestfs> module provides a Perl XS binding to the
9011 libguestfs API for examining and modifying virtual machine
9012 disk images.
9013
9014 Amongst the things this is good for: making batch configuration
9015 changes to guests, getting disk used/free statistics (see also:
9016 virt-df), migrating between virtualization systems (see also:
9017 virt-p2v), performing partial backups, performing partial guest
9018 clones, cloning guests and changing registry/UUID/hostname info, and
9019 much else besides.
9020
9021 Libguestfs uses Linux kernel and qemu code, and can access any type of
9022 guest filesystem that Linux and qemu can, including but not limited
9023 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9024 schemes, qcow, qcow2, vmdk.
9025
9026 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9027 LVs, what filesystem is in each LV, etc.).  It can also run commands
9028 in the context of the guest.  Also you can access filesystems over
9029 FUSE.
9030
9031 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9032 functions for using libguestfs from Perl, including integration
9033 with libvirt.
9034
9035 =head1 ERRORS
9036
9037 All errors turn into calls to C<croak> (see L<Carp(3)>).
9038
9039 =head1 METHODS
9040
9041 =over 4
9042
9043 =cut
9044
9045 package Sys::Guestfs;
9046
9047 use strict;
9048 use warnings;
9049
9050 # This version number changes whenever a new function
9051 # is added to the libguestfs API.  It is not directly
9052 # related to the libguestfs version number.
9053 use vars qw($VERSION);
9054 $VERSION = '0.%d';
9055
9056 require XSLoader;
9057 XSLoader::load ('Sys::Guestfs');
9058
9059 =item $h = Sys::Guestfs->new ();
9060
9061 Create a new guestfs handle.
9062
9063 =cut
9064
9065 sub new {
9066   my $proto = shift;
9067   my $class = ref ($proto) || $proto;
9068
9069   my $self = Sys::Guestfs::_create ();
9070   bless $self, $class;
9071   return $self;
9072 }
9073
9074 " max_proc_nr;
9075
9076   (* Actions.  We only need to print documentation for these as
9077    * they are pulled in from the XS code automatically.
9078    *)
9079   List.iter (
9080     fun (name, style, _, flags, _, _, longdesc) ->
9081       if not (List.mem NotInDocs flags) then (
9082         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9083         pr "=item ";
9084         generate_perl_prototype name style;
9085         pr "\n\n";
9086         pr "%s\n\n" longdesc;
9087         if List.mem ProtocolLimitWarning flags then
9088           pr "%s\n\n" protocol_limit_warning;
9089         if List.mem DangerWillRobinson flags then
9090           pr "%s\n\n" danger_will_robinson;
9091         match deprecation_notice flags with
9092         | None -> ()
9093         | Some txt -> pr "%s\n\n" txt
9094       )
9095   ) all_functions_sorted;
9096
9097   (* End of file. *)
9098   pr "\
9099 =cut
9100
9101 1;
9102
9103 =back
9104
9105 =head1 COPYRIGHT
9106
9107 Copyright (C) %s Red Hat Inc.
9108
9109 =head1 LICENSE
9110
9111 Please see the file COPYING.LIB for the full license.
9112
9113 =head1 SEE ALSO
9114
9115 L<guestfs(3)>,
9116 L<guestfish(1)>,
9117 L<http://libguestfs.org>,
9118 L<Sys::Guestfs::Lib(3)>.
9119
9120 =cut
9121 " copyright_years
9122
9123 and generate_perl_prototype name style =
9124   (match fst style with
9125    | RErr -> ()
9126    | RBool n
9127    | RInt n
9128    | RInt64 n
9129    | RConstString n
9130    | RConstOptString n
9131    | RString n
9132    | RBufferOut n -> pr "$%s = " n
9133    | RStruct (n,_)
9134    | RHashtable n -> pr "%%%s = " n
9135    | RStringList n
9136    | RStructList (n,_) -> pr "@%s = " n
9137   );
9138   pr "$h->%s (" name;
9139   let comma = ref false in
9140   List.iter (
9141     fun arg ->
9142       if !comma then pr ", ";
9143       comma := true;
9144       match arg with
9145       | Pathname n | Device n | Dev_or_Path n | String n
9146       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9147       | BufferIn n ->
9148           pr "$%s" n
9149       | StringList n | DeviceList n ->
9150           pr "\\@%s" n
9151   ) (snd style);
9152   pr ");"
9153
9154 (* Generate Python C module. *)
9155 and generate_python_c () =
9156   generate_header CStyle LGPLv2plus;
9157
9158   pr "\
9159 #define PY_SSIZE_T_CLEAN 1
9160 #include <Python.h>
9161
9162 #if PY_VERSION_HEX < 0x02050000
9163 typedef int Py_ssize_t;
9164 #define PY_SSIZE_T_MAX INT_MAX
9165 #define PY_SSIZE_T_MIN INT_MIN
9166 #endif
9167
9168 #include <stdio.h>
9169 #include <stdlib.h>
9170 #include <assert.h>
9171
9172 #include \"guestfs.h\"
9173
9174 typedef struct {
9175   PyObject_HEAD
9176   guestfs_h *g;
9177 } Pyguestfs_Object;
9178
9179 static guestfs_h *
9180 get_handle (PyObject *obj)
9181 {
9182   assert (obj);
9183   assert (obj != Py_None);
9184   return ((Pyguestfs_Object *) obj)->g;
9185 }
9186
9187 static PyObject *
9188 put_handle (guestfs_h *g)
9189 {
9190   assert (g);
9191   return
9192     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9193 }
9194
9195 /* This list should be freed (but not the strings) after use. */
9196 static char **
9197 get_string_list (PyObject *obj)
9198 {
9199   int i, len;
9200   char **r;
9201
9202   assert (obj);
9203
9204   if (!PyList_Check (obj)) {
9205     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9206     return NULL;
9207   }
9208
9209   len = PyList_Size (obj);
9210   r = malloc (sizeof (char *) * (len+1));
9211   if (r == NULL) {
9212     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9213     return NULL;
9214   }
9215
9216   for (i = 0; i < len; ++i)
9217     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9218   r[len] = NULL;
9219
9220   return r;
9221 }
9222
9223 static PyObject *
9224 put_string_list (char * const * const argv)
9225 {
9226   PyObject *list;
9227   int argc, i;
9228
9229   for (argc = 0; argv[argc] != NULL; ++argc)
9230     ;
9231
9232   list = PyList_New (argc);
9233   for (i = 0; i < argc; ++i)
9234     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9235
9236   return list;
9237 }
9238
9239 static PyObject *
9240 put_table (char * const * const argv)
9241 {
9242   PyObject *list, *item;
9243   int argc, i;
9244
9245   for (argc = 0; argv[argc] != NULL; ++argc)
9246     ;
9247
9248   list = PyList_New (argc >> 1);
9249   for (i = 0; i < argc; i += 2) {
9250     item = PyTuple_New (2);
9251     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9252     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9253     PyList_SetItem (list, i >> 1, item);
9254   }
9255
9256   return list;
9257 }
9258
9259 static void
9260 free_strings (char **argv)
9261 {
9262   int argc;
9263
9264   for (argc = 0; argv[argc] != NULL; ++argc)
9265     free (argv[argc]);
9266   free (argv);
9267 }
9268
9269 static PyObject *
9270 py_guestfs_create (PyObject *self, PyObject *args)
9271 {
9272   guestfs_h *g;
9273
9274   g = guestfs_create ();
9275   if (g == NULL) {
9276     PyErr_SetString (PyExc_RuntimeError,
9277                      \"guestfs.create: failed to allocate handle\");
9278     return NULL;
9279   }
9280   guestfs_set_error_handler (g, NULL, NULL);
9281   return put_handle (g);
9282 }
9283
9284 static PyObject *
9285 py_guestfs_close (PyObject *self, PyObject *args)
9286 {
9287   PyObject *py_g;
9288   guestfs_h *g;
9289
9290   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9291     return NULL;
9292   g = get_handle (py_g);
9293
9294   guestfs_close (g);
9295
9296   Py_INCREF (Py_None);
9297   return Py_None;
9298 }
9299
9300 ";
9301
9302   let emit_put_list_function typ =
9303     pr "static PyObject *\n";
9304     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9305     pr "{\n";
9306     pr "  PyObject *list;\n";
9307     pr "  int i;\n";
9308     pr "\n";
9309     pr "  list = PyList_New (%ss->len);\n" typ;
9310     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9311     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9312     pr "  return list;\n";
9313     pr "};\n";
9314     pr "\n"
9315   in
9316
9317   (* Structures, turned into Python dictionaries. *)
9318   List.iter (
9319     fun (typ, cols) ->
9320       pr "static PyObject *\n";
9321       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9322       pr "{\n";
9323       pr "  PyObject *dict;\n";
9324       pr "\n";
9325       pr "  dict = PyDict_New ();\n";
9326       List.iter (
9327         function
9328         | name, FString ->
9329             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9330             pr "                        PyString_FromString (%s->%s));\n"
9331               typ name
9332         | name, FBuffer ->
9333             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9334             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9335               typ name typ name
9336         | name, FUUID ->
9337             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9338             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9339               typ name
9340         | name, (FBytes|FUInt64) ->
9341             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9342             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9343               typ name
9344         | name, FInt64 ->
9345             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9346             pr "                        PyLong_FromLongLong (%s->%s));\n"
9347               typ name
9348         | name, FUInt32 ->
9349             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9350             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9351               typ name
9352         | name, FInt32 ->
9353             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9354             pr "                        PyLong_FromLong (%s->%s));\n"
9355               typ name
9356         | name, FOptPercent ->
9357             pr "  if (%s->%s >= 0)\n" typ name;
9358             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9359             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9360               typ name;
9361             pr "  else {\n";
9362             pr "    Py_INCREF (Py_None);\n";
9363             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9364             pr "  }\n"
9365         | name, FChar ->
9366             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9367             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9368       ) cols;
9369       pr "  return dict;\n";
9370       pr "};\n";
9371       pr "\n";
9372
9373   ) structs;
9374
9375   (* Emit a put_TYPE_list function definition only if that function is used. *)
9376   List.iter (
9377     function
9378     | typ, (RStructListOnly | RStructAndList) ->
9379         (* generate the function for typ *)
9380         emit_put_list_function typ
9381     | typ, _ -> () (* empty *)
9382   ) (rstructs_used_by all_functions);
9383
9384   (* Python wrapper functions. *)
9385   List.iter (
9386     fun (name, style, _, _, _, _, _) ->
9387       pr "static PyObject *\n";
9388       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9389       pr "{\n";
9390
9391       pr "  PyObject *py_g;\n";
9392       pr "  guestfs_h *g;\n";
9393       pr "  PyObject *py_r;\n";
9394
9395       let error_code =
9396         match fst style with
9397         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9398         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9399         | RConstString _ | RConstOptString _ ->
9400             pr "  const char *r;\n"; "NULL"
9401         | RString _ -> pr "  char *r;\n"; "NULL"
9402         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9403         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9404         | RStructList (_, typ) ->
9405             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9406         | RBufferOut _ ->
9407             pr "  char *r;\n";
9408             pr "  size_t size;\n";
9409             "NULL" in
9410
9411       List.iter (
9412         function
9413         | Pathname n | Device n | Dev_or_Path n | String n
9414         | FileIn n | FileOut n ->
9415             pr "  const char *%s;\n" n
9416         | OptString n -> pr "  const char *%s;\n" n
9417         | BufferIn n ->
9418             pr "  const char *%s;\n" n;
9419             pr "  Py_ssize_t %s_size;\n" n
9420         | StringList n | DeviceList n ->
9421             pr "  PyObject *py_%s;\n" n;
9422             pr "  char **%s;\n" n
9423         | Bool n -> pr "  int %s;\n" n
9424         | Int n -> pr "  int %s;\n" n
9425         | Int64 n -> pr "  long long %s;\n" n
9426       ) (snd style);
9427
9428       pr "\n";
9429
9430       (* Convert the parameters. *)
9431       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9432       List.iter (
9433         function
9434         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9435         | OptString _ -> pr "z"
9436         | StringList _ | DeviceList _ -> pr "O"
9437         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9438         | Int _ -> pr "i"
9439         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9440                              * emulate C's int/long/long long in Python?
9441                              *)
9442         | BufferIn _ -> pr "s#"
9443       ) (snd style);
9444       pr ":guestfs_%s\",\n" name;
9445       pr "                         &py_g";
9446       List.iter (
9447         function
9448         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9449         | OptString n -> pr ", &%s" n
9450         | StringList n | DeviceList n -> pr ", &py_%s" n
9451         | Bool n -> pr ", &%s" n
9452         | Int n -> pr ", &%s" n
9453         | Int64 n -> pr ", &%s" n
9454         | BufferIn n -> pr ", &%s, &%s_size" n n
9455       ) (snd style);
9456
9457       pr "))\n";
9458       pr "    return NULL;\n";
9459
9460       pr "  g = get_handle (py_g);\n";
9461       List.iter (
9462         function
9463         | Pathname _ | Device _ | Dev_or_Path _ | String _
9464         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9465         | BufferIn _ -> ()
9466         | StringList n | DeviceList n ->
9467             pr "  %s = get_string_list (py_%s);\n" n n;
9468             pr "  if (!%s) return NULL;\n" n
9469       ) (snd style);
9470
9471       pr "\n";
9472
9473       pr "  r = guestfs_%s " name;
9474       generate_c_call_args ~handle:"g" style;
9475       pr ";\n";
9476
9477       List.iter (
9478         function
9479         | Pathname _ | Device _ | Dev_or_Path _ | String _
9480         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9481         | BufferIn _ -> ()
9482         | StringList n | DeviceList n ->
9483             pr "  free (%s);\n" n
9484       ) (snd style);
9485
9486       pr "  if (r == %s) {\n" error_code;
9487       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9488       pr "    return NULL;\n";
9489       pr "  }\n";
9490       pr "\n";
9491
9492       (match fst style with
9493        | RErr ->
9494            pr "  Py_INCREF (Py_None);\n";
9495            pr "  py_r = Py_None;\n"
9496        | RInt _
9497        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9498        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9499        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9500        | RConstOptString _ ->
9501            pr "  if (r)\n";
9502            pr "    py_r = PyString_FromString (r);\n";
9503            pr "  else {\n";
9504            pr "    Py_INCREF (Py_None);\n";
9505            pr "    py_r = Py_None;\n";
9506            pr "  }\n"
9507        | RString _ ->
9508            pr "  py_r = PyString_FromString (r);\n";
9509            pr "  free (r);\n"
9510        | RStringList _ ->
9511            pr "  py_r = put_string_list (r);\n";
9512            pr "  free_strings (r);\n"
9513        | RStruct (_, typ) ->
9514            pr "  py_r = put_%s (r);\n" typ;
9515            pr "  guestfs_free_%s (r);\n" typ
9516        | RStructList (_, typ) ->
9517            pr "  py_r = put_%s_list (r);\n" typ;
9518            pr "  guestfs_free_%s_list (r);\n" typ
9519        | RHashtable n ->
9520            pr "  py_r = put_table (r);\n";
9521            pr "  free_strings (r);\n"
9522        | RBufferOut _ ->
9523            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9524            pr "  free (r);\n"
9525       );
9526
9527       pr "  return py_r;\n";
9528       pr "}\n";
9529       pr "\n"
9530   ) all_functions;
9531
9532   (* Table of functions. *)
9533   pr "static PyMethodDef methods[] = {\n";
9534   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9535   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9536   List.iter (
9537     fun (name, _, _, _, _, _, _) ->
9538       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9539         name name
9540   ) all_functions;
9541   pr "  { NULL, NULL, 0, NULL }\n";
9542   pr "};\n";
9543   pr "\n";
9544
9545   (* Init function. *)
9546   pr "\
9547 void
9548 initlibguestfsmod (void)
9549 {
9550   static int initialized = 0;
9551
9552   if (initialized) return;
9553   Py_InitModule ((char *) \"libguestfsmod\", methods);
9554   initialized = 1;
9555 }
9556 "
9557
9558 (* Generate Python module. *)
9559 and generate_python_py () =
9560   generate_header HashStyle LGPLv2plus;
9561
9562   pr "\
9563 u\"\"\"Python bindings for libguestfs
9564
9565 import guestfs
9566 g = guestfs.GuestFS ()
9567 g.add_drive (\"guest.img\")
9568 g.launch ()
9569 parts = g.list_partitions ()
9570
9571 The guestfs module provides a Python binding to the libguestfs API
9572 for examining and modifying virtual machine disk images.
9573
9574 Amongst the things this is good for: making batch configuration
9575 changes to guests, getting disk used/free statistics (see also:
9576 virt-df), migrating between virtualization systems (see also:
9577 virt-p2v), performing partial backups, performing partial guest
9578 clones, cloning guests and changing registry/UUID/hostname info, and
9579 much else besides.
9580
9581 Libguestfs uses Linux kernel and qemu code, and can access any type of
9582 guest filesystem that Linux and qemu can, including but not limited
9583 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9584 schemes, qcow, qcow2, vmdk.
9585
9586 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9587 LVs, what filesystem is in each LV, etc.).  It can also run commands
9588 in the context of the guest.  Also you can access filesystems over
9589 FUSE.
9590
9591 Errors which happen while using the API are turned into Python
9592 RuntimeError exceptions.
9593
9594 To create a guestfs handle you usually have to perform the following
9595 sequence of calls:
9596
9597 # Create the handle, call add_drive at least once, and possibly
9598 # several times if the guest has multiple block devices:
9599 g = guestfs.GuestFS ()
9600 g.add_drive (\"guest.img\")
9601
9602 # Launch the qemu subprocess and wait for it to become ready:
9603 g.launch ()
9604
9605 # Now you can issue commands, for example:
9606 logvols = g.lvs ()
9607
9608 \"\"\"
9609
9610 import libguestfsmod
9611
9612 class GuestFS:
9613     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9614
9615     def __init__ (self):
9616         \"\"\"Create a new libguestfs handle.\"\"\"
9617         self._o = libguestfsmod.create ()
9618
9619     def __del__ (self):
9620         libguestfsmod.close (self._o)
9621
9622 ";
9623
9624   List.iter (
9625     fun (name, style, _, flags, _, _, longdesc) ->
9626       pr "    def %s " name;
9627       generate_py_call_args ~handle:"self" (snd style);
9628       pr ":\n";
9629
9630       if not (List.mem NotInDocs flags) then (
9631         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9632         let doc =
9633           match fst style with
9634           | RErr | RInt _ | RInt64 _ | RBool _
9635           | RConstOptString _ | RConstString _
9636           | RString _ | RBufferOut _ -> doc
9637           | RStringList _ ->
9638               doc ^ "\n\nThis function returns a list of strings."
9639           | RStruct (_, typ) ->
9640               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9641           | RStructList (_, typ) ->
9642               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9643           | RHashtable _ ->
9644               doc ^ "\n\nThis function returns a dictionary." in
9645         let doc =
9646           if List.mem ProtocolLimitWarning flags then
9647             doc ^ "\n\n" ^ protocol_limit_warning
9648           else doc in
9649         let doc =
9650           if List.mem DangerWillRobinson flags then
9651             doc ^ "\n\n" ^ danger_will_robinson
9652           else doc in
9653         let doc =
9654           match deprecation_notice flags with
9655           | None -> doc
9656           | Some txt -> doc ^ "\n\n" ^ txt in
9657         let doc = pod2text ~width:60 name doc in
9658         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9659         let doc = String.concat "\n        " doc in
9660         pr "        u\"\"\"%s\"\"\"\n" doc;
9661       );
9662       pr "        return libguestfsmod.%s " name;
9663       generate_py_call_args ~handle:"self._o" (snd style);
9664       pr "\n";
9665       pr "\n";
9666   ) all_functions
9667
9668 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9669 and generate_py_call_args ~handle args =
9670   pr "(%s" handle;
9671   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9672   pr ")"
9673
9674 (* Useful if you need the longdesc POD text as plain text.  Returns a
9675  * list of lines.
9676  *
9677  * Because this is very slow (the slowest part of autogeneration),
9678  * we memoize the results.
9679  *)
9680 and pod2text ~width name longdesc =
9681   let key = width, name, longdesc in
9682   try Hashtbl.find pod2text_memo key
9683   with Not_found ->
9684     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9685     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9686     close_out chan;
9687     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9688     let chan = open_process_in cmd in
9689     let lines = ref [] in
9690     let rec loop i =
9691       let line = input_line chan in
9692       if i = 1 then             (* discard the first line of output *)
9693         loop (i+1)
9694       else (
9695         let line = triml line in
9696         lines := line :: !lines;
9697         loop (i+1)
9698       ) in
9699     let lines = try loop 1 with End_of_file -> List.rev !lines in
9700     unlink filename;
9701     (match close_process_in chan with
9702      | WEXITED 0 -> ()
9703      | WEXITED i ->
9704          failwithf "pod2text: process exited with non-zero status (%d)" i
9705      | WSIGNALED i | WSTOPPED i ->
9706          failwithf "pod2text: process signalled or stopped by signal %d" i
9707     );
9708     Hashtbl.add pod2text_memo key lines;
9709     pod2text_memo_updated ();
9710     lines
9711
9712 (* Generate ruby bindings. *)
9713 and generate_ruby_c () =
9714   generate_header CStyle LGPLv2plus;
9715
9716   pr "\
9717 #include <stdio.h>
9718 #include <stdlib.h>
9719
9720 #include <ruby.h>
9721
9722 #include \"guestfs.h\"
9723
9724 #include \"extconf.h\"
9725
9726 /* For Ruby < 1.9 */
9727 #ifndef RARRAY_LEN
9728 #define RARRAY_LEN(r) (RARRAY((r))->len)
9729 #endif
9730
9731 static VALUE m_guestfs;                 /* guestfs module */
9732 static VALUE c_guestfs;                 /* guestfs_h handle */
9733 static VALUE e_Error;                   /* used for all errors */
9734
9735 static void ruby_guestfs_free (void *p)
9736 {
9737   if (!p) return;
9738   guestfs_close ((guestfs_h *) p);
9739 }
9740
9741 static VALUE ruby_guestfs_create (VALUE m)
9742 {
9743   guestfs_h *g;
9744
9745   g = guestfs_create ();
9746   if (!g)
9747     rb_raise (e_Error, \"failed to create guestfs handle\");
9748
9749   /* Don't print error messages to stderr by default. */
9750   guestfs_set_error_handler (g, NULL, NULL);
9751
9752   /* Wrap it, and make sure the close function is called when the
9753    * handle goes away.
9754    */
9755   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9756 }
9757
9758 static VALUE ruby_guestfs_close (VALUE gv)
9759 {
9760   guestfs_h *g;
9761   Data_Get_Struct (gv, guestfs_h, g);
9762
9763   ruby_guestfs_free (g);
9764   DATA_PTR (gv) = NULL;
9765
9766   return Qnil;
9767 }
9768
9769 ";
9770
9771   List.iter (
9772     fun (name, style, _, _, _, _, _) ->
9773       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9774       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9775       pr ")\n";
9776       pr "{\n";
9777       pr "  guestfs_h *g;\n";
9778       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9779       pr "  if (!g)\n";
9780       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9781         name;
9782       pr "\n";
9783
9784       List.iter (
9785         function
9786         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9787             pr "  Check_Type (%sv, T_STRING);\n" n;
9788             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9789             pr "  if (!%s)\n" n;
9790             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9791             pr "              \"%s\", \"%s\");\n" n name
9792         | BufferIn n ->
9793             pr "  Check_Type (%sv, T_STRING);\n" n;
9794             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9795             pr "  if (!%s)\n" n;
9796             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9797             pr "              \"%s\", \"%s\");\n" n name;
9798             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9799         | OptString n ->
9800             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9801         | StringList n | DeviceList n ->
9802             pr "  char **%s;\n" n;
9803             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9804             pr "  {\n";
9805             pr "    int i, len;\n";
9806             pr "    len = RARRAY_LEN (%sv);\n" n;
9807             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9808               n;
9809             pr "    for (i = 0; i < len; ++i) {\n";
9810             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9811             pr "      %s[i] = StringValueCStr (v);\n" n;
9812             pr "    }\n";
9813             pr "    %s[len] = NULL;\n" n;
9814             pr "  }\n";
9815         | Bool n ->
9816             pr "  int %s = RTEST (%sv);\n" n n
9817         | Int n ->
9818             pr "  int %s = NUM2INT (%sv);\n" n n
9819         | Int64 n ->
9820             pr "  long long %s = NUM2LL (%sv);\n" n n
9821       ) (snd style);
9822       pr "\n";
9823
9824       let error_code =
9825         match fst style with
9826         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9827         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9828         | RConstString _ | RConstOptString _ ->
9829             pr "  const char *r;\n"; "NULL"
9830         | RString _ -> pr "  char *r;\n"; "NULL"
9831         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9832         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9833         | RStructList (_, typ) ->
9834             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9835         | RBufferOut _ ->
9836             pr "  char *r;\n";
9837             pr "  size_t size;\n";
9838             "NULL" in
9839       pr "\n";
9840
9841       pr "  r = guestfs_%s " name;
9842       generate_c_call_args ~handle:"g" style;
9843       pr ";\n";
9844
9845       List.iter (
9846         function
9847         | Pathname _ | Device _ | Dev_or_Path _ | String _
9848         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9849         | BufferIn _ -> ()
9850         | StringList n | DeviceList n ->
9851             pr "  free (%s);\n" n
9852       ) (snd style);
9853
9854       pr "  if (r == %s)\n" error_code;
9855       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9856       pr "\n";
9857
9858       (match fst style with
9859        | RErr ->
9860            pr "  return Qnil;\n"
9861        | RInt _ | RBool _ ->
9862            pr "  return INT2NUM (r);\n"
9863        | RInt64 _ ->
9864            pr "  return ULL2NUM (r);\n"
9865        | RConstString _ ->
9866            pr "  return rb_str_new2 (r);\n";
9867        | RConstOptString _ ->
9868            pr "  if (r)\n";
9869            pr "    return rb_str_new2 (r);\n";
9870            pr "  else\n";
9871            pr "    return Qnil;\n";
9872        | RString _ ->
9873            pr "  VALUE rv = rb_str_new2 (r);\n";
9874            pr "  free (r);\n";
9875            pr "  return rv;\n";
9876        | RStringList _ ->
9877            pr "  int i, len = 0;\n";
9878            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9879            pr "  VALUE rv = rb_ary_new2 (len);\n";
9880            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9881            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9882            pr "    free (r[i]);\n";
9883            pr "  }\n";
9884            pr "  free (r);\n";
9885            pr "  return rv;\n"
9886        | RStruct (_, typ) ->
9887            let cols = cols_of_struct typ in
9888            generate_ruby_struct_code typ cols
9889        | RStructList (_, typ) ->
9890            let cols = cols_of_struct typ in
9891            generate_ruby_struct_list_code typ cols
9892        | RHashtable _ ->
9893            pr "  VALUE rv = rb_hash_new ();\n";
9894            pr "  int i;\n";
9895            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9896            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9897            pr "    free (r[i]);\n";
9898            pr "    free (r[i+1]);\n";
9899            pr "  }\n";
9900            pr "  free (r);\n";
9901            pr "  return rv;\n"
9902        | RBufferOut _ ->
9903            pr "  VALUE rv = rb_str_new (r, size);\n";
9904            pr "  free (r);\n";
9905            pr "  return rv;\n";
9906       );
9907
9908       pr "}\n";
9909       pr "\n"
9910   ) all_functions;
9911
9912   pr "\
9913 /* Initialize the module. */
9914 void Init__guestfs ()
9915 {
9916   m_guestfs = rb_define_module (\"Guestfs\");
9917   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9918   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9919
9920   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9921   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9922
9923 ";
9924   (* Define the rest of the methods. *)
9925   List.iter (
9926     fun (name, style, _, _, _, _, _) ->
9927       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9928       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9929   ) all_functions;
9930
9931   pr "}\n"
9932
9933 (* Ruby code to return a struct. *)
9934 and generate_ruby_struct_code typ cols =
9935   pr "  VALUE rv = rb_hash_new ();\n";
9936   List.iter (
9937     function
9938     | name, FString ->
9939         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9940     | name, FBuffer ->
9941         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9942     | name, FUUID ->
9943         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9944     | name, (FBytes|FUInt64) ->
9945         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9946     | name, FInt64 ->
9947         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9948     | name, FUInt32 ->
9949         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9950     | name, FInt32 ->
9951         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9952     | name, FOptPercent ->
9953         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9954     | name, FChar -> (* XXX wrong? *)
9955         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9956   ) cols;
9957   pr "  guestfs_free_%s (r);\n" typ;
9958   pr "  return rv;\n"
9959
9960 (* Ruby code to return a struct list. *)
9961 and generate_ruby_struct_list_code typ cols =
9962   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9963   pr "  int i;\n";
9964   pr "  for (i = 0; i < r->len; ++i) {\n";
9965   pr "    VALUE hv = rb_hash_new ();\n";
9966   List.iter (
9967     function
9968     | name, FString ->
9969         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9970     | name, FBuffer ->
9971         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
9972     | name, FUUID ->
9973         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9974     | name, (FBytes|FUInt64) ->
9975         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9976     | name, FInt64 ->
9977         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9978     | name, FUInt32 ->
9979         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9980     | name, FInt32 ->
9981         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9982     | name, FOptPercent ->
9983         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9984     | name, FChar -> (* XXX wrong? *)
9985         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9986   ) cols;
9987   pr "    rb_ary_push (rv, hv);\n";
9988   pr "  }\n";
9989   pr "  guestfs_free_%s_list (r);\n" typ;
9990   pr "  return rv;\n"
9991
9992 (* Generate Java bindings GuestFS.java file. *)
9993 and generate_java_java () =
9994   generate_header CStyle LGPLv2plus;
9995
9996   pr "\
9997 package com.redhat.et.libguestfs;
9998
9999 import java.util.HashMap;
10000 import com.redhat.et.libguestfs.LibGuestFSException;
10001 import com.redhat.et.libguestfs.PV;
10002 import com.redhat.et.libguestfs.VG;
10003 import com.redhat.et.libguestfs.LV;
10004 import com.redhat.et.libguestfs.Stat;
10005 import com.redhat.et.libguestfs.StatVFS;
10006 import com.redhat.et.libguestfs.IntBool;
10007 import com.redhat.et.libguestfs.Dirent;
10008
10009 /**
10010  * The GuestFS object is a libguestfs handle.
10011  *
10012  * @author rjones
10013  */
10014 public class GuestFS {
10015   // Load the native code.
10016   static {
10017     System.loadLibrary (\"guestfs_jni\");
10018   }
10019
10020   /**
10021    * The native guestfs_h pointer.
10022    */
10023   long g;
10024
10025   /**
10026    * Create a libguestfs handle.
10027    *
10028    * @throws LibGuestFSException
10029    */
10030   public GuestFS () throws LibGuestFSException
10031   {
10032     g = _create ();
10033   }
10034   private native long _create () throws LibGuestFSException;
10035
10036   /**
10037    * Close a libguestfs handle.
10038    *
10039    * You can also leave handles to be collected by the garbage
10040    * collector, but this method ensures that the resources used
10041    * by the handle are freed up immediately.  If you call any
10042    * other methods after closing the handle, you will get an
10043    * exception.
10044    *
10045    * @throws LibGuestFSException
10046    */
10047   public void close () throws LibGuestFSException
10048   {
10049     if (g != 0)
10050       _close (g);
10051     g = 0;
10052   }
10053   private native void _close (long g) throws LibGuestFSException;
10054
10055   public void finalize () throws LibGuestFSException
10056   {
10057     close ();
10058   }
10059
10060 ";
10061
10062   List.iter (
10063     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10064       if not (List.mem NotInDocs flags); then (
10065         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10066         let doc =
10067           if List.mem ProtocolLimitWarning flags then
10068             doc ^ "\n\n" ^ protocol_limit_warning
10069           else doc in
10070         let doc =
10071           if List.mem DangerWillRobinson flags then
10072             doc ^ "\n\n" ^ danger_will_robinson
10073           else doc in
10074         let doc =
10075           match deprecation_notice flags with
10076           | None -> doc
10077           | Some txt -> doc ^ "\n\n" ^ txt in
10078         let doc = pod2text ~width:60 name doc in
10079         let doc = List.map (            (* RHBZ#501883 *)
10080           function
10081           | "" -> "<p>"
10082           | nonempty -> nonempty
10083         ) doc in
10084         let doc = String.concat "\n   * " doc in
10085
10086         pr "  /**\n";
10087         pr "   * %s\n" shortdesc;
10088         pr "   * <p>\n";
10089         pr "   * %s\n" doc;
10090         pr "   * @throws LibGuestFSException\n";
10091         pr "   */\n";
10092         pr "  ";
10093       );
10094       generate_java_prototype ~public:true ~semicolon:false name style;
10095       pr "\n";
10096       pr "  {\n";
10097       pr "    if (g == 0)\n";
10098       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10099         name;
10100       pr "    ";
10101       if fst style <> RErr then pr "return ";
10102       pr "_%s " name;
10103       generate_java_call_args ~handle:"g" (snd style);
10104       pr ";\n";
10105       pr "  }\n";
10106       pr "  ";
10107       generate_java_prototype ~privat:true ~native:true name style;
10108       pr "\n";
10109       pr "\n";
10110   ) all_functions;
10111
10112   pr "}\n"
10113
10114 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10115 and generate_java_call_args ~handle args =
10116   pr "(%s" handle;
10117   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10118   pr ")"
10119
10120 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10121     ?(semicolon=true) name style =
10122   if privat then pr "private ";
10123   if public then pr "public ";
10124   if native then pr "native ";
10125
10126   (* return type *)
10127   (match fst style with
10128    | RErr -> pr "void ";
10129    | RInt _ -> pr "int ";
10130    | RInt64 _ -> pr "long ";
10131    | RBool _ -> pr "boolean ";
10132    | RConstString _ | RConstOptString _ | RString _
10133    | RBufferOut _ -> pr "String ";
10134    | RStringList _ -> pr "String[] ";
10135    | RStruct (_, typ) ->
10136        let name = java_name_of_struct typ in
10137        pr "%s " name;
10138    | RStructList (_, typ) ->
10139        let name = java_name_of_struct typ in
10140        pr "%s[] " name;
10141    | RHashtable _ -> pr "HashMap<String,String> ";
10142   );
10143
10144   if native then pr "_%s " name else pr "%s " name;
10145   pr "(";
10146   let needs_comma = ref false in
10147   if native then (
10148     pr "long g";
10149     needs_comma := true
10150   );
10151
10152   (* args *)
10153   List.iter (
10154     fun arg ->
10155       if !needs_comma then pr ", ";
10156       needs_comma := true;
10157
10158       match arg with
10159       | Pathname n
10160       | Device n | Dev_or_Path n
10161       | String n
10162       | OptString n
10163       | FileIn n
10164       | FileOut n ->
10165           pr "String %s" n
10166       | BufferIn n ->
10167           pr "byte[] %s" n
10168       | StringList n | DeviceList n ->
10169           pr "String[] %s" n
10170       | Bool n ->
10171           pr "boolean %s" n
10172       | Int n ->
10173           pr "int %s" n
10174       | Int64 n ->
10175           pr "long %s" n
10176   ) (snd style);
10177
10178   pr ")\n";
10179   pr "    throws LibGuestFSException";
10180   if semicolon then pr ";"
10181
10182 and generate_java_struct jtyp cols () =
10183   generate_header CStyle LGPLv2plus;
10184
10185   pr "\
10186 package com.redhat.et.libguestfs;
10187
10188 /**
10189  * Libguestfs %s structure.
10190  *
10191  * @author rjones
10192  * @see GuestFS
10193  */
10194 public class %s {
10195 " jtyp jtyp;
10196
10197   List.iter (
10198     function
10199     | name, FString
10200     | name, FUUID
10201     | name, FBuffer -> pr "  public String %s;\n" name
10202     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10203     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10204     | name, FChar -> pr "  public char %s;\n" name
10205     | name, FOptPercent ->
10206         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10207         pr "  public float %s;\n" name
10208   ) cols;
10209
10210   pr "}\n"
10211
10212 and generate_java_c () =
10213   generate_header CStyle LGPLv2plus;
10214
10215   pr "\
10216 #include <stdio.h>
10217 #include <stdlib.h>
10218 #include <string.h>
10219
10220 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10221 #include \"guestfs.h\"
10222
10223 /* Note that this function returns.  The exception is not thrown
10224  * until after the wrapper function returns.
10225  */
10226 static void
10227 throw_exception (JNIEnv *env, const char *msg)
10228 {
10229   jclass cl;
10230   cl = (*env)->FindClass (env,
10231                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10232   (*env)->ThrowNew (env, cl, msg);
10233 }
10234
10235 JNIEXPORT jlong JNICALL
10236 Java_com_redhat_et_libguestfs_GuestFS__1create
10237   (JNIEnv *env, jobject obj)
10238 {
10239   guestfs_h *g;
10240
10241   g = guestfs_create ();
10242   if (g == NULL) {
10243     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10244     return 0;
10245   }
10246   guestfs_set_error_handler (g, NULL, NULL);
10247   return (jlong) (long) g;
10248 }
10249
10250 JNIEXPORT void JNICALL
10251 Java_com_redhat_et_libguestfs_GuestFS__1close
10252   (JNIEnv *env, jobject obj, jlong jg)
10253 {
10254   guestfs_h *g = (guestfs_h *) (long) jg;
10255   guestfs_close (g);
10256 }
10257
10258 ";
10259
10260   List.iter (
10261     fun (name, style, _, _, _, _, _) ->
10262       pr "JNIEXPORT ";
10263       (match fst style with
10264        | RErr -> pr "void ";
10265        | RInt _ -> pr "jint ";
10266        | RInt64 _ -> pr "jlong ";
10267        | RBool _ -> pr "jboolean ";
10268        | RConstString _ | RConstOptString _ | RString _
10269        | RBufferOut _ -> pr "jstring ";
10270        | RStruct _ | RHashtable _ ->
10271            pr "jobject ";
10272        | RStringList _ | RStructList _ ->
10273            pr "jobjectArray ";
10274       );
10275       pr "JNICALL\n";
10276       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10277       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10278       pr "\n";
10279       pr "  (JNIEnv *env, jobject obj, jlong jg";
10280       List.iter (
10281         function
10282         | Pathname n
10283         | Device n | Dev_or_Path n
10284         | String n
10285         | OptString n
10286         | FileIn n
10287         | FileOut n ->
10288             pr ", jstring j%s" n
10289         | BufferIn n ->
10290             pr ", jbyteArray j%s" n
10291         | StringList n | DeviceList n ->
10292             pr ", jobjectArray j%s" n
10293         | Bool n ->
10294             pr ", jboolean j%s" n
10295         | Int n ->
10296             pr ", jint j%s" n
10297         | Int64 n ->
10298             pr ", jlong j%s" n
10299       ) (snd style);
10300       pr ")\n";
10301       pr "{\n";
10302       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10303       let error_code, no_ret =
10304         match fst style with
10305         | RErr -> pr "  int r;\n"; "-1", ""
10306         | RBool _
10307         | RInt _ -> pr "  int r;\n"; "-1", "0"
10308         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10309         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10310         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10311         | RString _ ->
10312             pr "  jstring jr;\n";
10313             pr "  char *r;\n"; "NULL", "NULL"
10314         | RStringList _ ->
10315             pr "  jobjectArray jr;\n";
10316             pr "  int r_len;\n";
10317             pr "  jclass cl;\n";
10318             pr "  jstring jstr;\n";
10319             pr "  char **r;\n"; "NULL", "NULL"
10320         | RStruct (_, typ) ->
10321             pr "  jobject jr;\n";
10322             pr "  jclass cl;\n";
10323             pr "  jfieldID fl;\n";
10324             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10325         | RStructList (_, typ) ->
10326             pr "  jobjectArray jr;\n";
10327             pr "  jclass cl;\n";
10328             pr "  jfieldID fl;\n";
10329             pr "  jobject jfl;\n";
10330             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10331         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10332         | RBufferOut _ ->
10333             pr "  jstring jr;\n";
10334             pr "  char *r;\n";
10335             pr "  size_t size;\n";
10336             "NULL", "NULL" in
10337       List.iter (
10338         function
10339         | Pathname n
10340         | Device n | Dev_or_Path n
10341         | String n
10342         | OptString n
10343         | FileIn n
10344         | FileOut n ->
10345             pr "  const char *%s;\n" n
10346         | BufferIn n ->
10347             pr "  jbyte *%s;\n" n;
10348             pr "  size_t %s_size;\n" n
10349         | StringList n | DeviceList n ->
10350             pr "  int %s_len;\n" n;
10351             pr "  const char **%s;\n" n
10352         | Bool n
10353         | Int n ->
10354             pr "  int %s;\n" n
10355         | Int64 n ->
10356             pr "  int64_t %s;\n" n
10357       ) (snd style);
10358
10359       let needs_i =
10360         (match fst style with
10361          | RStringList _ | RStructList _ -> true
10362          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10363          | RConstOptString _
10364          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10365           List.exists (function
10366                        | StringList _ -> true
10367                        | DeviceList _ -> true
10368                        | _ -> false) (snd style) in
10369       if needs_i then
10370         pr "  int i;\n";
10371
10372       pr "\n";
10373
10374       (* Get the parameters. *)
10375       List.iter (
10376         function
10377         | Pathname n
10378         | Device n | Dev_or_Path n
10379         | String n
10380         | FileIn n
10381         | FileOut n ->
10382             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10383         | OptString n ->
10384             (* This is completely undocumented, but Java null becomes
10385              * a NULL parameter.
10386              *)
10387             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10388         | BufferIn n ->
10389             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10390             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10391         | StringList n | DeviceList n ->
10392             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10393             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10394             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10395             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10396               n;
10397             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10398             pr "  }\n";
10399             pr "  %s[%s_len] = NULL;\n" n n;
10400         | Bool n
10401         | Int n
10402         | Int64 n ->
10403             pr "  %s = j%s;\n" n n
10404       ) (snd style);
10405
10406       (* Make the call. *)
10407       pr "  r = guestfs_%s " name;
10408       generate_c_call_args ~handle:"g" style;
10409       pr ";\n";
10410
10411       (* Release the parameters. *)
10412       List.iter (
10413         function
10414         | Pathname n
10415         | Device n | Dev_or_Path n
10416         | String n
10417         | FileIn n
10418         | FileOut n ->
10419             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10420         | OptString n ->
10421             pr "  if (j%s)\n" n;
10422             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10423         | BufferIn n ->
10424             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10425         | StringList n | DeviceList n ->
10426             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10427             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10428               n;
10429             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10430             pr "  }\n";
10431             pr "  free (%s);\n" n
10432         | Bool n
10433         | Int n
10434         | Int64 n -> ()
10435       ) (snd style);
10436
10437       (* Check for errors. *)
10438       pr "  if (r == %s) {\n" error_code;
10439       pr "    throw_exception (env, guestfs_last_error (g));\n";
10440       pr "    return %s;\n" no_ret;
10441       pr "  }\n";
10442
10443       (* Return value. *)
10444       (match fst style with
10445        | RErr -> ()
10446        | RInt _ -> pr "  return (jint) r;\n"
10447        | RBool _ -> pr "  return (jboolean) r;\n"
10448        | RInt64 _ -> pr "  return (jlong) r;\n"
10449        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10450        | RConstOptString _ ->
10451            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10452        | RString _ ->
10453            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10454            pr "  free (r);\n";
10455            pr "  return jr;\n"
10456        | RStringList _ ->
10457            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10458            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10459            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10460            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10461            pr "  for (i = 0; i < r_len; ++i) {\n";
10462            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10463            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10464            pr "    free (r[i]);\n";
10465            pr "  }\n";
10466            pr "  free (r);\n";
10467            pr "  return jr;\n"
10468        | RStruct (_, typ) ->
10469            let jtyp = java_name_of_struct typ in
10470            let cols = cols_of_struct typ in
10471            generate_java_struct_return typ jtyp cols
10472        | RStructList (_, typ) ->
10473            let jtyp = java_name_of_struct typ in
10474            let cols = cols_of_struct typ in
10475            generate_java_struct_list_return typ jtyp cols
10476        | RHashtable _ ->
10477            (* XXX *)
10478            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10479            pr "  return NULL;\n"
10480        | RBufferOut _ ->
10481            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10482            pr "  free (r);\n";
10483            pr "  return jr;\n"
10484       );
10485
10486       pr "}\n";
10487       pr "\n"
10488   ) all_functions
10489
10490 and generate_java_struct_return typ jtyp cols =
10491   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10492   pr "  jr = (*env)->AllocObject (env, cl);\n";
10493   List.iter (
10494     function
10495     | name, FString ->
10496         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10497         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10498     | name, FUUID ->
10499         pr "  {\n";
10500         pr "    char s[33];\n";
10501         pr "    memcpy (s, r->%s, 32);\n" name;
10502         pr "    s[32] = 0;\n";
10503         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10504         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10505         pr "  }\n";
10506     | name, FBuffer ->
10507         pr "  {\n";
10508         pr "    int len = r->%s_len;\n" name;
10509         pr "    char s[len+1];\n";
10510         pr "    memcpy (s, r->%s, len);\n" name;
10511         pr "    s[len] = 0;\n";
10512         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10513         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10514         pr "  }\n";
10515     | name, (FBytes|FUInt64|FInt64) ->
10516         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10517         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10518     | name, (FUInt32|FInt32) ->
10519         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10520         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10521     | name, FOptPercent ->
10522         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10523         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10524     | name, FChar ->
10525         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10526         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10527   ) cols;
10528   pr "  free (r);\n";
10529   pr "  return jr;\n"
10530
10531 and generate_java_struct_list_return typ jtyp cols =
10532   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10533   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10534   pr "  for (i = 0; i < r->len; ++i) {\n";
10535   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10536   List.iter (
10537     function
10538     | name, FString ->
10539         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10540         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10541     | name, FUUID ->
10542         pr "    {\n";
10543         pr "      char s[33];\n";
10544         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10545         pr "      s[32] = 0;\n";
10546         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10547         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10548         pr "    }\n";
10549     | name, FBuffer ->
10550         pr "    {\n";
10551         pr "      int len = r->val[i].%s_len;\n" name;
10552         pr "      char s[len+1];\n";
10553         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10554         pr "      s[len] = 0;\n";
10555         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10556         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10557         pr "    }\n";
10558     | name, (FBytes|FUInt64|FInt64) ->
10559         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10560         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10561     | name, (FUInt32|FInt32) ->
10562         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10563         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10564     | name, FOptPercent ->
10565         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10566         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10567     | name, FChar ->
10568         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10569         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10570   ) cols;
10571   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10572   pr "  }\n";
10573   pr "  guestfs_free_%s_list (r);\n" typ;
10574   pr "  return jr;\n"
10575
10576 and generate_java_makefile_inc () =
10577   generate_header HashStyle GPLv2plus;
10578
10579   pr "java_built_sources = \\\n";
10580   List.iter (
10581     fun (typ, jtyp) ->
10582         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10583   ) java_structs;
10584   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10585
10586 and generate_haskell_hs () =
10587   generate_header HaskellStyle LGPLv2plus;
10588
10589   (* XXX We only know how to generate partial FFI for Haskell
10590    * at the moment.  Please help out!
10591    *)
10592   let can_generate style =
10593     match style with
10594     | RErr, _
10595     | RInt _, _
10596     | RInt64 _, _ -> true
10597     | RBool _, _
10598     | RConstString _, _
10599     | RConstOptString _, _
10600     | RString _, _
10601     | RStringList _, _
10602     | RStruct _, _
10603     | RStructList _, _
10604     | RHashtable _, _
10605     | RBufferOut _, _ -> false in
10606
10607   pr "\
10608 {-# INCLUDE <guestfs.h> #-}
10609 {-# LANGUAGE ForeignFunctionInterface #-}
10610
10611 module Guestfs (
10612   create";
10613
10614   (* List out the names of the actions we want to export. *)
10615   List.iter (
10616     fun (name, style, _, _, _, _, _) ->
10617       if can_generate style then pr ",\n  %s" name
10618   ) all_functions;
10619
10620   pr "
10621   ) where
10622
10623 -- Unfortunately some symbols duplicate ones already present
10624 -- in Prelude.  We don't know which, so we hard-code a list
10625 -- here.
10626 import Prelude hiding (truncate)
10627
10628 import Foreign
10629 import Foreign.C
10630 import Foreign.C.Types
10631 import IO
10632 import Control.Exception
10633 import Data.Typeable
10634
10635 data GuestfsS = GuestfsS            -- represents the opaque C struct
10636 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10637 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10638
10639 -- XXX define properly later XXX
10640 data PV = PV
10641 data VG = VG
10642 data LV = LV
10643 data IntBool = IntBool
10644 data Stat = Stat
10645 data StatVFS = StatVFS
10646 data Hashtable = Hashtable
10647
10648 foreign import ccall unsafe \"guestfs_create\" c_create
10649   :: IO GuestfsP
10650 foreign import ccall unsafe \"&guestfs_close\" c_close
10651   :: FunPtr (GuestfsP -> IO ())
10652 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10653   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10654
10655 create :: IO GuestfsH
10656 create = do
10657   p <- c_create
10658   c_set_error_handler p nullPtr nullPtr
10659   h <- newForeignPtr c_close p
10660   return h
10661
10662 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10663   :: GuestfsP -> IO CString
10664
10665 -- last_error :: GuestfsH -> IO (Maybe String)
10666 -- last_error h = do
10667 --   str <- withForeignPtr h (\\p -> c_last_error p)
10668 --   maybePeek peekCString str
10669
10670 last_error :: GuestfsH -> IO (String)
10671 last_error h = do
10672   str <- withForeignPtr h (\\p -> c_last_error p)
10673   if (str == nullPtr)
10674     then return \"no error\"
10675     else peekCString str
10676
10677 ";
10678
10679   (* Generate wrappers for each foreign function. *)
10680   List.iter (
10681     fun (name, style, _, _, _, _, _) ->
10682       if can_generate style then (
10683         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10684         pr "  :: ";
10685         generate_haskell_prototype ~handle:"GuestfsP" style;
10686         pr "\n";
10687         pr "\n";
10688         pr "%s :: " name;
10689         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10690         pr "\n";
10691         pr "%s %s = do\n" name
10692           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10693         pr "  r <- ";
10694         (* Convert pointer arguments using with* functions. *)
10695         List.iter (
10696           function
10697           | FileIn n
10698           | FileOut n
10699           | Pathname n | Device n | Dev_or_Path n | String n ->
10700               pr "withCString %s $ \\%s -> " n n
10701           | BufferIn n ->
10702               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10703           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10704           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10705           | Bool _ | Int _ | Int64 _ -> ()
10706         ) (snd style);
10707         (* Convert integer arguments. *)
10708         let args =
10709           List.map (
10710             function
10711             | Bool n -> sprintf "(fromBool %s)" n
10712             | Int n -> sprintf "(fromIntegral %s)" n
10713             | Int64 n -> sprintf "(fromIntegral %s)" n
10714             | FileIn n | FileOut n
10715             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10716             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10717           ) (snd style) in
10718         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10719           (String.concat " " ("p" :: args));
10720         (match fst style with
10721          | RErr | RInt _ | RInt64 _ | RBool _ ->
10722              pr "  if (r == -1)\n";
10723              pr "    then do\n";
10724              pr "      err <- last_error h\n";
10725              pr "      fail err\n";
10726          | RConstString _ | RConstOptString _ | RString _
10727          | RStringList _ | RStruct _
10728          | RStructList _ | RHashtable _ | RBufferOut _ ->
10729              pr "  if (r == nullPtr)\n";
10730              pr "    then do\n";
10731              pr "      err <- last_error h\n";
10732              pr "      fail err\n";
10733         );
10734         (match fst style with
10735          | RErr ->
10736              pr "    else return ()\n"
10737          | RInt _ ->
10738              pr "    else return (fromIntegral r)\n"
10739          | RInt64 _ ->
10740              pr "    else return (fromIntegral r)\n"
10741          | RBool _ ->
10742              pr "    else return (toBool r)\n"
10743          | RConstString _
10744          | RConstOptString _
10745          | RString _
10746          | RStringList _
10747          | RStruct _
10748          | RStructList _
10749          | RHashtable _
10750          | RBufferOut _ ->
10751              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10752         );
10753         pr "\n";
10754       )
10755   ) all_functions
10756
10757 and generate_haskell_prototype ~handle ?(hs = false) style =
10758   pr "%s -> " handle;
10759   let string = if hs then "String" else "CString" in
10760   let int = if hs then "Int" else "CInt" in
10761   let bool = if hs then "Bool" else "CInt" in
10762   let int64 = if hs then "Integer" else "Int64" in
10763   List.iter (
10764     fun arg ->
10765       (match arg with
10766        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10767        | BufferIn _ ->
10768            if hs then pr "String"
10769            else pr "CString -> CInt"
10770        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10771        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10772        | Bool _ -> pr "%s" bool
10773        | Int _ -> pr "%s" int
10774        | Int64 _ -> pr "%s" int
10775        | FileIn _ -> pr "%s" string
10776        | FileOut _ -> pr "%s" string
10777       );
10778       pr " -> ";
10779   ) (snd style);
10780   pr "IO (";
10781   (match fst style with
10782    | RErr -> if not hs then pr "CInt"
10783    | RInt _ -> pr "%s" int
10784    | RInt64 _ -> pr "%s" int64
10785    | RBool _ -> pr "%s" bool
10786    | RConstString _ -> pr "%s" string
10787    | RConstOptString _ -> pr "Maybe %s" string
10788    | RString _ -> pr "%s" string
10789    | RStringList _ -> pr "[%s]" string
10790    | RStruct (_, typ) ->
10791        let name = java_name_of_struct typ in
10792        pr "%s" name
10793    | RStructList (_, typ) ->
10794        let name = java_name_of_struct typ in
10795        pr "[%s]" name
10796    | RHashtable _ -> pr "Hashtable"
10797    | RBufferOut _ -> pr "%s" string
10798   );
10799   pr ")"
10800
10801 and generate_csharp () =
10802   generate_header CPlusPlusStyle LGPLv2plus;
10803
10804   (* XXX Make this configurable by the C# assembly users. *)
10805   let library = "libguestfs.so.0" in
10806
10807   pr "\
10808 // These C# bindings are highly experimental at present.
10809 //
10810 // Firstly they only work on Linux (ie. Mono).  In order to get them
10811 // to work on Windows (ie. .Net) you would need to port the library
10812 // itself to Windows first.
10813 //
10814 // The second issue is that some calls are known to be incorrect and
10815 // can cause Mono to segfault.  Particularly: calls which pass or
10816 // return string[], or return any structure value.  This is because
10817 // we haven't worked out the correct way to do this from C#.
10818 //
10819 // The third issue is that when compiling you get a lot of warnings.
10820 // We are not sure whether the warnings are important or not.
10821 //
10822 // Fourthly we do not routinely build or test these bindings as part
10823 // of the make && make check cycle, which means that regressions might
10824 // go unnoticed.
10825 //
10826 // Suggestions and patches are welcome.
10827
10828 // To compile:
10829 //
10830 // gmcs Libguestfs.cs
10831 // mono Libguestfs.exe
10832 //
10833 // (You'll probably want to add a Test class / static main function
10834 // otherwise this won't do anything useful).
10835
10836 using System;
10837 using System.IO;
10838 using System.Runtime.InteropServices;
10839 using System.Runtime.Serialization;
10840 using System.Collections;
10841
10842 namespace Guestfs
10843 {
10844   class Error : System.ApplicationException
10845   {
10846     public Error (string message) : base (message) {}
10847     protected Error (SerializationInfo info, StreamingContext context) {}
10848   }
10849
10850   class Guestfs
10851   {
10852     IntPtr _handle;
10853
10854     [DllImport (\"%s\")]
10855     static extern IntPtr guestfs_create ();
10856
10857     public Guestfs ()
10858     {
10859       _handle = guestfs_create ();
10860       if (_handle == IntPtr.Zero)
10861         throw new Error (\"could not create guestfs handle\");
10862     }
10863
10864     [DllImport (\"%s\")]
10865     static extern void guestfs_close (IntPtr h);
10866
10867     ~Guestfs ()
10868     {
10869       guestfs_close (_handle);
10870     }
10871
10872     [DllImport (\"%s\")]
10873     static extern string guestfs_last_error (IntPtr h);
10874
10875 " library library library;
10876
10877   (* Generate C# structure bindings.  We prefix struct names with
10878    * underscore because C# cannot have conflicting struct names and
10879    * method names (eg. "class stat" and "stat").
10880    *)
10881   List.iter (
10882     fun (typ, cols) ->
10883       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10884       pr "    public class _%s {\n" typ;
10885       List.iter (
10886         function
10887         | name, FChar -> pr "      char %s;\n" name
10888         | name, FString -> pr "      string %s;\n" name
10889         | name, FBuffer ->
10890             pr "      uint %s_len;\n" name;
10891             pr "      string %s;\n" name
10892         | name, FUUID ->
10893             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10894             pr "      string %s;\n" name
10895         | name, FUInt32 -> pr "      uint %s;\n" name
10896         | name, FInt32 -> pr "      int %s;\n" name
10897         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10898         | name, FInt64 -> pr "      long %s;\n" name
10899         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10900       ) cols;
10901       pr "    }\n";
10902       pr "\n"
10903   ) structs;
10904
10905   (* Generate C# function bindings. *)
10906   List.iter (
10907     fun (name, style, _, _, _, shortdesc, _) ->
10908       let rec csharp_return_type () =
10909         match fst style with
10910         | RErr -> "void"
10911         | RBool n -> "bool"
10912         | RInt n -> "int"
10913         | RInt64 n -> "long"
10914         | RConstString n
10915         | RConstOptString n
10916         | RString n
10917         | RBufferOut n -> "string"
10918         | RStruct (_,n) -> "_" ^ n
10919         | RHashtable n -> "Hashtable"
10920         | RStringList n -> "string[]"
10921         | RStructList (_,n) -> sprintf "_%s[]" n
10922
10923       and c_return_type () =
10924         match fst style with
10925         | RErr
10926         | RBool _
10927         | RInt _ -> "int"
10928         | RInt64 _ -> "long"
10929         | RConstString _
10930         | RConstOptString _
10931         | RString _
10932         | RBufferOut _ -> "string"
10933         | RStruct (_,n) -> "_" ^ n
10934         | RHashtable _
10935         | RStringList _ -> "string[]"
10936         | RStructList (_,n) -> sprintf "_%s[]" n
10937
10938       and c_error_comparison () =
10939         match fst style with
10940         | RErr
10941         | RBool _
10942         | RInt _
10943         | RInt64 _ -> "== -1"
10944         | RConstString _
10945         | RConstOptString _
10946         | RString _
10947         | RBufferOut _
10948         | RStruct (_,_)
10949         | RHashtable _
10950         | RStringList _
10951         | RStructList (_,_) -> "== null"
10952
10953       and generate_extern_prototype () =
10954         pr "    static extern %s guestfs_%s (IntPtr h"
10955           (c_return_type ()) name;
10956         List.iter (
10957           function
10958           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10959           | FileIn n | FileOut n
10960           | BufferIn n ->
10961               pr ", [In] string %s" n
10962           | StringList n | DeviceList n ->
10963               pr ", [In] string[] %s" n
10964           | Bool n ->
10965               pr ", bool %s" n
10966           | Int n ->
10967               pr ", int %s" n
10968           | Int64 n ->
10969               pr ", long %s" n
10970         ) (snd style);
10971         pr ");\n"
10972
10973       and generate_public_prototype () =
10974         pr "    public %s %s (" (csharp_return_type ()) name;
10975         let comma = ref false in
10976         let next () =
10977           if !comma then pr ", ";
10978           comma := true
10979         in
10980         List.iter (
10981           function
10982           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10983           | FileIn n | FileOut n
10984           | BufferIn n ->
10985               next (); pr "string %s" n
10986           | StringList n | DeviceList n ->
10987               next (); pr "string[] %s" n
10988           | Bool n ->
10989               next (); pr "bool %s" n
10990           | Int n ->
10991               next (); pr "int %s" n
10992           | Int64 n ->
10993               next (); pr "long %s" n
10994         ) (snd style);
10995         pr ")\n"
10996
10997       and generate_call () =
10998         pr "guestfs_%s (_handle" name;
10999         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11000         pr ");\n";
11001       in
11002
11003       pr "    [DllImport (\"%s\")]\n" library;
11004       generate_extern_prototype ();
11005       pr "\n";
11006       pr "    /// <summary>\n";
11007       pr "    /// %s\n" shortdesc;
11008       pr "    /// </summary>\n";
11009       generate_public_prototype ();
11010       pr "    {\n";
11011       pr "      %s r;\n" (c_return_type ());
11012       pr "      r = ";
11013       generate_call ();
11014       pr "      if (r %s)\n" (c_error_comparison ());
11015       pr "        throw new Error (guestfs_last_error (_handle));\n";
11016       (match fst style with
11017        | RErr -> ()
11018        | RBool _ ->
11019            pr "      return r != 0 ? true : false;\n"
11020        | RHashtable _ ->
11021            pr "      Hashtable rr = new Hashtable ();\n";
11022            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11023            pr "        rr.Add (r[i], r[i+1]);\n";
11024            pr "      return rr;\n"
11025        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11026        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11027        | RStructList _ ->
11028            pr "      return r;\n"
11029       );
11030       pr "    }\n";
11031       pr "\n";
11032   ) all_functions_sorted;
11033
11034   pr "  }
11035 }
11036 "
11037
11038 and generate_bindtests () =
11039   generate_header CStyle LGPLv2plus;
11040
11041   pr "\
11042 #include <stdio.h>
11043 #include <stdlib.h>
11044 #include <inttypes.h>
11045 #include <string.h>
11046
11047 #include \"guestfs.h\"
11048 #include \"guestfs-internal.h\"
11049 #include \"guestfs-internal-actions.h\"
11050 #include \"guestfs_protocol.h\"
11051
11052 #define error guestfs_error
11053 #define safe_calloc guestfs_safe_calloc
11054 #define safe_malloc guestfs_safe_malloc
11055
11056 static void
11057 print_strings (char *const *argv)
11058 {
11059   int argc;
11060
11061   printf (\"[\");
11062   for (argc = 0; argv[argc] != NULL; ++argc) {
11063     if (argc > 0) printf (\", \");
11064     printf (\"\\\"%%s\\\"\", argv[argc]);
11065   }
11066   printf (\"]\\n\");
11067 }
11068
11069 /* The test0 function prints its parameters to stdout. */
11070 ";
11071
11072   let test0, tests =
11073     match test_functions with
11074     | [] -> assert false
11075     | test0 :: tests -> test0, tests in
11076
11077   let () =
11078     let (name, style, _, _, _, _, _) = test0 in
11079     generate_prototype ~extern:false ~semicolon:false ~newline:true
11080       ~handle:"g" ~prefix:"guestfs__" name style;
11081     pr "{\n";
11082     List.iter (
11083       function
11084       | Pathname n
11085       | Device n | Dev_or_Path n
11086       | String n
11087       | FileIn n
11088       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11089       | BufferIn n ->
11090           pr "  {\n";
11091           pr "    size_t i;\n";
11092           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11093           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11094           pr "    printf (\"\\n\");\n";
11095           pr "  }\n";
11096       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11097       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11098       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11099       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11100       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11101     ) (snd style);
11102     pr "  /* Java changes stdout line buffering so we need this: */\n";
11103     pr "  fflush (stdout);\n";
11104     pr "  return 0;\n";
11105     pr "}\n";
11106     pr "\n" in
11107
11108   List.iter (
11109     fun (name, style, _, _, _, _, _) ->
11110       if String.sub name (String.length name - 3) 3 <> "err" then (
11111         pr "/* Test normal return. */\n";
11112         generate_prototype ~extern:false ~semicolon:false ~newline:true
11113           ~handle:"g" ~prefix:"guestfs__" name style;
11114         pr "{\n";
11115         (match fst style with
11116          | RErr ->
11117              pr "  return 0;\n"
11118          | RInt _ ->
11119              pr "  int r;\n";
11120              pr "  sscanf (val, \"%%d\", &r);\n";
11121              pr "  return r;\n"
11122          | RInt64 _ ->
11123              pr "  int64_t r;\n";
11124              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11125              pr "  return r;\n"
11126          | RBool _ ->
11127              pr "  return STREQ (val, \"true\");\n"
11128          | RConstString _
11129          | RConstOptString _ ->
11130              (* Can't return the input string here.  Return a static
11131               * string so we ensure we get a segfault if the caller
11132               * tries to free it.
11133               *)
11134              pr "  return \"static string\";\n"
11135          | RString _ ->
11136              pr "  return strdup (val);\n"
11137          | RStringList _ ->
11138              pr "  char **strs;\n";
11139              pr "  int n, i;\n";
11140              pr "  sscanf (val, \"%%d\", &n);\n";
11141              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11142              pr "  for (i = 0; i < n; ++i) {\n";
11143              pr "    strs[i] = safe_malloc (g, 16);\n";
11144              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11145              pr "  }\n";
11146              pr "  strs[n] = NULL;\n";
11147              pr "  return strs;\n"
11148          | RStruct (_, typ) ->
11149              pr "  struct guestfs_%s *r;\n" typ;
11150              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11151              pr "  return r;\n"
11152          | RStructList (_, typ) ->
11153              pr "  struct guestfs_%s_list *r;\n" typ;
11154              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11155              pr "  sscanf (val, \"%%d\", &r->len);\n";
11156              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11157              pr "  return r;\n"
11158          | RHashtable _ ->
11159              pr "  char **strs;\n";
11160              pr "  int n, i;\n";
11161              pr "  sscanf (val, \"%%d\", &n);\n";
11162              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11163              pr "  for (i = 0; i < n; ++i) {\n";
11164              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11165              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11166              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11167              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11168              pr "  }\n";
11169              pr "  strs[n*2] = NULL;\n";
11170              pr "  return strs;\n"
11171          | RBufferOut _ ->
11172              pr "  return strdup (val);\n"
11173         );
11174         pr "}\n";
11175         pr "\n"
11176       ) else (
11177         pr "/* Test error return. */\n";
11178         generate_prototype ~extern:false ~semicolon:false ~newline:true
11179           ~handle:"g" ~prefix:"guestfs__" name style;
11180         pr "{\n";
11181         pr "  error (g, \"error\");\n";
11182         (match fst style with
11183          | RErr | RInt _ | RInt64 _ | RBool _ ->
11184              pr "  return -1;\n"
11185          | RConstString _ | RConstOptString _
11186          | RString _ | RStringList _ | RStruct _
11187          | RStructList _
11188          | RHashtable _
11189          | RBufferOut _ ->
11190              pr "  return NULL;\n"
11191         );
11192         pr "}\n";
11193         pr "\n"
11194       )
11195   ) tests
11196
11197 and generate_ocaml_bindtests () =
11198   generate_header OCamlStyle GPLv2plus;
11199
11200   pr "\
11201 let () =
11202   let g = Guestfs.create () in
11203 ";
11204
11205   let mkargs args =
11206     String.concat " " (
11207       List.map (
11208         function
11209         | CallString s -> "\"" ^ s ^ "\""
11210         | CallOptString None -> "None"
11211         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11212         | CallStringList xs ->
11213             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11214         | CallInt i when i >= 0 -> string_of_int i
11215         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11216         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11217         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11218         | CallBool b -> string_of_bool b
11219         | CallBuffer s -> sprintf "%S" s
11220       ) args
11221     )
11222   in
11223
11224   generate_lang_bindtests (
11225     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11226   );
11227
11228   pr "print_endline \"EOF\"\n"
11229
11230 and generate_perl_bindtests () =
11231   pr "#!/usr/bin/perl -w\n";
11232   generate_header HashStyle GPLv2plus;
11233
11234   pr "\
11235 use strict;
11236
11237 use Sys::Guestfs;
11238
11239 my $g = Sys::Guestfs->new ();
11240 ";
11241
11242   let mkargs args =
11243     String.concat ", " (
11244       List.map (
11245         function
11246         | CallString s -> "\"" ^ s ^ "\""
11247         | CallOptString None -> "undef"
11248         | CallOptString (Some s) -> sprintf "\"%s\"" s
11249         | CallStringList xs ->
11250             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11251         | CallInt i -> string_of_int i
11252         | CallInt64 i -> Int64.to_string i
11253         | CallBool b -> if b then "1" else "0"
11254         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11255       ) args
11256     )
11257   in
11258
11259   generate_lang_bindtests (
11260     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11261   );
11262
11263   pr "print \"EOF\\n\"\n"
11264
11265 and generate_python_bindtests () =
11266   generate_header HashStyle GPLv2plus;
11267
11268   pr "\
11269 import guestfs
11270
11271 g = guestfs.GuestFS ()
11272 ";
11273
11274   let mkargs args =
11275     String.concat ", " (
11276       List.map (
11277         function
11278         | CallString s -> "\"" ^ s ^ "\""
11279         | CallOptString None -> "None"
11280         | CallOptString (Some s) -> sprintf "\"%s\"" s
11281         | CallStringList xs ->
11282             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11283         | CallInt i -> string_of_int i
11284         | CallInt64 i -> Int64.to_string i
11285         | CallBool b -> if b then "1" else "0"
11286         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11287       ) args
11288     )
11289   in
11290
11291   generate_lang_bindtests (
11292     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11293   );
11294
11295   pr "print \"EOF\"\n"
11296
11297 and generate_ruby_bindtests () =
11298   generate_header HashStyle GPLv2plus;
11299
11300   pr "\
11301 require 'guestfs'
11302
11303 g = Guestfs::create()
11304 ";
11305
11306   let mkargs args =
11307     String.concat ", " (
11308       List.map (
11309         function
11310         | CallString s -> "\"" ^ s ^ "\""
11311         | CallOptString None -> "nil"
11312         | CallOptString (Some s) -> sprintf "\"%s\"" s
11313         | CallStringList xs ->
11314             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11315         | CallInt i -> string_of_int i
11316         | CallInt64 i -> Int64.to_string i
11317         | CallBool b -> string_of_bool b
11318         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11319       ) args
11320     )
11321   in
11322
11323   generate_lang_bindtests (
11324     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11325   );
11326
11327   pr "print \"EOF\\n\"\n"
11328
11329 and generate_java_bindtests () =
11330   generate_header CStyle GPLv2plus;
11331
11332   pr "\
11333 import com.redhat.et.libguestfs.*;
11334
11335 public class Bindtests {
11336     public static void main (String[] argv)
11337     {
11338         try {
11339             GuestFS g = new GuestFS ();
11340 ";
11341
11342   let mkargs args =
11343     String.concat ", " (
11344       List.map (
11345         function
11346         | CallString s -> "\"" ^ s ^ "\""
11347         | CallOptString None -> "null"
11348         | CallOptString (Some s) -> sprintf "\"%s\"" s
11349         | CallStringList xs ->
11350             "new String[]{" ^
11351               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11352         | CallInt i -> string_of_int i
11353         | CallInt64 i -> Int64.to_string i
11354         | CallBool b -> string_of_bool b
11355         | CallBuffer s ->
11356             "new byte[] { " ^ String.concat "," (
11357               map_chars (fun c -> string_of_int (Char.code c)) s
11358             ) ^ " }"
11359       ) args
11360     )
11361   in
11362
11363   generate_lang_bindtests (
11364     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11365   );
11366
11367   pr "
11368             System.out.println (\"EOF\");
11369         }
11370         catch (Exception exn) {
11371             System.err.println (exn);
11372             System.exit (1);
11373         }
11374     }
11375 }
11376 "
11377
11378 and generate_haskell_bindtests () =
11379   generate_header HaskellStyle GPLv2plus;
11380
11381   pr "\
11382 module Bindtests where
11383 import qualified Guestfs
11384
11385 main = do
11386   g <- Guestfs.create
11387 ";
11388
11389   let mkargs args =
11390     String.concat " " (
11391       List.map (
11392         function
11393         | CallString s -> "\"" ^ s ^ "\""
11394         | CallOptString None -> "Nothing"
11395         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11396         | CallStringList xs ->
11397             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11398         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11399         | CallInt i -> string_of_int i
11400         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11401         | CallInt64 i -> Int64.to_string i
11402         | CallBool true -> "True"
11403         | CallBool false -> "False"
11404         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11405       ) args
11406     )
11407   in
11408
11409   generate_lang_bindtests (
11410     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11411   );
11412
11413   pr "  putStrLn \"EOF\"\n"
11414
11415 (* Language-independent bindings tests - we do it this way to
11416  * ensure there is parity in testing bindings across all languages.
11417  *)
11418 and generate_lang_bindtests call =
11419   call "test0" [CallString "abc"; CallOptString (Some "def");
11420                 CallStringList []; CallBool false;
11421                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11422                 CallBuffer "abc\000abc"];
11423   call "test0" [CallString "abc"; CallOptString None;
11424                 CallStringList []; CallBool false;
11425                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11426                 CallBuffer "abc\000abc"];
11427   call "test0" [CallString ""; CallOptString (Some "def");
11428                 CallStringList []; CallBool false;
11429                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11430                 CallBuffer "abc\000abc"];
11431   call "test0" [CallString ""; CallOptString (Some "");
11432                 CallStringList []; CallBool false;
11433                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11434                 CallBuffer "abc\000abc"];
11435   call "test0" [CallString "abc"; CallOptString (Some "def");
11436                 CallStringList ["1"]; CallBool false;
11437                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11438                 CallBuffer "abc\000abc"];
11439   call "test0" [CallString "abc"; CallOptString (Some "def");
11440                 CallStringList ["1"; "2"]; CallBool false;
11441                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11442                 CallBuffer "abc\000abc"];
11443   call "test0" [CallString "abc"; CallOptString (Some "def");
11444                 CallStringList ["1"]; CallBool true;
11445                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11446                 CallBuffer "abc\000abc"];
11447   call "test0" [CallString "abc"; CallOptString (Some "def");
11448                 CallStringList ["1"]; CallBool false;
11449                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11450                 CallBuffer "abc\000abc"];
11451   call "test0" [CallString "abc"; CallOptString (Some "def");
11452                 CallStringList ["1"]; CallBool false;
11453                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11454                 CallBuffer "abc\000abc"];
11455   call "test0" [CallString "abc"; CallOptString (Some "def");
11456                 CallStringList ["1"]; CallBool false;
11457                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11458                 CallBuffer "abc\000abc"];
11459   call "test0" [CallString "abc"; CallOptString (Some "def");
11460                 CallStringList ["1"]; CallBool false;
11461                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11462                 CallBuffer "abc\000abc"];
11463   call "test0" [CallString "abc"; CallOptString (Some "def");
11464                 CallStringList ["1"]; CallBool false;
11465                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11466                 CallBuffer "abc\000abc"];
11467   call "test0" [CallString "abc"; CallOptString (Some "def");
11468                 CallStringList ["1"]; CallBool false;
11469                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11470                 CallBuffer "abc\000abc"]
11471
11472 (* XXX Add here tests of the return and error functions. *)
11473
11474 (* Code to generator bindings for virt-inspector.  Currently only
11475  * implemented for OCaml code (for virt-p2v 2.0).
11476  *)
11477 let rng_input = "inspector/virt-inspector.rng"
11478
11479 (* Read the input file and parse it into internal structures.  This is
11480  * by no means a complete RELAX NG parser, but is just enough to be
11481  * able to parse the specific input file.
11482  *)
11483 type rng =
11484   | Element of string * rng list        (* <element name=name/> *)
11485   | Attribute of string * rng list        (* <attribute name=name/> *)
11486   | Interleave of rng list                (* <interleave/> *)
11487   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11488   | OneOrMore of rng                        (* <oneOrMore/> *)
11489   | Optional of rng                        (* <optional/> *)
11490   | Choice of string list                (* <choice><value/>*</choice> *)
11491   | Value of string                        (* <value>str</value> *)
11492   | Text                                (* <text/> *)
11493
11494 let rec string_of_rng = function
11495   | Element (name, xs) ->
11496       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11497   | Attribute (name, xs) ->
11498       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11499   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11500   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11501   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11502   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11503   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11504   | Value value -> "Value \"" ^ value ^ "\""
11505   | Text -> "Text"
11506
11507 and string_of_rng_list xs =
11508   String.concat ", " (List.map string_of_rng xs)
11509
11510 let rec parse_rng ?defines context = function
11511   | [] -> []
11512   | Xml.Element ("element", ["name", name], children) :: rest ->
11513       Element (name, parse_rng ?defines context children)
11514       :: parse_rng ?defines context rest
11515   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11516       Attribute (name, parse_rng ?defines context children)
11517       :: parse_rng ?defines context rest
11518   | Xml.Element ("interleave", [], children) :: rest ->
11519       Interleave (parse_rng ?defines context children)
11520       :: parse_rng ?defines context rest
11521   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11522       let rng = parse_rng ?defines context [child] in
11523       (match rng with
11524        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11525        | _ ->
11526            failwithf "%s: <zeroOrMore> contains more than one child element"
11527              context
11528       )
11529   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11530       let rng = parse_rng ?defines context [child] in
11531       (match rng with
11532        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11533        | _ ->
11534            failwithf "%s: <oneOrMore> contains more than one child element"
11535              context
11536       )
11537   | Xml.Element ("optional", [], [child]) :: rest ->
11538       let rng = parse_rng ?defines context [child] in
11539       (match rng with
11540        | [child] -> Optional child :: parse_rng ?defines context rest
11541        | _ ->
11542            failwithf "%s: <optional> contains more than one child element"
11543              context
11544       )
11545   | Xml.Element ("choice", [], children) :: rest ->
11546       let values = List.map (
11547         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11548         | _ ->
11549             failwithf "%s: can't handle anything except <value> in <choice>"
11550               context
11551       ) children in
11552       Choice values
11553       :: parse_rng ?defines context rest
11554   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11555       Value value :: parse_rng ?defines context rest
11556   | Xml.Element ("text", [], []) :: rest ->
11557       Text :: parse_rng ?defines context rest
11558   | Xml.Element ("ref", ["name", name], []) :: rest ->
11559       (* Look up the reference.  Because of limitations in this parser,
11560        * we can't handle arbitrarily nested <ref> yet.  You can only
11561        * use <ref> from inside <start>.
11562        *)
11563       (match defines with
11564        | None ->
11565            failwithf "%s: contains <ref>, but no refs are defined yet" context
11566        | Some map ->
11567            let rng = StringMap.find name map in
11568            rng @ parse_rng ?defines context rest
11569       )
11570   | x :: _ ->
11571       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11572
11573 let grammar =
11574   let xml = Xml.parse_file rng_input in
11575   match xml with
11576   | Xml.Element ("grammar", _,
11577                  Xml.Element ("start", _, gram) :: defines) ->
11578       (* The <define/> elements are referenced in the <start> section,
11579        * so build a map of those first.
11580        *)
11581       let defines = List.fold_left (
11582         fun map ->
11583           function Xml.Element ("define", ["name", name], defn) ->
11584             StringMap.add name defn map
11585           | _ ->
11586               failwithf "%s: expected <define name=name/>" rng_input
11587       ) StringMap.empty defines in
11588       let defines = StringMap.mapi parse_rng defines in
11589
11590       (* Parse the <start> clause, passing the defines. *)
11591       parse_rng ~defines "<start>" gram
11592   | _ ->
11593       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11594         rng_input
11595
11596 let name_of_field = function
11597   | Element (name, _) | Attribute (name, _)
11598   | ZeroOrMore (Element (name, _))
11599   | OneOrMore (Element (name, _))
11600   | Optional (Element (name, _)) -> name
11601   | Optional (Attribute (name, _)) -> name
11602   | Text -> (* an unnamed field in an element *)
11603       "data"
11604   | rng ->
11605       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11606
11607 (* At the moment this function only generates OCaml types.  However we
11608  * should parameterize it later so it can generate types/structs in a
11609  * variety of languages.
11610  *)
11611 let generate_types xs =
11612   (* A simple type is one that can be printed out directly, eg.
11613    * "string option".  A complex type is one which has a name and has
11614    * to be defined via another toplevel definition, eg. a struct.
11615    *
11616    * generate_type generates code for either simple or complex types.
11617    * In the simple case, it returns the string ("string option").  In
11618    * the complex case, it returns the name ("mountpoint").  In the
11619    * complex case it has to print out the definition before returning,
11620    * so it should only be called when we are at the beginning of a
11621    * new line (BOL context).
11622    *)
11623   let rec generate_type = function
11624     | Text ->                                (* string *)
11625         "string", true
11626     | Choice values ->                        (* [`val1|`val2|...] *)
11627         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11628     | ZeroOrMore rng ->                        (* <rng> list *)
11629         let t, is_simple = generate_type rng in
11630         t ^ " list (* 0 or more *)", is_simple
11631     | OneOrMore rng ->                        (* <rng> list *)
11632         let t, is_simple = generate_type rng in
11633         t ^ " list (* 1 or more *)", is_simple
11634                                         (* virt-inspector hack: bool *)
11635     | Optional (Attribute (name, [Value "1"])) ->
11636         "bool", true
11637     | Optional rng ->                        (* <rng> list *)
11638         let t, is_simple = generate_type rng in
11639         t ^ " option", is_simple
11640                                         (* type name = { fields ... } *)
11641     | Element (name, fields) when is_attrs_interleave fields ->
11642         generate_type_struct name (get_attrs_interleave fields)
11643     | Element (name, [field])                (* type name = field *)
11644     | Attribute (name, [field]) ->
11645         let t, is_simple = generate_type field in
11646         if is_simple then (t, true)
11647         else (
11648           pr "type %s = %s\n" name t;
11649           name, false
11650         )
11651     | Element (name, fields) ->              (* type name = { fields ... } *)
11652         generate_type_struct name fields
11653     | rng ->
11654         failwithf "generate_type failed at: %s" (string_of_rng rng)
11655
11656   and is_attrs_interleave = function
11657     | [Interleave _] -> true
11658     | Attribute _ :: fields -> is_attrs_interleave fields
11659     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11660     | _ -> false
11661
11662   and get_attrs_interleave = function
11663     | [Interleave fields] -> fields
11664     | ((Attribute _) as field) :: fields
11665     | ((Optional (Attribute _)) as field) :: fields ->
11666         field :: get_attrs_interleave fields
11667     | _ -> assert false
11668
11669   and generate_types xs =
11670     List.iter (fun x -> ignore (generate_type x)) xs
11671
11672   and generate_type_struct name fields =
11673     (* Calculate the types of the fields first.  We have to do this
11674      * before printing anything so we are still in BOL context.
11675      *)
11676     let types = List.map fst (List.map generate_type fields) in
11677
11678     (* Special case of a struct containing just a string and another
11679      * field.  Turn it into an assoc list.
11680      *)
11681     match types with
11682     | ["string"; other] ->
11683         let fname1, fname2 =
11684           match fields with
11685           | [f1; f2] -> name_of_field f1, name_of_field f2
11686           | _ -> assert false in
11687         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11688         name, false
11689
11690     | types ->
11691         pr "type %s = {\n" name;
11692         List.iter (
11693           fun (field, ftype) ->
11694             let fname = name_of_field field in
11695             pr "  %s_%s : %s;\n" name fname ftype
11696         ) (List.combine fields types);
11697         pr "}\n";
11698         (* Return the name of this type, and
11699          * false because it's not a simple type.
11700          *)
11701         name, false
11702   in
11703
11704   generate_types xs
11705
11706 let generate_parsers xs =
11707   (* As for generate_type above, generate_parser makes a parser for
11708    * some type, and returns the name of the parser it has generated.
11709    * Because it (may) need to print something, it should always be
11710    * called in BOL context.
11711    *)
11712   let rec generate_parser = function
11713     | Text ->                                (* string *)
11714         "string_child_or_empty"
11715     | Choice values ->                        (* [`val1|`val2|...] *)
11716         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11717           (String.concat "|"
11718              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11719     | ZeroOrMore rng ->                        (* <rng> list *)
11720         let pa = generate_parser rng in
11721         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11722     | OneOrMore rng ->                        (* <rng> list *)
11723         let pa = generate_parser rng in
11724         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11725                                         (* virt-inspector hack: bool *)
11726     | Optional (Attribute (name, [Value "1"])) ->
11727         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11728     | Optional rng ->                        (* <rng> list *)
11729         let pa = generate_parser rng in
11730         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11731                                         (* type name = { fields ... } *)
11732     | Element (name, fields) when is_attrs_interleave fields ->
11733         generate_parser_struct name (get_attrs_interleave fields)
11734     | Element (name, [field]) ->        (* type name = field *)
11735         let pa = generate_parser field in
11736         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11737         pr "let %s =\n" parser_name;
11738         pr "  %s\n" pa;
11739         pr "let parse_%s = %s\n" name parser_name;
11740         parser_name
11741     | Attribute (name, [field]) ->
11742         let pa = generate_parser field in
11743         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11744         pr "let %s =\n" parser_name;
11745         pr "  %s\n" pa;
11746         pr "let parse_%s = %s\n" name parser_name;
11747         parser_name
11748     | Element (name, fields) ->              (* type name = { fields ... } *)
11749         generate_parser_struct name ([], fields)
11750     | rng ->
11751         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11752
11753   and is_attrs_interleave = function
11754     | [Interleave _] -> true
11755     | Attribute _ :: fields -> is_attrs_interleave fields
11756     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11757     | _ -> false
11758
11759   and get_attrs_interleave = function
11760     | [Interleave fields] -> [], fields
11761     | ((Attribute _) as field) :: fields
11762     | ((Optional (Attribute _)) as field) :: fields ->
11763         let attrs, interleaves = get_attrs_interleave fields in
11764         (field :: attrs), interleaves
11765     | _ -> assert false
11766
11767   and generate_parsers xs =
11768     List.iter (fun x -> ignore (generate_parser x)) xs
11769
11770   and generate_parser_struct name (attrs, interleaves) =
11771     (* Generate parsers for the fields first.  We have to do this
11772      * before printing anything so we are still in BOL context.
11773      *)
11774     let fields = attrs @ interleaves in
11775     let pas = List.map generate_parser fields in
11776
11777     (* Generate an intermediate tuple from all the fields first.
11778      * If the type is just a string + another field, then we will
11779      * return this directly, otherwise it is turned into a record.
11780      *
11781      * RELAX NG note: This code treats <interleave> and plain lists of
11782      * fields the same.  In other words, it doesn't bother enforcing
11783      * any ordering of fields in the XML.
11784      *)
11785     pr "let parse_%s x =\n" name;
11786     pr "  let t = (\n    ";
11787     let comma = ref false in
11788     List.iter (
11789       fun x ->
11790         if !comma then pr ",\n    ";
11791         comma := true;
11792         match x with
11793         | Optional (Attribute (fname, [field])), pa ->
11794             pr "%s x" pa
11795         | Optional (Element (fname, [field])), pa ->
11796             pr "%s (optional_child %S x)" pa fname
11797         | Attribute (fname, [Text]), _ ->
11798             pr "attribute %S x" fname
11799         | (ZeroOrMore _ | OneOrMore _), pa ->
11800             pr "%s x" pa
11801         | Text, pa ->
11802             pr "%s x" pa
11803         | (field, pa) ->
11804             let fname = name_of_field field in
11805             pr "%s (child %S x)" pa fname
11806     ) (List.combine fields pas);
11807     pr "\n  ) in\n";
11808
11809     (match fields with
11810      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11811          pr "  t\n"
11812
11813      | _ ->
11814          pr "  (Obj.magic t : %s)\n" name
11815 (*
11816          List.iter (
11817            function
11818            | (Optional (Attribute (fname, [field])), pa) ->
11819                pr "  %s_%s =\n" name fname;
11820                pr "    %s x;\n" pa
11821            | (Optional (Element (fname, [field])), pa) ->
11822                pr "  %s_%s =\n" name fname;
11823                pr "    (let x = optional_child %S x in\n" fname;
11824                pr "     %s x);\n" pa
11825            | (field, pa) ->
11826                let fname = name_of_field field in
11827                pr "  %s_%s =\n" name fname;
11828                pr "    (let x = child %S x in\n" fname;
11829                pr "     %s x);\n" pa
11830          ) (List.combine fields pas);
11831          pr "}\n"
11832 *)
11833     );
11834     sprintf "parse_%s" name
11835   in
11836
11837   generate_parsers xs
11838
11839 (* Generate ocaml/guestfs_inspector.mli. *)
11840 let generate_ocaml_inspector_mli () =
11841   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11842
11843   pr "\
11844 (** This is an OCaml language binding to the external [virt-inspector]
11845     program.
11846
11847     For more information, please read the man page [virt-inspector(1)].
11848 *)
11849
11850 ";
11851
11852   generate_types grammar;
11853   pr "(** The nested information returned from the {!inspect} function. *)\n";
11854   pr "\n";
11855
11856   pr "\
11857 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11858 (** To inspect a libvirt domain called [name], pass a singleton
11859     list: [inspect [name]].  When using libvirt only, you may
11860     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11861
11862     To inspect a disk image or images, pass a list of the filenames
11863     of the disk images: [inspect filenames]
11864
11865     This function inspects the given guest or disk images and
11866     returns a list of operating system(s) found and a large amount
11867     of information about them.  In the vast majority of cases,
11868     a virtual machine only contains a single operating system.
11869
11870     If the optional [~xml] parameter is given, then this function
11871     skips running the external virt-inspector program and just
11872     parses the given XML directly (which is expected to be XML
11873     produced from a previous run of virt-inspector).  The list of
11874     names and connect URI are ignored in this case.
11875
11876     This function can throw a wide variety of exceptions, for example
11877     if the external virt-inspector program cannot be found, or if
11878     it doesn't generate valid XML.
11879 *)
11880 "
11881
11882 (* Generate ocaml/guestfs_inspector.ml. *)
11883 let generate_ocaml_inspector_ml () =
11884   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11885
11886   pr "open Unix\n";
11887   pr "\n";
11888
11889   generate_types grammar;
11890   pr "\n";
11891
11892   pr "\
11893 (* Misc functions which are used by the parser code below. *)
11894 let first_child = function
11895   | Xml.Element (_, _, c::_) -> c
11896   | Xml.Element (name, _, []) ->
11897       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11898   | Xml.PCData str ->
11899       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11900
11901 let string_child_or_empty = function
11902   | Xml.Element (_, _, [Xml.PCData s]) -> s
11903   | Xml.Element (_, _, []) -> \"\"
11904   | Xml.Element (x, _, _) ->
11905       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11906                 x ^ \" instead\")
11907   | Xml.PCData str ->
11908       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11909
11910 let optional_child name xml =
11911   let children = Xml.children xml in
11912   try
11913     Some (List.find (function
11914                      | Xml.Element (n, _, _) when n = name -> true
11915                      | _ -> false) children)
11916   with
11917     Not_found -> None
11918
11919 let child name xml =
11920   match optional_child name xml with
11921   | Some c -> c
11922   | None ->
11923       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11924
11925 let attribute name xml =
11926   try Xml.attrib xml name
11927   with Xml.No_attribute _ ->
11928     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11929
11930 ";
11931
11932   generate_parsers grammar;
11933   pr "\n";
11934
11935   pr "\
11936 (* Run external virt-inspector, then use parser to parse the XML. *)
11937 let inspect ?connect ?xml names =
11938   let xml =
11939     match xml with
11940     | None ->
11941         if names = [] then invalid_arg \"inspect: no names given\";
11942         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11943           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11944           names in
11945         let cmd = List.map Filename.quote cmd in
11946         let cmd = String.concat \" \" cmd in
11947         let chan = open_process_in cmd in
11948         let xml = Xml.parse_in chan in
11949         (match close_process_in chan with
11950          | WEXITED 0 -> ()
11951          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11952          | WSIGNALED i | WSTOPPED i ->
11953              failwith (\"external virt-inspector command died or stopped on sig \" ^
11954                        string_of_int i)
11955         );
11956         xml
11957     | Some doc ->
11958         Xml.parse_string doc in
11959   parse_operatingsystems xml
11960 "
11961
11962 and generate_max_proc_nr () =
11963   pr "%d\n" max_proc_nr
11964
11965 let output_to filename k =
11966   let filename_new = filename ^ ".new" in
11967   chan := open_out filename_new;
11968   k ();
11969   close_out !chan;
11970   chan := Pervasives.stdout;
11971
11972   (* Is the new file different from the current file? *)
11973   if Sys.file_exists filename && files_equal filename filename_new then
11974     unlink filename_new                 (* same, so skip it *)
11975   else (
11976     (* different, overwrite old one *)
11977     (try chmod filename 0o644 with Unix_error _ -> ());
11978     rename filename_new filename;
11979     chmod filename 0o444;
11980     printf "written %s\n%!" filename;
11981   )
11982
11983 let perror msg = function
11984   | Unix_error (err, _, _) ->
11985       eprintf "%s: %s\n" msg (error_message err)
11986   | exn ->
11987       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11988
11989 (* Main program. *)
11990 let () =
11991   let lock_fd =
11992     try openfile "HACKING" [O_RDWR] 0
11993     with
11994     | Unix_error (ENOENT, _, _) ->
11995         eprintf "\
11996 You are probably running this from the wrong directory.
11997 Run it from the top source directory using the command
11998   src/generator.ml
11999 ";
12000         exit 1
12001     | exn ->
12002         perror "open: HACKING" exn;
12003         exit 1 in
12004
12005   (* Acquire a lock so parallel builds won't try to run the generator
12006    * twice at the same time.  Subsequent builds will wait for the first
12007    * one to finish.  Note the lock is released implicitly when the
12008    * program exits.
12009    *)
12010   (try lockf lock_fd F_LOCK 1
12011    with exn ->
12012      perror "lock: HACKING" exn;
12013      exit 1);
12014
12015   check_functions ();
12016
12017   output_to "src/guestfs_protocol.x" generate_xdr;
12018   output_to "src/guestfs-structs.h" generate_structs_h;
12019   output_to "src/guestfs-actions.h" generate_actions_h;
12020   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12021   output_to "src/guestfs-actions.c" generate_client_actions;
12022   output_to "src/guestfs-bindtests.c" generate_bindtests;
12023   output_to "src/guestfs-structs.pod" generate_structs_pod;
12024   output_to "src/guestfs-actions.pod" generate_actions_pod;
12025   output_to "src/guestfs-availability.pod" generate_availability_pod;
12026   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12027   output_to "src/libguestfs.syms" generate_linker_script;
12028   output_to "daemon/actions.h" generate_daemon_actions_h;
12029   output_to "daemon/stubs.c" generate_daemon_actions;
12030   output_to "daemon/names.c" generate_daemon_names;
12031   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12032   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12033   output_to "capitests/tests.c" generate_tests;
12034   output_to "fish/cmds.c" generate_fish_cmds;
12035   output_to "fish/completion.c" generate_fish_completion;
12036   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12037   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12038   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12039   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12040   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12041   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12042   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12043   output_to "perl/Guestfs.xs" generate_perl_xs;
12044   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12045   output_to "perl/bindtests.pl" generate_perl_bindtests;
12046   output_to "python/guestfs-py.c" generate_python_c;
12047   output_to "python/guestfs.py" generate_python_py;
12048   output_to "python/bindtests.py" generate_python_bindtests;
12049   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12050   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12051   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12052
12053   List.iter (
12054     fun (typ, jtyp) ->
12055       let cols = cols_of_struct typ in
12056       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12057       output_to filename (generate_java_struct jtyp cols);
12058   ) java_structs;
12059
12060   output_to "java/Makefile.inc" generate_java_makefile_inc;
12061   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12062   output_to "java/Bindtests.java" generate_java_bindtests;
12063   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12064   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12065   output_to "csharp/Libguestfs.cs" generate_csharp;
12066
12067   (* Always generate this file last, and unconditionally.  It's used
12068    * by the Makefile to know when we must re-run the generator.
12069    *)
12070   let chan = open_out "src/stamp-generator" in
12071   fprintf chan "1\n";
12072   close_out chan;
12073
12074   printf "generated %d lines of code\n" !lines